Back to blog
Tutorials

Cashod REST API: Send COD Orders From Any Store, CRM or AI Agent

Ahmed TaziSeptember 21, 20267 min read

How to connect any store, CRM, landing page or AI agent to Cashod with the REST API: per-store keys, scopes, idempotent orders, tracking, stock and rate limits.

Cashod REST API: Send COD Orders From Any Store, CRM or AI Agent

If your orders come from somewhere Cashod does not connect to natively (a custom store, a CRM, a landing page builder, or an AI agent), the Cashod public REST API lets that system create COD orders, read their delivery status and tracking number, and keep products and stock in sync. You create a key per store in Settings → Developers, send POST /v1/orders with your own external_id so retries never create duplicates, and poll the order to follow its delivery. Full guides and an interactive reference are on the developer portal.

API, native integration, webhook or Google Sheets: which one should you use?

Cashod has four ways to receive orders. Pick the lightest one that fits:

  • Native integrations: Shopify, YouCan, WooCommerce, LightFunnels, Storeep and xPage. If your store runs on one of these, connect it from Integrations and skip the code entirely. See the Shopify integration for an example.
  • Inbound webhook: your form or tool sends each new order to a Cashod webhook URL. Good when the sending tool can post an order but you do not need anything back. Details on the webhook integration page.
  • Google Sheets import: for teams that still collect orders in a spreadsheet.
  • Public REST API: when you need a two-way conversation: create orders, read their status and tracking, upsert products by SKU and update stock. This is the option for developers, agencies building for several merchants, and AI agents.

How do API keys and scopes work?

Every request carries a header Authorization: Bearer csk_live_…. Keys are created per store in Settings → Developers. A key is shown once, when you create it, and Cashod stores only a hash of it, so copy it straight into your secret manager.

Each key gets only the scopes it needs:

  • orders:read and orders:write: list, read and create orders.
  • products:read and products:write: list, read and upsert products.
  • stock:write: update the stock of a variant.

A write scope implies the matching read. A landing page that only creates orders needs orders:write and nothing else; a warehouse script that only pushes stock needs stock:write. Agencies should create one key per client store, so revoking one client never breaks another.

How do you create a COD order without duplicates?

Send POST /v1/orders with a JSON body. The main fields are:

  • external_id: your own id for the order (strongly recommended, see below).
  • customer: name and phone. The phone can be in any format; Cashod normalises it.
  • shipping: address, city, and an optional delivery phone.
  • items: each with a quantity and one of sku, product_id or a free-text name (with a unit price) for something not in the catalogue.
  • Optional: total or discount, notes for the confirmation agent, source_name for your own reporting, scheduled_for for a due date, and confirmed.

By default a new order lands in the confirmation queue like any other, so your call center or AI agent confirms it. Set confirmed to true only if you have already confirmed the order with the customer yourself.

Safe retries with external_id

Networks time out. Without idempotency, a retried request can become a second real order sent to a real courier. With external_id, the first call returns 201 (created) and any retry with the same id returns 200 with the order that already exists. Your code can therefore retry freely and tell from the status code alone what happened.

How do you read delivery status and tracking back?

GET /v1/orders/:id returns the order with its shipping status, confirmation status, delivery company, tracking_number, amounts (including advance payment and the COD amount to collect) and timestamps such as shipped and delivered. GET /v1/orders lists orders and can filter by shipping status, confirmation status and creation date, which is how you sync status back into a CRM or show it to your customer.

The API does not send outbound webhooks, so status sync is a polling job: for example, every few minutes list recent orders, or read the ones still in transit, and write any status change to your system.

How do you keep products and stock in sync?

  • POST /v1/products upserts by SKU: the same call creates a product the first time and updates it afterwards. Variants are matched by SKU too; a variant you leave out is left untouched, not deleted.
  • GET /v1/products and GET /v1/products/:id read the catalogue, with filters for SKU, name and active status.
  • PATCH /v1/products/:id/variants/:variantId/stock sets the stock level. It is an absolute count, not a delta, so a retried call cannot double-count.

Pagination, rate limits and errors

  • Pagination: list endpoints use cursors. Each page returns data, has_more and next_cursor; pass the cursor back to get the next page (up to 100 items per page).
  • Rate limit: 120 requests per minute per key. Past that you get HTTP 429; back off and retry.
  • Errors: always the same shape, an error object with a type (such as invalid_request, authentication_error, permission_error, not_found, rate_limit_exceeded or server_error) and a human-readable message. Branch on the type, log the message.

Should an AI agent use the API or the MCP server?

It depends on who the agent works for:

  • Your own agent or automation (a sales bot on your landing page, an order-taking agent in your CRM) should use the REST API with a scoped key. It acts for one store, with exactly the permissions you gave that key. The OpenAPI spec at https://api.cashod.ma/api/v1/openapi.json makes it easy to turn the endpoints into agent tools.
  • An AI assistant used by a person should use the Cashod MCP server at https://mcp.cashod.ma/mcp. It works with AI assistants that support MCP connectors, such as Claude and ChatGPT. Sign-in is OAuth: the user logs in with their Cashod account and approves access, and the assistant then acts with that user's normal permissions across their stores. Setup steps are in Settings → AI Chat. Read more about Cashod's AI features.

Can Cashod push events to your system?

Not from the API. For pushing events out, use Workflows: a workflow can call any URL with its webhook action, and can also post to Slack or Discord, send an email, an SMS or a WhatsApp message. Combine the two: the API to create and read, a workflow to notify your system when something happens.

Checklist before going live

  1. Create one key per store with the smallest set of scopes, and keep it server-side only.
  2. Send an external_id on every order and treat both 201 and 200 as success.
  3. Use SKUs that match your Cashod catalogue, or upsert products first.
  4. Leave confirmed off unless you really confirmed with the customer.
  5. Handle 429 with backoff and parse the error.type field.
  6. Follow next_cursor until has_more is false.
  7. Schedule a polling job for status and tracking, or a workflow webhook for events.
  8. Test the full path with one real order: create, confirm, ship, read the tracking number.

FAQ

Does the Cashod API send webhooks?

No. Read status with GET requests, or use a Workflow's webhook action to call your URL.

I manage several stores. Do I need several keys?

Yes. Keys are per store, which keeps each store's data and access separate.

Where is the full reference?

On the developer portal, with guides, an interactive reference and the OpenAPI spec.

Get started

Open the developer docs, create your first key in Settings → Developers and send a test order. To choose a plan by number of stores and monthly orders, see pricing.

Tags
APIREST APIdevelopersCODintegrationAI agentsMCP
Share
Ready to get started?

Grow Your COD Business

Join thousands of Moroccan entrepreneurs using Cashod to manage their COD operations efficiently.

Secure payment
Secure payment
Cashod REST API: Send COD Orders From Any Store, CRM or AI Agent