Qubit API v1

Integrating your system

An online store end to end: confirm an order, post an event, hear the reply.

This page walks one integration end to end - an online store - so you can see how the pieces fit before reading any of them in depth. A POS, an ERP, a booking engine or a helpdesk follows the same loop: identify the customer, message them, tell the platform what happened, and hear back in realtime.

Before you start

An administrator has created an application for your store in Settings → Developer with the scopes below and the store's WhatsApp number on its allow-list, and handed you an API key. Every request in this guide sends it as Authorization: Bearer … and every POST sends an Idempotency-Key (why).

Step Scope Endpoint
Create the customer contacts.write POST /contacts
Confirm the order templates.send (or messages.send for text) POST /messages
Post an event events.send POST /events
Receive replies and receipts webhooks.receive your endpoint
Read history messages.read, contacts.read GET /conversations, GET /contacts

Step 1 - Identify the customer

You never need the platform's ids to start. A message is addressed by channel and handle - whatsapp and a phone number in E.164, email and an address - and if the platform has never seen that handle, the first message creates the contact and the conversation for you.

Create the contact explicitly when you want a name, tags and your own reference on it before any message goes out - on sign-up, or at checkout:

Request
Try it - send it and see the response

This is a real request. A test key still acts on its workspace: a send goes out on the connection named in the body. Point it at your own number.

Response 201
{
    "data": {
        "id": "01997f2a-6f90-7f41-8e7d-5c3f20b1ad44",
        "first_name": "Rahul",
        "last_name": "Verma",
        "name": "Rahul Verma",
        "company": "Verma Traders",
        "job_title": null,
        "email": "rahul@example.com",
        "phone": "919876543210",
        "country": null,
        "city": null,
        "language": null,
        "lifecycle_stage": "customer",
        "opted_out": false,
        "marketing_opted_out": false,
        "identities": [],
        "tags": [
            "wholesale",
            "delhi"
        ],
        "last_activity_at": null,
        "created_at": "2026-09-15T10:00:00+05:30"
    }
}

Keep the returned id against your customer record. A contact needs at least one of email, phone or an identity; a handle that already belongs to a contact is refused with 422 validation_failed and the owner's id in details.contact_id - use that id rather than creating a duplicate. custom_fields keys must match fields the business has defined under Settings → CRM; store_customer_id is the kind of thing to put there.

Step 2 - Send the order confirmation

On WhatsApp a business may only start a conversation with an approved template; free text is allowed once the customer has written to you in the last 24 hours. Telegram, email and web chat accept text at any time. So the store confirms an order with a template:

Request
Try it - send it and see the response

This is a real request. A test key still acts on its workspace: a send goes out on the connection named in the body. Point it at your own number.

Response 202
{
    "data": {
        "message_id": "01997f2a-4d7e-7d2f-8c5b-3a1d0e9f8b22",
        "conversation_id": "01997f2a-3c6d-7c1e-9b4a-2f0c9d8e7a11",
        "external_reference": "INV-10025",
        "status": "queued"
    }
}

202 means queued - the customer does not have it yet. Store message_id, and put your order number in external_reference: every webhook about this message carries it back, so you can match a delivery receipt to an order without a lookup. Which templates exist, with their variable slots, comes from GET /templates (Sending messages).

Step 3 - Tell the platform what happened

Post a named event whenever something worth reacting to happens in your store - paid, shipped, delivered, refunded, cart abandoned. Events send nothing by themselves; they are what the business's automations listen for (Automations):

Request
Try it - send it and see the response

This is a real request. A test key still acts on its workspace: a send goes out on the connection named in the body. Point it at your own number.

Response 202
{
    "data": {
        "event": "order.paid",
        "contact_id": "01997f2a-6f90-7f41-8e7d-5c3f20b1ad44",
        "workflows_matched": 1
    }
}

Name the customer by contact_id or by an identity you know. Everything under data reaches the workflow as {{data.order_id}}-style placeholders, so a "Send message" action can say "Order {{data.order_id}} has shipped with {{data.courier}} - track it at {{data.tracking_url}}" without you sending the message yourself. workflows_matched tells you whether anything is listening.

Step 4 - Hear the customer back

Register a webhook endpoint under your application (Webhooks) subscribed to message.received, message.delivered and message.failed. When the customer replies "Can I change the delivery address?", your endpoint receives within a second or two:

{
  "id": "6d2c0a84-1f2e-4b3c-9d4e-5f6a7b8c9d0e",
  "type": "message.received",
  "created_at": "2026-09-17T09:12:44+00:00",
  "data": {
    "message": {
      "id": "d3a0…", "direction": "inbound", "type": "text", "status": "delivered",
      "body": "Can I change the delivery address?",
      "conversation_id": "9c0e…", "contact_id": "b7f2…", "connection_id": "e51a…",
      "attachments": [], "received_at": "2026-09-17T09:12:43+00:00"
    }
  }
}

Verify the signature, answer 200, then act: reply from your own system with POST /messages (type: "text" is fine now - the customer just wrote to you), or leave it to the agents in the inbox. Either way every message and every status lands on the same webhook, so your order page can show "Sent · Delivered · Read" from the receipts alone.

Subscribe to conversation.status_changed and conversation.assigned as well if your system tracks whether a customer's question is open or who is handling it, and to lead.stage_changed if the store feeds a sales pipeline.

Step 5 - Keep the CRM in step

Optional, and usually a nightly job:

Going live

  1. The live key (omni_live_…) is in your secret manager, never in code or a browser.
  2. Every POST sends an Idempotency-Key; retries are safe.
  3. The webhook endpoint is https://, verifies the signature and the timestamp, dedupes on X-Webhook-ID, and answers within 10 seconds before doing the work.
  4. Send test on the endpoint page delivered a webhook.test you verified.
  5. The templates you send are is_sendable: true in GET /templates.
  6. Your events have published workflows listening (workflows_matched > 0).
  7. Retry-After is honoured on a 429, and X-Request-ID is in your logs.
Base URL https://communication-api.artofluminaire.com Every response carries X-Request-ID; quote it when you write to support.