EL OUATINE — Reseller API v2

Version 2 — Bearer-token auth (Authorization: Bearer), per-key scopes, key management from your account, and signed order-status webhooks. All endpoints live under /api/v2. The v1 API (/api/reseller) keeps working unchanged — see the v1 docs.

API v2 للموزعين: مفتاح بصيغة Bearer بصلاحيات تختارها انت، تقدر تجيب الخدمات والأسعار، تطلب لزبونك مباشرة (الرصيد يتخصم من محفظتك)، وتستقبل إشعارات فورية (webhooks) على كل تغيير في حالة الطلب — موقّعة بمفتاح سري خاص بك. أنشئ مفاتيحك وإشعاراتك من الأسفل بعد تسجيل الدخول، وعبّي رصيدك من صفحة حسابك كيما العادة (RedotPay).

Authentication

Every request must carry your API key as a Bearer token in the Authorization header. Without a valid key the API answers 401. Keep your key secret — it is shown once when created below.

curl -H "Authorization: Bearer elo_YOUR_KEY" https://securecelleouatine.com/api/v2/balance

Manage your keys & webhooks

Create API keys (with the scopes you choose), revoke them, and register signed webhook URLs — all from here, after logging in to your EL OUATINE account.

Endpoints

MethodPathScopeDescription
GET/api/v2/servicesservicesActive services with reseller prices (USD)
GET/api/v2/services/:id/priceservicesSingle price + availability check
POST/api/v2/ordersordersPlace an order — charged to your wallet
GET/api/v2/ordersordersList your orders (paginated, newest first)
GET/api/v2/orders/:idordersOrder status (your orders only)
PATCH/api/v2/orders/:id/imeiordersSupply a missing IMEI when the order asks for it
GET/api/v2/balancebalanceYour wallet balance

Every response is { "ok": true, "data": … } or { "ok": false, "error": "code" }. Rate limit: 60 requests/minute per key (429 rate_limited).

List services

curl -H "Authorization: Bearer elo_YOUR_KEY" \
  https://securecelleouatine.com/api/v2/services
{
  "ok": true,
  "data": [
    { "id": 873, "name_en": "iPhone Network Unlock", "name_fr": "...", "name_ar": "...",
      "price_member": 12.5, "currency": "USD", "category": "Apple",
      "delivery_time": "1-24h" }
  ]
}

Price check

curl -H "Authorization: Bearer elo_YOUR_KEY" \
  https://securecelleouatine.com/api/v2/services/873/price
{ "ok": true, "data": { "service_id": 873, "price_member": 12.5,
  "currency": "USD", "available": true } }

Place an order

Send service_id and the imei. The wallet is charged atomically — a service that is temporarily off answers 409 service_off; an empty wallet answers 402 insufficient_balance. Pass an Idempotency-Key header (any unique value per logical purchase) so network retries never create a duplicate order — replaying a key returns the original order with replayed: true and no second charge.

curl -X POST -H "Authorization: Bearer elo_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{"service_id": 873, "imei": "356938035643809"}' \
  https://securecelleouatine.com/api/v2/orders
{
  "ok": true,
  "data": { "order_id": 1024, "status": "paid", "replayed": false,
            "order": { "id": 1024, "service_name": "iPhone Network Unlock",
                       "price": 12.5, "currency": "USD", "status": "paid", ... } }
}

List orders

Query params: limit (default 50, max 200), offset (default 0), status (optional filter, e.g. paid).

curl -H "Authorization: Bearer elo_YOUR_KEY" \
  "https://securecelleouatine.com/api/v2/orders?limit=20&status=paid"

Check an order

curl -H "Authorization: Bearer elo_YOUR_KEY" \
  https://securecelleouatine.com/api/v2/orders/1024

Supply a missing IMEI

If an order's supplier_status is awaiting_imei, send the IMEI here — the order is automatically re-sent to the supplier.

curl -X PATCH -H "Authorization: Bearer elo_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"imei": "356938035643809"}' \
  https://securecelleouatine.com/api/v2/orders/1024/imei

Check balance

curl -H "Authorization: Bearer elo_YOUR_KEY" \
  https://securecelleouatine.com/api/v2/balance
{ "ok": true, "data": { "balance": 87.5, "currency": "USD" } }

Webhooks

Register a URL above. On every status change of your orders (paid → in_progress → completed, or cancelled) EL OUATINE POSTs JSON like this:

{
  "event": "order.status",
  "order_id": 1024,
  "status": "completed",
  "service_name": "iPhone Network Unlock",
  "price": 12.5,
  "currency": "USD",
  "imei": "356938035643809",
  "supplier_status": null,
  "sent_at": "2026-10-11T12:00:00.000Z"
}

An order.created event fires when the order is placed. Use the Test button above (or POST /api/v2/webhooks/:id/test) to send a webhook.test ping.

Verifying webhook signatures

The X-ElOuatine-Signature header is sha256= + the hex HMAC-SHA256 of the raw request body, keyed with your webhook secret. Verify before parsing the JSON:

Node.js (Express):

const crypto = require('crypto');

app.post('/elouatine-webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.get('X-ElOuatine-Signature') || '';
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.ELOUATINE_WEBHOOK_SECRET)
    .update(req.body) // raw bytes, NOT the parsed object
    .digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(401).end();
  }
  const event = JSON.parse(req.body.toString());
  console.log(event.event, event.order_id, event.status);
  res.status(200).end();
});

PHP:

<?php
$raw = file_get_contents('php://input');
$sig = $_SERVER['HTTP_X_ELOUATINE_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $raw, getenv('ELOUATINE_WEBHOOK_SECRET'));
if (!hash_equals($expected, $sig)) { http_response_code(401); exit; }
$event = json_decode($raw, true);
// $event['event'], $event['order_id'], $event['status'] ...
http_response_code(200);

Errors

HTTPerrorMeaning
400service_id_invalid / service_on_request / imei_invalidBad request or service has no fixed price
401api_key_required / api_key_invalidMissing, wrong or revoked key
402insufficient_balanceTop up your wallet and retry
403insufficient_scopeYour key lacks the scope for this endpoint
404service_not_found / order_not_found / key_not_found / webhook_not_foundUnknown id (orders/keys/webhooks are scoped to your account)
409service_off / imei_not_neededService temporarily unavailable / IMEI not requested
429rate_limitedSlow down — 60 requests/minute per key

Wallet top-up

Top up from your site account page as usual (RedotPay, USD). The API uses the same wallet — no separate payment setup needed.