cognichat.
Get keys
Reference

Commerce API

The complete reference for building on the CogniChat Commerce API. Authentication, request bodies, responses, and copy-paste examples in your language. Pick a language in the top bar and it applies to every example.

Introduction

The CogniChat Commerce API is a headless REST API for building your own storefront, app, or integration on top of a CogniChat workspace. It exposes the same catalog, cart, checkout, bookings, customers, and order data that power the hosted store and the WhatsApp agent.

Every request is authenticated with a workspace API key, scoped to that one workspace, and rate limited per key. All responses are JSON. The API is versioned in the path; this document describes v1.

Base URL

text
https://cognichat-api.vendyi.com/api/public/v1

Conventions

Detail
ProtocolHTTPS only. Requests over plain HTTP are refused.
Content typeSend and receive application/json. Send Content-Type: application/json on any request with a body.
MoneyEvery amount is an integer in the smallest currency unit (e.g. cents / pesewas) named *_cents. Never a float.
Money-blindYour client never sends prices. Send ids + quantities; the server prices every line against the live catalog and returns a pay link.
TimeTimestamps are ISO-8601 UTC strings (e.g. 2026-07-08T14:20:00Z).
IdsOrder and cart handles in URLs are opaque tokens, not guessable sequential ids.
The API is available on the Business plan. Create keys in your dashboard under Developers, then come back here.

Authentication

Authenticate every request with a workspace API key. Send it either as a Bearer token or in the X-Api-Key header — pick one, they are equivalent.

bash
curl "https://cognichat-api.vendyi.com/api/public/v1/catalog/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"

# ...or, equivalently:
curl "https://cognichat-api.vendyi.com/api/public/v1/catalog/" \
  -H "X-Api-Key: pk_live_YOUR_KEY"

Two kinds of key

KeyPrefixUse it inCan access
Publishablepk_live_Browser / client codeCatalog, services, cart, checkout, order status
Secretsk_live_Server-side onlyEverything a publishable key can, plus customer records and webhook configuration
Never put a secret (sk_) key in a browser, mobile app, or any client a user can inspect. If a key leaks, revoke it in the dashboard and mint a new one — keys are shown in full exactly once, at creation.

How keys are handled

Keys are stored only as a SHA-256 hash — a database leak cannot reconstruct a usable key. Revoking a key takes effect immediately; the next request with it returns 401. Each key carries its own rate-limit bucket and usage counters.

FailureStatusMeaning
No key sent401Missing Authorization / X-Api-Key header.
Unknown or revoked key401The key does not resolve to an active credential.
Workspace not on plan403not_entitled — the headless API is not enabled on this workspace's plan.
Publishable key on a secret endpoint403secret_key_required — use an sk_ key.

Errors

Errors use conventional HTTP status codes and a single, stable JSON shape you can branch on. 2xx is success, 4xx is a problem with the request, 5xx is a problem on our side.

json
{
  "error": {
    "code": "not_entitled",
    "message": "The headless commerce API is not enabled on this plan."
  }
}

Always branch on error.code (stable, machine-readable), not error.message (human-readable, may change).

Common codes

StatuscodeWhen
400unknown_item / unknown_serviceA referenced product or service does not exist or is inactive.
400mixed_cartA cart holds a booking; products and bookings can't share a cart.
400stock_changedAn item sold out between preview and checkout.
401Missing, invalid, or revoked API key.
403not_entitledThe workspace's plan does not include the headless API.
403secret_key_requiredEndpoint needs an sk_ key; a pk_ key was used.
404cart_not_found / not_foundThe token or id does not resolve within this workspace.
429Rate limit exceeded. Retry after the Retry-After header.

Rate limits

Rate limits are applied per API key, not per IP, so one integration can never starve another. A well-behaved storefront stays comfortably under the limit.

When you exceed the limit the API returns 429 Too Many Requests with a Retry-After header (seconds). Back off for that long, then retry. Build retries with exponential backoff and jitter for resilience.

Need a higher limit for a launch or a bulk import? Get in touch from your dashboard — limits are configurable per workspace.

Webhooks

