POS reports a top-up SKU sold: credit wallet + accrue SKU bonus
Reports that a registered top-up SKU was sold at tender and credits the customer’s wallet. The POS reports the sale; Feddi credits the resolved wallet by the SKU’s wallet_credits_minor and, in the same atomic transaction, accrues any configured SKU bonus as a promotional grant (source SKU_TOPUP_BONUS), which accrues RELEASED because the customer is identified at point of sale. If the customer is not yet a verified customer, a PENDING_PROOF proto-wallet is created and both the credit and a LOCKED cashback-class promotional grant are escrowed until the customer registers (the register-to-claim flow): the customer keeps their reload, while the bonus stays LOCKED behind proof-of-phone. The credited amount and bonus are derived server-side from the SKU registration and the finalized POS sale, never from POS-submitted money fields. Idempotent on the Idempotency-Key header and on the POS order reference, so a duplicate sale report never double-credits; concurrent reports collapse to exactly one creditor. Cross-tenant SKU access resolves to NOT_FOUND (404). Money is minor-units integers with explicit ISO-4217 currency.
Authorizations
POS terminal JWT minted by /auth/token; carries integrationId + terminal/cashier claims (server-trusted).
Headers
Partner-generated UUID; the ONE dedup key for all mutating endpoints. 24h TTL. Same key + same payload -> byte-identical replay; same key + different payload -> IDEMPOTENCY_KEY_REUSED (422).
Path Parameters
The registered top-up SKU id.
Body
Body for POST /topup/sku/{skuId}. The credited amount + bonus are derived server-side from the SKU registration + finalized POS sale; POS-submitted money fields are ignored. Idempotent on the Idempotency-Key header AND the pos_order_ref.
Canonical request context, shared across all partner domains. merchant_id is key-enforced to a merchant the calling credential is authorized for (a platform-scoped credential acts only on its own tenants), so it is never a free-text trust field: a merchant_id outside the credential's authority is rejected rather than honored.
The finalized POS order reference for this sale, the server-side derivation + idempotency anchor.
Common request metadata shared across all Partner API domains. partner_request_id is a correlation identifier only: it appears in logs and responses for tracing but is never used as the deduplication key. Request deduplication is keyed exclusively on the Idempotency-Key header.
An identity credential used to resolve a customer, shared across all partner domains. The object is discriminated by credential_type, and the value field matching the declared credential_type is REQUIRED (enforced by per-type conditional schemas: a credential without its matching value field is invalid). The set of supported credential_type values is enumerated by GET /capabilities. New credential types are added additively: a new type appears in the GET /capabilities set without any route change. A credential_type that is not in the supported set returns CREDENTIAL_TYPE_UNSUPPORTED, and the error response lists the currently supported set.
Number of SKU units sold (credit = wallet_credits_minor × quantity).
x >= 1Response
Wallet credited (or escrowed for PENDING_PROOF) + SKU bonus accrued.
The standard response envelope that every enveloped endpoint serializes through. ok is a boolean discriminator: when ok is true, the typed result is carried in data; when ok is false, a typed error object is returned instead. The meta object is uniform across the entire API surface.
The uniform response metadata block returned on every response. data_completeness_score is computed per call and reports the completeness of the returned data. decision_trace_id is present on responses that carry decision or insight output and can be used to correlate the response with its reasoning. capabilities is an additive, response-level array of hints advertising features the caller may use, and may be extended over time without notice.
Result of a completed top-up credit (confirm or SKU sale). Carries both money classes after the credit.
The typed error object returned with every non-2xx response. code is a string enum (for example WALLET_PROGRAM_AMBIGUOUS, CREDENTIAL_TYPE_UNSUPPORTED, INSUFFICIENT_FUNDS, IDEMPOTENCY_KEY_REUSED, CURRENCY_NOT_SUPPORTED), never a bare HTTP status number. Inspect code for programmatic branching, not the HTTP status. Some codes echo the valid set in details so clients can present or reconcile the accepted values: for example CREDENTIAL_TYPE_UNSUPPORTED lists the supported credential types, CURRENCY_NOT_SUPPORTED lists the supported ISO-4217 currencies, and WALLET_PROGRAM_AMBIGUOUS lists the candidate wallet_program_id values that matched the request.