Developer Documentation
A guide for developers connecting a custom e-commerce backend to Olemhe.
Olemhe's AI agent sells on your behalf over Facebook Messenger, Instagram DM, and WhatsApp. To serve customers it needs to (a) list your products with live stock, (b) place orders on your system, and (c) return a payment URL the customer can pay at. You expose three HTTP endpoints on your store backend and Olemhe calls them with a bearer token. That's the whole contract.
Already on Shopify or WooCommerce? Use the dedicated integration for that platform instead — the REST integration is only needed for custom or in-house backends.
X-Tenant-Id)./api/products, /api/orders, /api/checkout.Every request Olemhe sends includes:
Authorization: Bearer <your-api-key> Content-Type: application/json
Plus any key/value pairs you added under Custom Headers on the integrations page. Reject requests that don't carry a valid bearer token.
For reference — and for anything you'll want to log, allowlist, or correlate — here is the full shape of an outbound call from Olemhe to your backend.
Headers
| Header | Value |
|---|---|
Authorization | Bearer <your-api-key> |
Content-Type | application/json |
Accept | application/json |
| Custom headers | Whatever you configured in the dashboard (merged verbatim). |
Body (POST only)
JSON-encoded. Order creation always includes "source": "olemhe" at the top level (with "legacy_source": "olechat" kept during the rename deprecation window) so you can distinguish Olemhe-originated traffic from other integrations. See the endpoint sections below for the full payload shape.
Network
POST {orders_endpoint} as idempotent where you can — e.g. by deduping on the customer.phone + items hash within a short window.Sandbox & support
customer.phone from the request body — that's enough for us to find the conversation in our logs.GET {products_endpoint}List and search products. Olemhe calls this when the customer asks what you sell.
?search=<text> when the customer names a specific product. You may ignore it and return everything — Olemhe filters client-side.data, products, items.Product fields Olemhe reads
| Field | Type | Notes |
|---|---|---|
id | string / number | Required. |
name or title | string | Required. |
description | string | Truncated to 200 chars. |
price or regular_price | number | In the store's base currency. |
sku | string | |
stock_status | "in_stock" / "out_of_stock" / "on_backorder" | |
in_stock | boolean | Alternative to stock_status. |
quantity | number | |
images | string[] or {url|src}[] | Public image URLs. |
variants or attributes | {name, options|values: string[]}[] | e.g. {name:"Size", options:["S","M","L"]}. |
categories | string[] or {name}[] | |
url or permalink | string | Surfaced in-chat when useful. |
active / status | boolean / "inactive" | Inactive products are hidden from customers. |
GET {products_endpoint}/{id}Fetch a single product. Same field shape as the list endpoint. Either return the product object directly, or wrap it as { "product": { ... } }.
POST {orders_endpoint}Place a new order once the customer confirms.
Request body
{
"source": "olemhe",
"legacy_source": "olechat",
"customer": {
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+2348012345678"
},
"shipping_address": {
"line1": "12 Allen Avenue",
"line2": "Apt 4",
"city": "Ikeja",
"state": "Lagos",
"postal_code": "100271",
"country": "NG"
},
"billing_address": { /* same shape as shipping_address */ },
"items": [
{
"product_id": "123",
"product_name": "Cotton T-Shirt",
"quantity": 2,
"price": 4500,
"currency": "NGN",
"selected_variants": { "Size": "M", "Color": "Blue" },
"variant_sku": "TSH-M-BLUE"
}
],
"currency": "NGN"
}Response (HTTP 200 or 201)
{
"id": "order_abc123",
"payment_url": "https://pay.yourstore.com/abc123"
}order_id is accepted as a synonym for id.checkout_url is accepted as a synonym for payment_url.POST {checkout_endpoint} (optional)If your platform generates a fresh checkout URL separately from order creation, configure this path. Olemhe POSTs the same body as the order-create call and expects { "url": "..." } (or payment_url / checkout_url). Leave blank and Olemhe will use the payment_url returned by your orders endpoint.
Once the integration is saved, you can drive test requests from the dashboard at Integrations → Sandbox test. It sends a real request from Olemhe's servers to your backend and shows the raw request, raw response, latency, and a diagnostics panel that flags missing fields (id, payment_url, etc.). The order-create action uses a fixed payload tagged "sandbox": true and a dummy customer — wire your backend to ignore or soft-delete any order whose body carries that flag.
You can also sanity-check your backend independently with curl:
curl -H "Authorization: Bearer YOUR_KEY" \
https://your.store/api/products
curl -H "Authorization: Bearer YOUR_KEY" \
https://your.store/api/products/123
curl -X POST https://your.store/api/orders \
-H "Authorization: Bearer YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"olemhe","customer":{...},"items":[...],"currency":"NGN"}'Olemhe stores your API key encrypted at rest with AES-256-GCM. The key is only decrypted server-side at the moment of an outbound call to your endpoint, and never exposed to the browser or to Olemhe support staff.
To rotate the key, paste the new value in the dashboard — saving invalidates the old one immediately. Your backend should never log the Authorization header.
data, products, or items.payment_url, or the URL isn't HTTPS. Olemhe will not send a plain-HTTP checkout link to a customer.stock_status (or in_stock) on every list call.Need help? Email support@theoleai.com with your merchant ID and a sample response payload and we'll debug it with you.