Webhooks push commerce events to your server the moment they happen, so you don't have to poll. Register one or more endpoint URLs (with a secret sk_ key), choose which events you want, and we POST a signed JSON body to each.

Event types

EventFires when
order.paidA product order's payment is confirmed.
booking.paidA booking's payment is confirmed.
order.status_changedAn order moves between fulfillment states.
order.review_submittedA customer submits or edits a review for an order (money-blind: rating only, no price).

Verifying the signature

Every delivery carries an X-Webhook-Signature header. It is the HMAC-SHA256 of the raw request body, keyed with your endpoint's signing secret (returned once when you create the endpoint), prefixed with sha256=. Recompute it over the raw body and compare in constant time before trusting the payload.

javascript
import crypto from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected =
    "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader),
    Buffer.from(expected),
  );
}

// Express: use the RAW body, not the parsed JSON, for the HMAC.
app.post("/webhooks/cognichat", express.raw({ type: "*/*" }), (req, res) => {
  const sig = req.headers["x-webhook-signature"];
  if (!verify(req.body, sig, process.env.COGNICHAT_WEBHOOK_SECRET)) {
    return res.sendStatus(400);
  }
  const event = JSON.parse(req.body.toString());
  // handle event.type ...
  res.sendStatus(200);
});

Delivery headers

HeaderValue
X-Webhook-Signaturesha256=<hmac_sha256(secret, raw_body)>
X-Webhook-EventThe event type, e.g. order.paid.
X-Webhook-DeliveryA unique delivery id — dedupe on it.

Retries

Return a 2xx quickly to acknowledge. Any non-2xx or a timeout is retried with backoff (roughly 1m, 5m, 30m, 2h, 6h — up to 6 attempts). Because a delivery may arrive more than once, make your handler idempotent by deduping on X-Webhook-Delivery.

Manage endpoints and read the delivery log in your dashboard under Developers → Webhooks, or via the Webhook endpoints API below.

Catalog

Read the workspace's product catalog. Read-only and customer-safe — cost prices and stock internals are never exposed.

GETpk_ / sk_

Get the catalog

/catalog/

Returns the full category tree, each category carrying its active items with modifiers, portions, and an is_orderable flag (effective, stock-aware availability). The response also carries a store block with the workspace's aggregate customer rating for social proof.

Query parameters
branchinteger

Scope is_orderable availability to a specific branch id.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/catalog/?branch=1" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 200 OK
{
  "categories": [
    {
      "id": 3,
      "parent": null,
      "name": "Mains",
      "brand_tag": "kanzo",
      "sort_order": 0,
      "image_url": "https://.../mains.jpg",
      "items": [
        {
          "id": 42,
          "category": 3,
          "parent": null,
          "variant_name": "",
          "variant_group": "",
          "name": "Jollof & Chicken",
          "description": "Smoky party jollof with grilled chicken.",
          "price_cents": 5500,
          "image_url": "https://.../jollof.jpg",
          "is_drink": false,
          "sort_order": 0,
          "modifiers": [],
          "modifier_groups": [],
          "portions": [],
          "is_orderable": true
        }
      ]
    }
  ],
  "store": {
    "rating": 4.8,
    "review_count": 126,
    "rating_distribution": { "1": 2, "2": 3, "3": 8, "4": 30, "5": 83 }
  }
}

Reviews are per-order, so store is the whole-workspace aggregate (not per-item). It carries only customer-safe numbers (the average rating, the review count, and the star distribution), never cost or internal metrics.

GETpk_ / sk_

Get one product

/catalog/items/{id}/

Returns a single active product by id, with the same customer-safe shape as an item in the catalog tree.

Path parameters
idintegerrequired

The product id.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/catalog/items/42/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 200 OK
{
  "id": 42,
  "category": 3,
  "parent": null,
  "variant_name": "",
  "variant_group": "",
  "name": "Jollof & Chicken",
  "description": "Smoky party jollof with grilled chicken.",
  "price_cents": 5500,
  "image_url": "https://.../jollof.jpg",
  "is_drink": false,
  "sort_order": 0,
  "modifiers": [],
  "modifier_groups": [],
  "portions": [],
  "is_orderable": true
}

