Prices in INR, before GST.
Marketiism OS

Developers

Connect your own code to Marketiism OS.

Use the REST API to read and write contacts, deals and bookings and to read orders, products and invoices. Webhooks send a signed HTTPS request to your server when something happens in your workspace, such as a paid order or a new booking. Both are on the Growth and Agency plans.

Authentication

Every request carries a workspace API key as a Bearer token. The key decides the workspace; you never pass a workspace id. Keys look like mos_<prefix>_<secret>.

  1. Sign in and open Settings, then API keys. Owners and admins can create keys.
  2. Give the key a name and choose its scopes. The full key is shown once, so copy it then.
  3. Send it on every request in the Authorization header, over HTTPS only.
  4. Revoke a key from the same page if it leaks. Requests with it fail straight away.

Base URL

https://marketiism.online/api/v1/

Example request

curl https://marketiism.online/api/v1/contacts/?limit=20 \
  -H "Authorization: Bearer mos_xxxx_your_secret"

Scopes

Each key can be limited to the resources it needs. A write scope includes read. A key with no scopes set uses its read or read-write access for every resource. A missing scope returns 403.

Scopes
ResourceRead scopeWrite scope
Contactscontacts:readcontacts:write
Tagstags:readRead only
Dealsdeals:readdeals:write
Ordersorders:readRead only
Productsproducts:readRead only
Bookingsbookings:readbookings:write
Invoicesinvoices:readRead only

Pagination

Lists use cursors. Pass limit (1 to 100, default 50) and follow the next link until has_more is false. Don't build cursors yourself; they are opaque.

{
  "data": [ { "id": 812, "name": "Pooja Kulkarni", ... } ],
  "next": "https://marketiism.online/api/v1/contacts/?cursor=cD0yMDI2...",
  "previous": null,
  "has_more": true
}

Errors

Errors share one JSON shape. Use the code field in your logic; the message is for people.

{
  "error": {
    "code": "permission_denied",
    "message": "Missing scope deals:write.",
    "details": null
  }
}
Errors
CodeHTTPWhen
invalid400A field is missing or wrong. details names the fields.
not_authenticated401No Authorization header.
authentication_failed401The key is wrong or revoked.
plan_limit_reached402Your plan limit is reached, for example the contact limit.
permission_denied403The key doesn't have the scope for this call.
not_found404No such record in this workspace.
method_not_allowed405That method isn't supported on this path.
booking_unavailable409The booking can't be made, for example the slot was just taken.
throttled429Too many requests. Wait for the seconds in Retry-After.

Rate limits

Each key can make 120 requests every 60 seconds. Every response has X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers. Over the limit you get 429 with Retry-After. Too many wrong keys from one IP address in a minute also get 429.

Resources and endpoints

Paths are relative to the base URL. Money is in paise (integer), times are ISO 8601 with time zone.

The full OpenAPI 3.1 document is at https://marketiism.online/api/v1/openapi.json. Import it into Postman or generate a client from it.

Contacts

Contacts
MethodPathWhat it doesScope
GET /contacts/List contactscontacts:read
POST /contacts/Createcontacts:write
GET /contacts/{id}/Get onecontacts:read
PATCH /contacts/{id}/Updatecontacts:write
DELETE /contacts/{id}/Deletecontacts:write
POST /contacts/{id}/tags/Add a tagcontacts:write
DELETE /contacts/{id}/tags/{tag}/Remove a tagcontacts:write

Deals

Deals
MethodPathWhat it doesScope
GET /deals/List dealsdeals:read
POST /deals/Createdeals:write
GET /deals/{id}/Get onedeals:read
PATCH /deals/{id}/Updatedeals:write
DELETE /deals/{id}/Deletedeals:write

Pipelines

Pipelines
MethodPathWhat it doesScope
GET /pipelines/List pipelinesdeals:read
GET /pipelines/{id}/Get onedeals:read

Products

Products
MethodPathWhat it doesScope
GET /products/List productsproducts:read
GET /products/{id}/Get oneproducts:read

Orders

