Skip to main content

One envelope, every endpoint

Every mutating call sends the same two-part request envelope, and every response, success or error, comes back in the same response envelope. Learn this shape once and it holds across the entire surface. The base URL is https://api.feddi.io/v1/partner. A dev environment is available at https://api.dev.feddi.io/v1/partner. All paths sit under /v1/partner.
The envelope conventions on this page apply to every endpoint regardless of its own stability. Call GET /capabilities and GET /openapi at runtime to confirm which operations and enums are enabled for your credentials. See API stability below.

The request envelope

A mutating request carries two top-level objects: meta (correlation and timing) and context (who and where). Your resource-specific body fields sit alongside them.

meta: correlation and timing

required
Your correlation id for this call, a UUID. It threads your logs to Feddi’s. It is not the dedup key. A fresh partner_request_id with a reused Idempotency-Key is a replay, not a new action.
required
RFC 3339 timestamp for when the event happened at the POS.
required
RFC 3339 timestamp for when you transmitted the call. Send both occurred_at and sent_at.
required
The single version field. See Versioning below.

context: who and where

required
The resolved Feddi tenant, a UUID. On a platform integration this is key-enforced to a merchant your credential is authorized for, never a free-text trust field. A merchant_id outside your credential’s authority is rejected. See Identity and credentials.
required
The branch within the merchant, a UUID. Null when not applicable.
required
The physical or logical terminal. Scoped into the terminal JWT.
required
The operator. Server-trusted only when it is signed into the terminal JWT.
required
Your own session or order reference. This is the field that carries your order number into Feddi.
required
The checkout_session UUID this call belongs to. Null on standalone calls that do not run inside a session.
Your order number is not its own envelope field. Put it in context.partner_session_id and read it back the same way. There is exactly one mapping.

The response envelope

Every response, whether ok is true or false, returns the same four top-level keys.
required
True on success, false on a typed error. Branch on this first.
The resource payload on success. Null when ok is false.
Null on success. On failure, a typed object of code, message, and optional details, where code is a string enum, never a bare HTTP number. See Errors.
required
Feddi’s id for this response. Quote it in support requests.
True when this response is a byte-identical replay of an earlier call with the same Idempotency-Key. Do not double-act on a replay.
required
The version that served this response.
An opaque integer Feddi may use internally. No action required.
An opaque correlation id. Persist it and echo it where a call accepts one. Null otherwise.
Additive, response-level capability hints. Treat unknown keys as forward-compatible, never as an error.
On paginated reads, meta also carries next_cursor and has_more. See Pagination.

Money is always minor integers

Every money field is an *_minor integer paired with an explicit ISO-4217 currency. Feddi never accepts or returns a decimal-formatted amount in a body.
amount_minor: 3402 with currency: "QAR" means 34.02 Qatari riyal. The currency code is exactly three characters. Money is server-authoritative: Feddi recomputes its own total from the basket lines you submit and treats that as the basis for any debit or incentive. Your submitted total is captured and reconciled. A divergence is flagged for reconciliation, never silently overridden.
Never send "34.02" or 34.02 for an amount. Floating-point currency is the most common integration bug. Always use an integer minor-units amount plus a currency string.

The Idempotency-Key header

Put a partner-generated UUID in the Idempotency-Key HTTP header on every mutating call. It is the one and only dedup key.
required
A partner-generated UUID, stable for one logical operation and unique across different operations. The TTL is 24 hours. Same key plus same payload replays the original response. Same key plus a different payload returns the typed IDEMPOTENCY_KEY_REUSED conflict, HTTP 422.
Three read-shaped POSTs are the exception: identify, the redeem balance check, and incentive evaluation are side-effect-free, so the header is optional on them. Sending it anyway is fine, uniform client middleware that stamps every POST is accepted, and replays are reported via meta.idempotency_replayed. Every other mutating operation still requires it. The key lives in the HTTP header, not the envelope. There is no meta.idempotency_key field. For the full replay, concurrency, and conflict rules, read Idempotency and errors.

Versioning

There is one version field, api_version, sent in meta and echoed back in meta. /v1 is additive-only. Feddi grows the contract by adding nullable attributes, never by renumbering or renaming a top-level field. Build a forward-compatible client: ignore response keys you do not recognize, and send new fields only when your POS genuinely has them.
A breaking change ships as a new dated api_version, announced in the Changelog. Inside a version, you only ever see additions.

Pagination

List endpoints are cursor-paginated. Pass limit to set the page size and cursor to fetch the next page. The response carries meta.next_cursor and meta.has_more.
required
Page size. Defaults to 50, with a maximum of 200.
required
An opaque cursor from a prior page’s meta.next_cursor. Omit it on the first page.
The cursor to pass as cursor on the next request. Null on the final page.
True when more pages remain. Stop paging when this is false.
Loop until has_more is false, passing the previous response’s next_cursor each time.

API stability

GA operations are stable: the shape will not shift under you. Beta operations are callable today and may still change additively before reaching GA, so pin your api_version. This site documents the designed surface, not what is mounted in your environment right now. Call GET /capabilities and GET /openapi at runtime for the authoritative list of what is available to your credentials, including the enabled credential types, currencies, and feature flags.
Confirm the live, mounted set at runtime via GET /capabilities and GET /openapi before you call a money or identity path. Never assume an operation exists because this site or a guide names it.

A full request and response

This is a standalone identity resolution, the cashier-panel balance check (POST /v1/partner/identify). It shows the envelope on both sides, with money in minor units and the Idempotency-Key header in place. The header is optional on this read-shaped call; it is shown here as a client that stamps every POST would send it.

Where to go next

Errors

Every typed error.code, its HTTP status, and what to do about it.

Idempotency and errors

The full replay, concurrency, and conflict rules for the Idempotency-Key header.

Authentication

Exchange your API key for the terminal JWT every mutating call carries.

Transactions

The cursor-paginated reads that return your settled ledger.