Returns 404 with code not_found if the item does not exist or is inactive in this workspace.

Services

Read bookable services (stays and appointments) and their open availability.

GETpk_ / sk_

List services

/services/

Returns the workspace's active bookable services.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/services/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 200 OK
{
  "services": [
    {
      "id": 12,
      "name": "Deluxe Room",
      "description": "Queen bed, garden view.",
      "category": "Rooms",
      "price_cents": 42000,
      "price_label": "per night",
      "duration_minutes": null,
      "booking_mode": "stay",
      "max_capacity": 2
    }
  ]
}
GETpk_ / sk_

Get availability

/services/{id}/availability/

Returns open dates/slots for one service, using the same availability engine as the dashboard and the agent. The window is capped at 60 days.

Path parameters
idintegerrequired

The service id.

Query parameters
startdate

Window start, YYYY-MM-DD. Defaults to today; clamped to today at the earliest.

enddate

Window end, YYYY-MM-DD. Defaults to 30 days out; capped at 60 days from start.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/services/42/availability/?start=2026-07-10&end=2026-07-10" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 200 OK
{
  "service_id": 12,
  "availability": {
    "2026-07-10": { "available": true },
    "2026-07-11": { "available": false }
  }
}

The inner shape depends on booking_mode: a stay returns per-date availability; an appointment returns per-date open time slots.

Cart

A server-side cart addressed by an opaque token. Every price in the preview is computed by the server — the cart is never trusted for money. A cart holds either products or a single booking, never both.

POSTpk_ / sk_

Create a cart

/cart/

Creates an empty cart and returns its opaque token. The cart expires after 7 days.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/cart/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 201 Created
{
  "token": "hV3k...opaque...9Qz",
  "expires_at": "2026-07-15T14:20:00Z"
}
GET/PATCHpk_ / sk_

Get or update a cart

/cart/{token}/

GET returns the cart with a server-priced preview. PATCH sets a coupon code. The priced block reflects live prices; if the cart is currently invalid (e.g. an item sold out) it carries an error instead of a subtotal rather than failing the request.

Path parameters
tokenstringrequired

The cart token.

Body parameters
coupon_codestring

PATCH only. Apply a coupon (max 40 chars). Send empty to clear.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/cart/hV3k9Qz/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 200 OK
{
  "token": "hV3k...9Qz",
  "coupon_code": "",
  "expires_at": "2026-07-15T14:20:00Z",
  "raw_lines": [
    {
      "id": 88,
      "kind": "product",
      "menu_item_id": 42,
      "service_id": null,
      "qty": 2,
      "selection": {}
    }
  ],
  "priced": {
    "kind": "product",
    "lines": [
      { "menu_item_id": 42, "name": "Jollof & Chicken", "qty": 2, "line_total_cents": 11000 }
    ],
    "subtotal_cents": 11000
  }
}
POSTpk_ / sk_

Add a line

/cart/{token}/items/

Adds a product line, or replaces the cart with a single booking line when kind is booking. Adding the same product with the same selection increments its quantity. Returns the re-priced cart.

Path parameters
tokenstringrequired

The cart token.

Body parameters
kindstring

product (default) or booking.

menu_item_idinteger

Product line: the item to add. Required when kind is product.

qtyinteger

Product line: quantity (min 1, default 1).

selectionobject

Product line: chosen modifiers / portion. Echoed to checkout; never a price.

service_idinteger

Booking line: the service to book. Required when kind is booking.

check_in_datedate

Booking (stay): YYYY-MM-DD.

check_out_datedate

Booking (stay): YYYY-MM-DD.

datedate

Booking (appointment): YYYY-MM-DD.

start_timestring

Booking (appointment): HH:MM.

num_guestsinteger

Booking: party size.

special_requestsstring

