v1 · draft
View .md

Core concepts

Conventions

Rules every endpoint follows. Read them once before you build.

Requests#

  • JSON in and out (Content-Type: application/json), UTF-8. The only exceptions are the token route (form-encoded) and bordereaux (CSV out).
  • Unknown body fields and query parameters are rejected (400 bad_request), so typos fail loudly instead of being ignored.
  • Bodies are limited to 100 KB.
HeaderDirectionUse
AuthorizationrequestBearer <accessToken> on every route except the token route.
Idempotency-KeyrequestSafe retries of writes. See below.
If-MatchrequestThe version you read, to avoid overwriting a newer change. See below.
X-Request-IdbothYour id for the call (a fresh UUID), echoed in the response and our logs.
ETagresponseVersion of an editable resource: W/"7".
RateLimit, RateLimit-Policy, Retry-AfterresponseRate limiter state. See Rate limits.

Response envelope#

Every JSON response, success or error, has the same four keys:

200 OK
{
  "status": "success",
  "data": { "id": "6f1c2d3e-4b5a-4c69-8d7e-1f2a3b4c5d6e", "status": "active" },
  "error": null,
  "metadata": {
    "timestamp": "2026-11-05T09:15:02.481Z",
    "path": "/api/v1/partner/policies/6f1c2d3e-4b5a-4c69-8d7e-1f2a3b4c5d6e",
    "method": "GET",
    "requestId": "8d7e2c1a-41f0-4a4e-9a55-6f0b3c2d1e77"
  }
}
  • status is success (2xx), fail (4xx: fix the request) or error (5xx: our side, retry later).
  • Read the HTTP status code and error.code. Never parse error.message: it's English text for developers and can change. See Errors.
  • metadata.requestId identifies the call. Log it and quote it to support.

Data formats#

KindFormatExample
IdsUUID strings. Path ids that aren't UUIDs get 400.6f1c2d3e-4b5a-4c69-8d7e-1f2a3b4c5d6e
MoneyEGP, decimal strings with 2 decimals. Prices are tax-inclusive."9500.00", "-620.27"
InstantsISO 8601 in UTC.2026-11-05T09:15:02.481Z
Calendar datesYYYY-MM-DD, on the Cairo (Africa/Cairo) calendar.2026-11-05
Phone numbersEgyptian mobiles, returned as 01XXXXXXXXX.01012345678
Translatable textBoth languages, always.{ "en": "Gold Care", "ar": "جولد كير" }
EnumsLowercase snake_case, case-sensitive.documents_requested

Parse money with a decimal type (decimal in C#, Decimal in Python, BigDecimal in Java, a decimal library in JavaScript). Never with a binary float: rounding errors break reconciliation.

Pagination#

Lists take page (from 1) and size (1–100, default 20) and return:

data
{
  "items": [ { "id": "…" } ],
  "meta": {
    "page": 2,
    "size": 20,
    "totalItems": 47,
    "totalPages": 3,
    "hasNextPage": true,
    "hasPreviousPage": true
  }
}

Change feed#

Policies, cancellations, claims and packages accept updatedSince. Sorted by updatedAt ascending, a list is a change feed: a reliable way to sync, and the safety net behind webhooks.

Pseudocode
# Every few minutes, per resource:
since = load_checkpoint("policies")          # e.g. 2026-11-04T00:00:00.000Z
loop:
  page = GET /partner/policies?updatedSince={since}&sortBy=updatedAt&sortOrder=asc&size=100
  for row in page.items:
      upsert(row) unless already_seen(row.id, row.updatedAt)
  if page.items: since = page.items[-1].updatedAt; save_checkpoint("policies", since)
  if not page.meta.hasNextPage: break

Rows changed in the same millisecond can appear on two pages, so make the upsert idempotent on id + updatedAt.

Idempotency#

A network failure can hide whether a write happened. Send Idempotency-Key: <UUID v4> on writes; if you retry with the same key, the action runs once and every retry gets the first result.

  • One key per action (one cancellation, one approval), reused for every retry of it. A new action gets a new key.
  • Successful results are kept for 24 hours.
  • A failed request (validation or business error) releases the key, so you can fix the input and retry with the same key.
StatusCodeMeaningDo
409idempotency_request_is_still_processingThe first request with this key is still running.Wait Retry-After (1 s), retry with the same key.
422idempotency_key_already_usedSame key, different URL or body.Bug: use a new key for a new action.
400bad_requestKey missing where required, or not 8–128 of A-Z a-z 0-9 _ -.Send a UUID v4.

Each endpoint shows whether it requires or supports the header. Required on money-moving actions (cancel a policy, record a refund).

Concurrent edits#

Your staff may edit the same resource in the Wathiqaty portal while your system does through the API. Editable resources return a version in ETag (and a version field). Send it back as If-Match: if someone changed the resource since you read it, you get 412 version_conflict with details.currentVersion instead of silently overwriting their change. Reload, re-apply, resend.

Files#

Files are never streamed through the API. Responses carry a url to download from directly. To upload (settlement proof), ask for a presigned upload URL, send the file straight to storage, then reference its fileKey.

Personal data#

Policies carry the policyholder's personal data, including the national id verified by eKYC. Request policies:read only for systems that need it, store only what your policy administration requires, and handle it under Egypt's Personal Data Protection Law (151/2020) and the integration agreement.