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/orders — orders: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}/fulfilment — orders: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/products — products:read
Query parameters: active (true/false), per_page. Cursor-paginated.
GET /v1/products/{id} — products:read
POST /v1/products — products: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/customers — customers: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.