Booking: free-text note.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/cart/hV3k9Qz/items/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"menu_item_id":42,"qty":2}'
Response · 201 Created
{
  "token": "hV3k...9Qz",
  "coupon_code": "",
  "expires_at": "2026-07-15T14:20:00Z",
  "raw_lines": [
    { "id": 88, "kind": "product", "menu_item_id": 42, "service_id": null, "qty": 2, "selection": {} }
  ],
  "priced": {
    "kind": "product",
    "lines": [ { "menu_item_id": 42, "name": "Jollof & Chicken", "qty": 2, "line_total_cents": 11000 } ],
    "subtotal_cents": 11000
  }
}

Returns 400 with unknown_item / unknown_service for a bad id, or mixed_cart when adding a product to a cart that holds a booking.

PATCH/DELETEpk_ / sk_

Update or remove a line

/cart/{token}/items/{line_id}/

PATCH sets a new quantity (a quantity of 0 removes the line). DELETE removes the line outright. Both return the re-priced cart.

Path parameters
tokenstringrequired

The cart token.

line_idintegerrequired

The raw_lines[].id to change.

Body parameters
qtyinteger

PATCH only. New quantity; 0 removes the line.

Request · cURL
curl -X PATCH "https://cognichat-api.vendyi.com/api/public/v1/cart/hV3k9Qz/items/88/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"qty":3}'
Response · 200 OK
{
  "token": "hV3k...9Qz",
  "coupon_code": "",
  "expires_at": "2026-07-15T14:20:00Z",
  "raw_lines": [
    { "id": 88, "kind": "product", "menu_item_id": 42, "service_id": null, "qty": 3, "selection": {} }
  ],
  "priced": { "kind": "product", "lines": [ ... ], "subtotal_cents": 16500 }
}

Checkout

Turn a cart (or a set of raw lines) into a paid order or booking. Checkout is money-blind: you send ids, quantities, a customer, and an optional coupon; the server prices every cent and returns a pay link. No card data ever touches your integration.

POSTpk_ / sk_

Place an order or booking

/checkout/

Provide either a cart_token (recommended — uses the cart you built) or an inline lines array. The server prices the order, creates it as pending payment, and returns a pay_url to send the customer to, plus an opaque order_token for status lookups.

Body parameters
cart_tokenstring

Check out an existing cart. Its coupon is used unless you override coupon_code.

linesarray

Alternative to cart_token: inline line objects ({kind, menu_item_id, qty} or a booking line).

customerobject

Buyer contact: { name, phone, email }.

fulfillment_typestring

e.g. pickup (default) or delivery.

coupon_codestring

Discount code; overrides the cart's coupon when present.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/checkout/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cart_token":"hV3k...9Qz","customer":{"name":"Ada Owusu","phone":"+233201234567","email":"ada@example.com"},"fulfillment_type":"pickup"}'
Response · 201 Created
{
  "kind": "product",
  "order_number": "1042",
  "order_token": "Xa7...opaque...b2",
  "pay_url": "https://checkout.paystack.com/xxxxxxxx",
  "total_cents": 11000
}

For a booking, kind is booking. Errors return 400 with codes like stock_changed, mixed_cart, delivery_unavailable, or paystack_not_configured.

GETpk_ / sk_

Get order status

/orders/{token}/

Look up an order or booking by its opaque order_token (from checkout). Guessable numbers like order_number are never accepted here.

Path parameters
tokenstringrequired

The order_token returned by checkout.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/orders/hV3k9Qz/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
Response · 200 OK
{
  "kind": "product",
  "order_number": "1042",
  "status": "confirmed",
  "payment_status": "paid",
  "total_cents": 11000
}

Returns 404 with not_found if no order matches the token in this workspace.

POSTpk_ / sk_

Submit a review

/orders/{token}/review/

Submit (or edit) the customer's star rating for an order, resolved by the same opaque order_token you got from checkout. Re-submitting for the same order updates the existing review. Money-blind: a rating and an optional comment only.

Path parameters
tokenstringrequired

The order_token returned by checkout.

Body parameters
ratingintegerrequired

The rating, an integer from 1 (poor) to 5 (great).

commentstring

Optional free-text feedback (trimmed and capped at 500 chars).

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/orders/hV3k9Qz/review/" \
  -H "Authorization: Bearer pk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"rating":5,"comment":"Fast delivery and the jollof was perfect."}'