Orders
MethodPathWhat it doesScope
GET /orders/List ordersorders:read
GET /orders/{id}/Get oneorders:read

Booking services

Booking services
MethodPathWhat it doesScope
GET /booking-services/List booking-servicesbookings:read
GET /booking-services/{id}/Get onebookings:read

Bookings

Bookings
MethodPathWhat it doesScope
GET /bookings/List bookingsbookings:read
POST /bookings/Createbookings:write
GET /bookings/{id}/Get onebookings:read
POST /bookings/{id}/cancel/Cancel a bookingbookings:write

Invoices

Invoices
MethodPathWhat it doesScope
GET /invoices/List invoicesinvoices:read
GET /invoices/{id}/Get oneinvoices:read

Tags

Tags
MethodPathWhat it doesScope
GET /tags/List tags in usetags:read

Webhooks

Add an endpoint in the console under Settings, then Webhooks: an https URL on port 443 and the events you want. The signing secret is shown once when you create the endpoint or rotate it. You can send a test ping and see every delivery with its response code.

Every delivery is a POST with a JSON body like this. data has the same shape as the API.

{
  "id": "6f1c2b9e-4d1a-4b8e-9a51-0c7d2f3e8a10",
  "event": "booking.created",
  "created": 1791100800,
  "workspace": "sharma-dental",
  "data": { "id": 3141, "status": "confirmed", ... }
}

Headers

Headers
HeaderWhat it holds
X-Marketiism-Signaturet=<unix time>,v1=<hex HMAC-SHA256>. See the steps below.
X-Marketiism-EventThe event name, for example order.paid.
X-Marketiism-DeliveryUnique id of this event (the id in the body). Store it to skip duplicates.

Events (22)

Events
EventSent when
contact.createdA contact was created (form, import, API, console).
contact.tag_addedA tag was added to a contact.
contact.tag_removedA tag was removed from a contact.
form.submittedAn opt-in form was submitted.
deal.createdA deal was created.
deal.stage_changedA deal moved to another stage.
order.paidAn order was paid (confirmed by the payment gateway webhook).
booking.createdA booking was made.
booking.confirmedA prepaid booking was confirmed after payment.
booking.cancelledA booking was cancelled.
booking.rescheduledA booking moved to a new time (data.old_start).
booking.completedA booking was marked completed.
booking.no_showA booking was marked no-show.
subscription.createdA subscription was created.
subscription.activatedA subscription became active.
subscription.cancelledA subscription was cancelled.
subscription.pausedA subscription was paused.
subscription.resumedA subscription was resumed.
subscription.past_dueA renewal payment failed (dunning started).
subscription.chargedA renewal was charged (data.order).
invoice.createdA tax invoice was issued (after an order is paid).
credit_note.createdA credit note was issued (refund).

Verify the signature

  1. Read the raw request body as bytes, before any JSON parsing.
  2. Split the X-Marketiism-Signature header on commas into t and v1.
  3. Reject the request if t is more than 5 minutes away from your clock.
  4. Compute HMAC-SHA256 with your endpoint secret over t, a full stop, and the raw body.
  5. Compare the hex result with v1 using a constant-time comparison. Reject on mismatch.
  6. Reply with any 2xx within 5 seconds, then do the slow work in the background.
import hashlib, hmac, time


def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
    try:
        parts = dict(p.split("=", 1) for p in header.split(","))
        ts = int(parts["t"])
    except (ValueError, KeyError):
        return False
    if abs(time.time() - ts) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))


# Django: verify(SECRET, request.headers.get("X-Marketiism-Signature", ""), request.body)

Retries and auto-disable

A delivery that doesn't get a 2xx in 5 seconds is retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, so 6 attempts in all. Redirects are not followed. After 10 failed attempts in a row the endpoint is turned off and workspace owners are notified. Fix it and turn it back on from the console. Deliveries can arrive more than once or out of order, so use the delivery id and the created time.

Try it on your own business for two weeks.

14 days free, no card. If you get stuck setting up WhatsApp, we'll get on a call and do it with you.