EYalla/Developers Contact us

Merchant API (v1)

The Merchant API lets a store's own systems — ERPs, fulfilment tools, spreadsheets, custom apps — read and update that store's data. It is available on the Elite plan.

  • Base URL: https://api.eyalla.net/v1
  • Format: JSON in, JSON out. All prices are KWD with 3 decimals, returned as strings ("4.750").
  • Rate limit: 60 requests/minute per key. Exceeding it returns 429.

Authentication

Create a key in your admin panel: Settings → API keys. Choose the scopes the integration actually needs — a key can never do more than its scopes.

The full key is shown once, at creation. We store only a hash.

Send it on every request:

Authorization: Bearer <your key>

Every authentication failure — missing key, unknown key, revoked key, expired key — returns the same 401. A key whose scopes don't cover the endpoint returns 403. A store whose plan doesn't include the API returns 403 with plan_gate.

Every request is logged to your own audit trail (key, route, status, IP) — you can see exactly what your integrations did.

Scopes

Scope Grants
orders:read List and read orders
orders:write Update order fulfilment
products:read List and read products
products:write Create and edit products
customers:read List and read customers

Orders

GET /v1/ordersorders:read

Query parameters: payment_status, created_after (ISO date), per_page (max 100).

Cursor-paginated: pass the response's next_cursor back as ?cursor=.

GET /v1/orders/{number}orders:read

One order by its order number, including line items.

PATCH /v1/orders/{number}/fulfilmentorders:write

{ "status": "shipped", "carrier": "aramex", "awb": "123456" }

status is required and must be one of pending, confirmed, processing, shipped, delivered, cancelled, returned. carrier and awb are optional and stored with the order.

This behaves exactly like updating the status in the admin panel: the same status-change events fire, so customer notification emails and webhooks go out identically. The first transition to shipped or delivered stamps its timestamp; repeat transitions never rewrite it.

The API cannot touch money. Payment status, refunds, and captures are panel-only by design.

Products

GET /v1/productsproducts:read

Query parameters: active (true/false), per_page. Cursor-paginated.

GET /v1/products/{id}products:read

POST /v1/productsproducts:write

{
  "name": "Tulip Bouquet",
  "name_ar": "باقة توليب",
  "sku": "TULIP-12",
  "price": 12.500,
  "stock_qty": 40,
  "manage_stock": true,
  "is_active": true
}

Required: name, name_ar, sku, price. EYalla storefronts are bilingual — the Arabic name is shown to Arabic-preference customers, so it is required, not optional.

Slugs are generated from the name and de-duplicated automatically (you may pass slug to suggest one; it will be normalized). Currency is always the store currency — a currency field in the payload is ignored.

Also writable: description, description_ar, compare_at_price, vendor.

PATCH /v1/products/{id}products:write

Partial update — send only the fields you're changing, from the same field set as create.

Customers

GET /v1/customerscustomers:read

Your customers as the platform itself counts them: registered accounts and guest buyers, grouped by identity (a guest is the same customer across orders when their email + phone match). Each row carries orders_count, total_spent, and first/last order dates.

Query parameters: email, phone (exact-match filters), page, per_page (max 100). This endpoint uses page-number pagination (page/per_page/has_more), not cursors.

GET /v1/customers/{id}customers:read

One registered customer by their account id. Guest customers have no id — find them via the list filters.


Errors

Status Meaning
401 Authentication failed (any reason)
403 Key lacks the scope, or the plan lacks the API
404 {"error": "not_found"}
409 {"error": "not_available_for_vertical"} — the store's vertical has no such resource
422 {"error": "validation", "messages": {...}}
423 The store's account is locked — suspended, cancelled or expired. The body carries status and reason. Do not retry: this will not change until the merchant acts.
429 Rate limit exceeded
503 The store is still being set up, or is temporarily unavailable. Safe to retry with backoff.

Webhooks

Prefer being told over polling: the Webhooks system pushes order, payment, and shipping events to your endpoint as they happen.