Response · 201 Created
{
  "ok": true,
  "review": {
    "rating": 5,
    "comment": "Fast delivery and the jollof was perfect.",
    "submitted_at": "2026-07-09T14:20:00Z"
  }
}

Returns 400 with invalid_rating if the rating is missing or outside 1-5, or 404 with not_found if no order matches the token in this workspace. Emits an order.review_submitted webhook.

Customers

Identify and look up the workspace's customers — the same customer records the WhatsApp agent and dashboard use. This is PII and the business's own CRM, so these endpoints require a secret (sk_) key.

POSTsk_

Identify / upsert a customer

/customers/

Resolves a customer by phone (creating one if new), and updates their email and your own external_id when provided. Idempotent by phone.

Body parameters
phonestringrequired

The customer's phone number (E.164, e.g. +233201234567).

namestring

Display name; set on first sight.

emailstring

Email to store.

external_idstring

Your own id for this customer (max 120 chars).

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/customers/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+233201234567","name":"Ada Owusu","email":"ada@example.com","external_id":"cus_1042"}'
Response · 200 OK
{
  "id": 501,
  "name": "Ada Owusu",
  "phone": "+233201234567",
  "email": "ada@example.com",
  "external_id": "cus_1042",
  "total_orders": 3,
  "total_bookings": 0,
  "total_spent_cents": 33000,
  "first_seen_at": "2026-05-01T10:00:00Z",
  "last_seen_at": "2026-07-08T14:20:00Z"
}

Returns 400 with invalid_phone if the number can't be parsed.

GETsk_

Look up a customer

/customers/

Read-only lookup by your external_id or by phone. Never creates a record.

Query parameters
external_idstring

Find by the id you assigned via upsert.

phonestring

Find by phone number.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/customers/?external_id=value&phone=value" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
Response · 200 OK
{
  "id": 501,
  "name": "Ada Owusu",
  "phone": "+233201234567",
  "email": "ada@example.com",
  "external_id": "cus_1042",
  "total_orders": 3,
  "total_bookings": 0,
  "total_spent_cents": 33000,
  "first_seen_at": "2026-05-01T10:00:00Z",
  "last_seen_at": "2026-07-08T14:20:00Z"
}

Returns 404 with not_found when no customer matches.

Webhook endpoints

Register and manage the URLs we POST events to. These require a secret (sk_) key. See the Webhooks concept above for signing and retries.

POSTsk_

Register an endpoint

/webhooks/

Registers a URL to receive events. The signing secret is returned once, in this response only — store it to verify signatures.

Body parameters
urlstringrequired

Your HTTPS endpoint URL.

eventsarray

Subset of event types to receive. Omit or empty to receive all.

descriptionstring

A label for your own reference.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/webhooks/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://yourapp.com/webhooks/cognichat","events":["order.paid","booking.paid"],"description":"Prod fulfillment"}'
Response · 201 Created
{
  "id": 7,
  "url": "https://yourapp.com/webhooks/cognichat",
  "events": ["order.paid", "booking.paid"],
  "description": "Prod fulfillment",
  "active": true,
  "created_at": "2026-07-08T14:20:00Z",
  "secret": "whsec_9s...shown once...Kf"
}

Returns 400 with invalid_events if an event name is not recognized.

GETsk_

List endpoints

/webhooks/

Lists your registered endpoints. The signing secret is never returned again after creation.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/webhooks/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
Response · 200 OK
[
  {
    "id": 7,
    "url": "https://yourapp.com/webhooks/cognichat",
    "events": ["order.paid", "booking.paid"],
    "description": "Prod fulfillment",
    "active": true,
    "created_at": "2026-07-08T14:20:00Z"
  }
]
DELETEsk_

Delete an endpoint

/webhooks/{id}/

Removes an endpoint. We stop delivering to it immediately.

Path parameters
idintegerrequired

The endpoint id.

Request · cURL
curl -X DELETE "https://cognichat-api.vendyi.com/api/public/v1/webhooks/42/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
Response · 204 No Content
(empty body)
POSTsk_

Send a test event

