Developer Documentation

REST API Integration

A guide for developers connecting a custom e-commerce backend to Olemhe.

Overview

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.

What you'll need

  • A public HTTPS URL for your store backend (the "Store URL").
  • A long-lived API key your server will accept as a bearer token.
  • Optional: any extra headers your auth stack requires (e.g. X-Tenant-Id).
  • Three endpoint paths. Defaults if you don't override them: /api/products, /api/orders, /api/checkout.

Authentication

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.

What Olemhe sends

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

HeaderValue
AuthorizationBearer <your-api-key>
Content-Typeapplication/json
Acceptapplication/json
Custom headersWhatever 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

  • All requests originate from our Vercel-hosted infrastructure. If you need to allowlist by IP, email support and we'll share the current egress ranges.
  • TLS 1.2+ only. Olemhe will refuse to send orders to a non-HTTPS URL.
  • Default request timeout: 15 seconds. Respond within that window or the customer sees an error.
  • We retry offline-looking failures (connection refused, timeout, 502/503/504) up to 3 times with backoff via the webhook queue. Application-level 4xx responses are not retried.
  • Because 5xx can be retried, treat POST {orders_endpoint} as idempotent where you can — e.g. by deduping on the customer.phone + items hash within a short window.

Sandbox & support

  • For a sandbox tenant and test credentials, email support@theoleai.com with your merchant ID.
  • When reporting a bug, include the approximate timestamp (UTC) and the 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.

  • Query param: ?search=<text> when the customer names a specific product. You may ignore it and return everything — Olemhe filters client-side.
  • Response: an array of products, either at the top level or wrapped under one of these keys: data, products, items.

Product fields Olemhe reads

FieldTypeNotes
idstring / numberRequired.
name or titlestringRequired.
descriptionstringTruncated to 200 chars.
price or regular_pricenumberIn the store's base currency.
skustring
stock_status"in_stock" / "out_of_stock" / "on_backorder"
in_stockbooleanAlternative to stock_status.
quantitynumber
imagesstring[] or {url|src}[]Public image URLs.
variants or attributes{name, options|values: string[]}[]e.g. {name:"Size", options:["S","M","L"]}.
categoriesstring[] or {name}[]
url or permalinkstringSurfaced in-chat when useful.
active / statusboolean / "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.
  • Return a 4xx or 5xx on failure — Olemhe will surface the error to the customer and log it for the merchant.

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.

Configuring in Olemhe

  1. Open the DashboardIntegrations page.
  2. Click Add integration and select REST API.
  3. Paste your Store URL and API key. Add Custom Headers if your auth needs them.
  4. Override the default endpoint paths if yours differ from the defaults above.
  5. Save. Use the Test connection button to verify — it hits your products endpoint and should report a product count.

Testing your endpoints

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"}'

Security

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.

Troubleshooting

  • 401 Unauthorized in the logs. API key mismatch, or your auth stack expects an extra header. Add it under Custom Headers.
  • Test connection returns 0 products. Your response shape isn't recognised. Return a top-level array, or wrap it under data, products, or items.
  • Order succeeds but the customer never pays. The order-create response is missing payment_url, or the URL isn't HTTPS. Olemhe will not send a plain-HTTP checkout link to a customer.
  • Stock levels never update. Olemhe does not maintain inventory locally for REST integrations. Return a fresh 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.