/webhooks/{id}/test/

Enqueues a signed ping delivery so you can verify your receiver end to end.

Path parameters
idintegerrequired

The endpoint id.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/public/v1/webhooks/42/test/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
Response · 202 Accepted
{
  "delivery_id": 331,
  "status": "pending"
}
GETsk_

List deliveries

/webhooks/{id}/deliveries/

Returns the recent delivery log for an endpoint (most recent first), including status, attempts, and the last error.

Path parameters
idintegerrequired

The endpoint id.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/public/v1/webhooks/42/deliveries/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
Response · 200 OK
[
  {
    "id": 331,
    "event_type": "order.paid",
    "status": "delivered",
    "attempts": 1,
    "last_error": "",
    "created_at": "2026-07-08T14:20:00Z",
    "delivered_at": "2026-07-08T14:20:01Z"
  }
]

Notifications

Send WhatsApp notifications programmatically. These endpoints live under a separate base, https://cognichat-api.vendyi.com/api/notify/v1 (a sibling of the Commerce API), and require a secret (`sk_`) key. You send one of your approved templates to a recipient who has opted in; each accepted send draws one message credit from your prepaid balance. A send is idempotent on idempotency_key, so a retry with the same key never sends or charges twice. Delivery is reported back on your notification.sent / notification.delivered / notification.failed webhooks (add notify.* events to a webhook endpoint).

POSTsk_

Send a notification

/messages/

Sends an approved template to one recipient. Returns 402 insufficient_credit when your balance is too low (top up and retry the same key), 403 not_opted_in when the recipient has not opted in for the template's category, 409 template_not_approved / 409 line_paused when the template is not approved or the line is paused for quality, and 422 bad_params when the parameter count does not match the template.

Body parameters
tostringrequired

Recipient phone in E.164 (e.g. +233244000000).

templatestringrequired

The name of one of your APPROVED templates.

paramsstring[]required

Body variables in order; length must equal the template's variable count.

idempotency_keystring

Your unique id for this send. Reusing it returns the original result without re-sending or re-charging. Auto-generated if omitted.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/notify/v1/messages/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"+233244000000","template":"appointment_reminder","params":["Ama","your delivery"],"idempotency_key":"appt-9f2c"}'
Response · 201 Created
{
  "id": 481,
  "status": "sent",
  "to": "+233244000000",
  "template": "appointment_reminder",
  "category": "utility",
  "wamid": "wamid.HBg...",
  "price_pesewas": 15,
  "created_at": "2026-07-10T14:20:00Z"
}
GETsk_

Get a send's status

/messages/{id}/

Returns the current status of a send: sent, delivered, read, or failed. Status updates arrive on your webhook; poll this if you are not using webhooks.

Path parameters
idintegerrequired

The send id returned when you created it.

Request · cURL
curl -X GET "https://cognichat-api.vendyi.com/api/notify/v1/messages/42/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY"
Response · 200 OK
{
  "id": 481,
  "status": "delivered",
  "to": "+233244000000",
  "template": "appointment_reminder",
  "category": "utility",
  "wamid": "wamid.HBg...",
  "price_pesewas": 15,
  "created_at": "2026-07-10T14:20:00Z"
}
POSTsk_

Register a contact opt-in

/contacts/

Records a recipient's consent so you may notify them. Utility/authentication templates need utility_opt_in; marketing templates need marketing_opt_in. Idempotent per phone (creates or updates the contact).

Body parameters
phonestringrequired

Contact phone in E.164 (Ghana-local like 0244000000 is accepted).

namestring

Display name.

utility_opt_inboolean

Consent to transactional/utility notifications. Defaults to true.

marketing_opt_inboolean

Explicit consent to marketing/promotions. Defaults to false.

Request · cURL
curl -X POST "https://cognichat-api.vendyi.com/api/notify/v1/contacts/" \
  -H "Authorization: Bearer sk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone":"+233244000000","name":"Ama Mensah","marketing_opt_in":true}'
Response · 200 OK
{
  "phone": "+233244000000",
  "utility_opt_in": true,
  "marketing_opt_in": true
}