{"openapi":"3.1.0","paths":{"/v1/payment_intents":{"post":{"description":"Returns a client secret and, once confirmed, whatever the customer must do next. Send an `Idempotency-Key` header — a replay returns the same payment rather than creating a second.","operationId":"PaymentsController_createIntent","parameters":[{"name":"idempotency-key","required":false,"in":"header","description":"Any unique string you generate per logical payment. A replay returns the payment the first call created rather than taking the money twice. Reusing a key with a different body is rejected with 412 — that is a client bug, and answering with the first result would charge the wrong figure silently.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePaymentIntentDto"}}}},"responses":{"201":{"description":"Created, awaiting confirmation. `clientSecret` is present exactly here.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatedPaymentIntentResponseDto"}}}},"400":{"description":"Validation failed, or the amount is not positive.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"401":{"description":"Missing, malformed, revoked or IP-refused key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"404":{"description":"The customer or wallet referenced does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"412":{"description":"The idempotency key was reused with a different body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"429":{"description":"Per-key request budget exhausted. Honour `retry-after`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}}},"security":[{"apiKey":[]}],"summary":"Create a payment","tags":["Payments"]},"get":{"description":"Scoped to the environment of the key you authenticate with. A TEST key never sees LIVE payments.","operationId":"PaymentsController_listIntents","parameters":[{"name":"limit","required":false,"in":"query","description":"Capped at 100. Larger reads belong in an export.","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"One-based.","schema":{"type":"string"}},{"name":"search","required":false,"in":"query","description":"Prefix on ids; case-insensitive contains on reference, receipt email, description and the customer’s name or email.","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedPaymentIntentsResponseDto"}}}},"401":{"description":"Missing, malformed, revoked or IP-refused key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"429":{"description":"Per-key request budget exhausted. Honour `retry-after`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}}},"security":[{"apiKey":[]}],"summary":"List payments","tags":["Payments"]}},"/v1/payment_intents/{id}/confirm":{"post":{"description":"Routes the payment to a provider and starts it. The response says what the customer must do next.","operationId":"PaymentsController_confirmIntent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Routed and started. Read `status` and `nextAction` — a DEVICE_PUSH payment is not complete when this returns.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmedPaymentIntentResponseDto"}}}},"401":{"description":"Missing, malformed, revoked or IP-refused key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"404":{"description":"No such payment under this merchant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"409":{"description":"Already expired, already confirmed, or another attempt is in flight — a customer double-tapping a pay button gets this rather than two charges.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"429":{"description":"Per-key request budget exhausted. Honour `retry-after`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"503":{"description":"No route is available for this corridor right now.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}}},"security":[{"apiKey":[]}],"summary":"Confirm a payment","tags":["Payments"]}},"/v1/payment_intents/{id}":{"get":{"description":"Includes every charge attempted against it. Somebody else’s id answers 404 rather than 403, so this cannot be used to test whether an id exists.","operationId":"PaymentsController_getIntent","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntentWithChargesResponseDto"}}}},"401":{"description":"Missing, malformed, revoked or IP-refused key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"404":{"description":"No such payment under this merchant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"429":{"description":"Per-key request budget exhausted. Honour `retry-after`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}}},"security":[{"apiKey":[]}],"summary":"Retrieve a payment","tags":["Payments"]}},"/v1/customers":{"post":{"description":"Optional. A payment can name a customer or stand alone; creating one is worth it when you want the same payer across several payments.","operationId":"PaymentsController_createCustomer","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponseDto"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"401":{"description":"Missing, malformed, revoked or IP-refused key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"429":{"description":"Per-key request budget exhausted. Honour `retry-after`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}}},"security":[{"apiKey":[]}],"summary":"Create a customer","tags":["Payments"]}},"/v1/providers":{"get":{"description":"Returns flow kinds, not provider names. A checkout UI renders from this, which is why enabling a new provider requires no client release. Pass `amount` to exclude methods whose limits exclude this payment.","operationId":"PaymentsController_availableMethods","parameters":[{"name":"country","required":true,"in":"query","schema":{"example":"CM","type":"string"}},{"name":"currency","required":true,"in":"query","schema":{"example":"XAF","type":"string"}},{"name":"amount","required":false,"in":"query","description":"Minor units, as a decimal string.","schema":{"example":"500000","type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailableMethodsResponseDto"}}}},"401":{"description":"Missing, malformed, revoked or IP-refused key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}},"429":{"description":"Per-key request budget exhausted. Honour `retry-after`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponseDto"}}}}},"security":[{"apiKey":[]}],"summary":"Payment methods available for a corridor","tags":["Payments"]}}},"info":{"title":"IdealBox Pay API","description":"The REST surface a merchant server integrates against. The dashboard uses\nGraphQL; both are presentations of one service layer, and neither holds\nbusiness logic of its own.\n\nFour conventions run through every endpoint:\n\n- **Amounts are decimal strings of minor units.** `\"1050\"` in USD is $10.50;\n  `\"500000\"` in XAF is 500,000 francs, because XAF has no minor unit. A JSON\n  number silently loses precision above 2^53, which a settlement batch in a\n  zero-decimal currency reaches sooner than it looks.\n- **Dates are epoch milliseconds**, matching the GraphQL surface exactly.\n- **The environment is in the key**, never in a header or a request field. A\n  `ib_sk_test_…` key can neither read nor write live data.\n- **Errors carry a stable `code`.** Branch on `error.code`, never on\n  `error.message` — the message is translated to the caller’s language.\n\nMoney-moving calls take an `Idempotency-Key`. A replay returns the original\nresult rather than taking the money twice.","version":"2026-08-19","contact":{}},"tags":[{"name":"Payments","description":"Create a payment, confirm it, and read what happened. Fulfil an order on the `payment_intent.succeeded` webhook, never on the response to confirm — a mobile-money payment is not complete when that call returns."}],"servers":[{"url":"https://secure.idealbox.org","description":"Production"},{"url":"http://localhost:4004","description":"Local development"}],"components":{"securitySchemes":{"apiKey":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"A secret key, `ib_sk_test_…` or `ib_sk_live_…`. The environment is in the key text, never inferred from the request, so a production credential in a staging config is visible to anyone reading the file."}},"schemas":{"ApiErrorDetailDto":{"type":"object","properties":{"type":{"type":"string","enum":["invalid_request_error","authentication_error","rate_limit_error","api_error"]},"code":{"type":"string","enum":["invalid_request","unauthenticated","permission_denied","resource_missing","resource_conflict","idempotency_key_reused","unprocessable_entity","rate_limit_exceeded","processor_unavailable","api_error"]},"message":{"type":"string","description":"Human-readable, already translated."},"requestId":{"type":"string","description":"Echoed from the `x-request-id` response header."},"details":{"type":"object","additionalProperties":true,"description":"Field-level validation failures, when there are any."}},"required":["type","code","message"]},"ApiErrorResponseDto":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ApiErrorDetailDto"}},"required":["error"]},"CreatePaymentIntentDto":{"type":"object","properties":{"amount":{"type":"string","description":"Amount in minor units, as a decimal string. \"1050\" is $10.50.","example":"500000"},"currency":{"type":"string","example":"XAF"},"country":{"type":"string","description":"Where the payer is. Decides the corridor and the route.","example":"CM"},"methodType":{"type":"string","enum":["CARD","BANK_ACCOUNT","MOBILE_MONEY","WALLET","CRYPTO","CASH"]},"walletBrand":{"type":"string","enum":["APPLE_PAY","GOOGLE_PAY","PAYPAL"],"description":"The credential source for a wallet payment. Not a provider — Apple Pay produces a token an acquirer processes."},"reference":{"type":"string","description":"Your own reference for this payment."},"description":{"type":"string"},"customer":{"type":"string","description":"Customer id (cus_…)."},"wallet":{"type":"string","description":"Wallet to credit (wlt_…). Defaults to the wallet bound to your key, then your default wallet."},"receiptEmail":{"type":"string"},"returnUrl":{"type":"string","description":"Where to send the payer after an off-site step."},"statementDescriptor":{"type":"string","description":"Shown on the customer’s statement."},"providerParams":{"type":"object","description":"Provider-specific parameters. In test mode, `simulate` forces an outcome."},"metadata":{"type":"object"}},"required":["amount","currency","country","methodType"]},"CreatedPaymentIntentResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"pi_01JAY2K5RQ9M3W7ZB8XF4TC6VD"},"object":{"type":"string","enum":["payment_intent"],"example":"payment_intent"},"status":{"type":"string","enum":["REQUIRES_PAYMENT_METHOD","REQUIRES_CONFIRMATION","REQUIRES_ACTION","PROCESSING","REQUIRES_CAPTURE","SUCCEEDED","CANCELED","FAILED","EXPIRED"]},"amount":{"type":"string","description":"What the merchant asked to receive, in minor units as a decimal string. **Not necessarily what the customer pays** — see `surcharge`.","example":"500000"},"surcharge":{"type":"string","description":"Added to `amount` for the customer to pay, when the merchant has set the customer as the fee bearer. `\"0\"` otherwise.","example":"0"},"totalAmount":{"type":"string","description":"What the customer is actually charged: `amount + surcharge`. Show this figure at checkout — it is the number the payer approves.","example":"500000"},"currency":{"type":"string","example":"XAF"},"country":{"type":"string","example":"CM"},"methodType":{"type":"string","enum":["CARD","BANK_ACCOUNT","MOBILE_MONEY","WALLET","CRYPTO","CASH"]},"provider":{"type":"string","enum":["SIMULATOR","FLUTTERWAVE","PAYSTACK","CAMERPAY","STRIPE","MTN_MOMO","ORANGE_MONEY","AIRTEL_MONEY","MOOV_MONEY","WAVE","MPESA","PAYPAL","BANK_TRANSFER_LOCAL"],"nullable":true,"description":"Null until the payment is confirmed and routed."},"flowKind":{"type":"string","enum":["DIRECT","REDIRECT","DEVICE_PUSH","OTP_CHALLENGE","QR_DISPLAY","VOUCHER_INSTRUCTION"],"nullable":true,"description":"What the customer must do. A client renders from this, never from the provider name — which is why enabling a new provider needs no client release."},"reference":{"type":"object","nullable":true,"example":"order-4471"},"description":{"type":"object","nullable":true},"nextAction":{"type":"object","nullable":true,"additionalProperties":true,"description":"The instruction for the client while the payment needs the customer."},"lastPaymentError":{"type":"object","nullable":true,"additionalProperties":true,"description":"The last failure, with a canonical `code` from the failure taxonomy plus the provider’s own message. Retry logic branches on `code`."},"expiresAt":{"type":"number","nullable":true,"description":"Epoch milliseconds. After this the payment moves to EXPIRED, which is not FAILED — nobody declined it."},"created":{"type":"number","description":"Epoch milliseconds."},"clientSecret":{"type":"string","description":"Returned exactly once, at creation. Only a hash is stored, so this cannot be recovered — a client that loses it creates a new payment. It lets a browser confirm this one payment without holding a secret key."}},"required":["id","object","status","amount","surcharge","totalAmount","currency","country","methodType","provider","flowKind","reference","description","nextAction","lastPaymentError","expiresAt","created"]},"ChargeResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"ch_01JAY2K5RQ9M3W7ZB8XF4TC6VD"},"object":{"type":"string","enum":["charge"],"example":"charge"},"status":{"type":"string","enum":["PENDING","AUTHORIZED","SUCCEEDED","FAILED","CANCELED","EXPIRED","REFUNDED","PARTIALLY_REFUNDED","DISPUTED"]},"amount":{"type":"string","example":"500000"},"amountCaptured":{"type":"string","example":"500000","description":"What the provider actually took, which is not always what was asked for."},"currency":{"type":"string","example":"XAF"},"provider":{"type":"string","enum":["SIMULATOR","FLUTTERWAVE","PAYSTACK","CAMERPAY","STRIPE","MTN_MOMO","ORANGE_MONEY","AIRTEL_MONEY","MOOV_MONEY","WAVE","MPESA","PAYPAL","BANK_TRANSFER_LOCAL"]},"failureCode":{"type":"string","enum":["INSUFFICIENT_FUNDS","INVALID_ACCOUNT","ACCOUNT_INACTIVE","LIMIT_EXCEEDED","EXPIRED_INSTRUMENT","AUTHENTICATION_FAILED","DECLINED_BY_ISSUER","USER_CANCELLED","TIMEOUT","DUPLICATE","FRAUD_SUSPECTED","CURRENCY_NOT_SUPPORTED","PROVIDER_UNAVAILABLE","PROVIDER_ERROR","CONFIGURATION_ERROR"],"nullable":true},"failureMessage":{"type":"object","nullable":true,"description":"The provider’s own prose. Never branch on it."},"created":{"type":"number"}},"required":["id","object","status","amount","amountCaptured","currency","provider","failureCode","failureMessage","created"]},"ConfirmedPaymentIntentResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"pi_01JAY2K5RQ9M3W7ZB8XF4TC6VD"},"object":{"type":"string","enum":["payment_intent"],"example":"payment_intent"},"status":{"type":"string","enum":["REQUIRES_PAYMENT_METHOD","REQUIRES_CONFIRMATION","REQUIRES_ACTION","PROCESSING","REQUIRES_CAPTURE","SUCCEEDED","CANCELED","FAILED","EXPIRED"]},"amount":{"type":"string","description":"What the merchant asked to receive, in minor units as a decimal string. **Not necessarily what the customer pays** — see `surcharge`.","example":"500000"},"surcharge":{"type":"string","description":"Added to `amount` for the customer to pay, when the merchant has set the customer as the fee bearer. `\"0\"` otherwise.","example":"0"},"totalAmount":{"type":"string","description":"What the customer is actually charged: `amount + surcharge`. Show this figure at checkout — it is the number the payer approves.","example":"500000"},"currency":{"type":"string","example":"XAF"},"country":{"type":"string","example":"CM"},"methodType":{"type":"string","enum":["CARD","BANK_ACCOUNT","MOBILE_MONEY","WALLET","CRYPTO","CASH"]},"provider":{"type":"string","enum":["SIMULATOR","FLUTTERWAVE","PAYSTACK","CAMERPAY","STRIPE","MTN_MOMO","ORANGE_MONEY","AIRTEL_MONEY","MOOV_MONEY","WAVE","MPESA","PAYPAL","BANK_TRANSFER_LOCAL"],"nullable":true,"description":"Null until the payment is confirmed and routed."},"flowKind":{"type":"string","enum":["DIRECT","REDIRECT","DEVICE_PUSH","OTP_CHALLENGE","QR_DISPLAY","VOUCHER_INSTRUCTION"],"nullable":true,"description":"What the customer must do. A client renders from this, never from the provider name — which is why enabling a new provider needs no client release."},"reference":{"type":"object","nullable":true,"example":"order-4471"},"description":{"type":"object","nullable":true},"nextAction":{"type":"object","nullable":true,"additionalProperties":true,"description":"The instruction for the client while the payment needs the customer."},"lastPaymentError":{"type":"object","nullable":true,"additionalProperties":true,"description":"The last failure, with a canonical `code` from the failure taxonomy plus the provider’s own message. Retry logic branches on `code`."},"expiresAt":{"type":"number","nullable":true,"description":"Epoch milliseconds. After this the payment moves to EXPIRED, which is not FAILED — nobody declined it."},"created":{"type":"number","description":"Epoch milliseconds."},"latestCharge":{"$ref":"#/components/schemas/ChargeResponseDto"}},"required":["id","object","status","amount","surcharge","totalAmount","currency","country","methodType","provider","flowKind","reference","description","nextAction","lastPaymentError","expiresAt","created","latestCharge"]},"PaymentIntentWithChargesResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"pi_01JAY2K5RQ9M3W7ZB8XF4TC6VD"},"object":{"type":"string","enum":["payment_intent"],"example":"payment_intent"},"status":{"type":"string","enum":["REQUIRES_PAYMENT_METHOD","REQUIRES_CONFIRMATION","REQUIRES_ACTION","PROCESSING","REQUIRES_CAPTURE","SUCCEEDED","CANCELED","FAILED","EXPIRED"]},"amount":{"type":"string","description":"What the merchant asked to receive, in minor units as a decimal string. **Not necessarily what the customer pays** — see `surcharge`.","example":"500000"},"surcharge":{"type":"string","description":"Added to `amount` for the customer to pay, when the merchant has set the customer as the fee bearer. `\"0\"` otherwise.","example":"0"},"totalAmount":{"type":"string","description":"What the customer is actually charged: `amount + surcharge`. Show this figure at checkout — it is the number the payer approves.","example":"500000"},"currency":{"type":"string","example":"XAF"},"country":{"type":"string","example":"CM"},"methodType":{"type":"string","enum":["CARD","BANK_ACCOUNT","MOBILE_MONEY","WALLET","CRYPTO","CASH"]},"provider":{"type":"string","enum":["SIMULATOR","FLUTTERWAVE","PAYSTACK","CAMERPAY","STRIPE","MTN_MOMO","ORANGE_MONEY","AIRTEL_MONEY","MOOV_MONEY","WAVE","MPESA","PAYPAL","BANK_TRANSFER_LOCAL"],"nullable":true,"description":"Null until the payment is confirmed and routed."},"flowKind":{"type":"string","enum":["DIRECT","REDIRECT","DEVICE_PUSH","OTP_CHALLENGE","QR_DISPLAY","VOUCHER_INSTRUCTION"],"nullable":true,"description":"What the customer must do. A client renders from this, never from the provider name — which is why enabling a new provider needs no client release."},"reference":{"type":"object","nullable":true,"example":"order-4471"},"description":{"type":"object","nullable":true},"nextAction":{"type":"object","nullable":true,"additionalProperties":true,"description":"The instruction for the client while the payment needs the customer."},"lastPaymentError":{"type":"object","nullable":true,"additionalProperties":true,"description":"The last failure, with a canonical `code` from the failure taxonomy plus the provider’s own message. Retry logic branches on `code`."},"expiresAt":{"type":"number","nullable":true,"description":"Epoch milliseconds. After this the payment moves to EXPIRED, which is not FAILED — nobody declined it."},"created":{"type":"number","description":"Epoch milliseconds."},"charges":{"description":"Every attempt against this payment. A declined card followed by a successful mobile-money payment is two charges under one payment.","type":"array","items":{"$ref":"#/components/schemas/ChargeResponseDto"}}},"required":["id","object","status","amount","surcharge","totalAmount","currency","country","methodType","provider","flowKind","reference","description","nextAction","lastPaymentError","expiresAt","created","charges"]},"PaymentIntentResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"pi_01JAY2K5RQ9M3W7ZB8XF4TC6VD"},"object":{"type":"string","enum":["payment_intent"],"example":"payment_intent"},"status":{"type":"string","enum":["REQUIRES_PAYMENT_METHOD","REQUIRES_CONFIRMATION","REQUIRES_ACTION","PROCESSING","REQUIRES_CAPTURE","SUCCEEDED","CANCELED","FAILED","EXPIRED"]},"amount":{"type":"string","description":"What the merchant asked to receive, in minor units as a decimal string. **Not necessarily what the customer pays** — see `surcharge`.","example":"500000"},"surcharge":{"type":"string","description":"Added to `amount` for the customer to pay, when the merchant has set the customer as the fee bearer. `\"0\"` otherwise.","example":"0"},"totalAmount":{"type":"string","description":"What the customer is actually charged: `amount + surcharge`. Show this figure at checkout — it is the number the payer approves.","example":"500000"},"currency":{"type":"string","example":"XAF"},"country":{"type":"string","example":"CM"},"methodType":{"type":"string","enum":["CARD","BANK_ACCOUNT","MOBILE_MONEY","WALLET","CRYPTO","CASH"]},"provider":{"type":"string","enum":["SIMULATOR","FLUTTERWAVE","PAYSTACK","CAMERPAY","STRIPE","MTN_MOMO","ORANGE_MONEY","AIRTEL_MONEY","MOOV_MONEY","WAVE","MPESA","PAYPAL","BANK_TRANSFER_LOCAL"],"nullable":true,"description":"Null until the payment is confirmed and routed."},"flowKind":{"type":"string","enum":["DIRECT","REDIRECT","DEVICE_PUSH","OTP_CHALLENGE","QR_DISPLAY","VOUCHER_INSTRUCTION"],"nullable":true,"description":"What the customer must do. A client renders from this, never from the provider name — which is why enabling a new provider needs no client release."},"reference":{"type":"object","nullable":true,"example":"order-4471"},"description":{"type":"object","nullable":true},"nextAction":{"type":"object","nullable":true,"additionalProperties":true,"description":"The instruction for the client while the payment needs the customer."},"lastPaymentError":{"type":"object","nullable":true,"additionalProperties":true,"description":"The last failure, with a canonical `code` from the failure taxonomy plus the provider’s own message. Retry logic branches on `code`."},"expiresAt":{"type":"number","nullable":true,"description":"Epoch milliseconds. After this the payment moves to EXPIRED, which is not FAILED — nobody declined it."},"created":{"type":"number","description":"Epoch milliseconds."}},"required":["id","object","status","amount","surcharge","totalAmount","currency","country","methodType","provider","flowKind","reference","description","nextAction","lastPaymentError","expiresAt","created"]},"PaginatedPaymentIntentsResponseDto":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PaymentIntentResponseDto"}},"total":{"type":"number","example":137},"page":{"type":"number","example":1},"limit":{"type":"number","example":20,"description":"Capped at 100."},"hasMore":{"type":"boolean","description":"From the server, never inferred from page × limit < total — the two disagree the moment a row is inserted between the count and the fetch."}},"required":["items","total","page","limit","hasMore"]},"CreateCustomerDto":{"type":"object","properties":{"email":{"type":"string"},"phone":{"type":"string"},"name":{"type":"string"},"externalRef":{"type":"string","description":"Your own id for this customer."},"country":{"type":"string"},"metadata":{"type":"object"}}},"CustomerResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"cus_01JAY2K5RQ9M3W7ZB8XF4TC6VD"},"object":{"type":"string","enum":["customer"],"example":"customer"},"email":{"type":"object","nullable":true},"phone":{"type":"object","nullable":true},"name":{"type":"object","nullable":true},"externalRef":{"type":"object","nullable":true,"description":"Your own id for this customer."},"created":{"type":"number"}},"required":["id","object","email","phone","name","externalRef","created"]},"ProviderMethodDto":{"type":"object","properties":{"methodType":{"type":"string","enum":["CARD","BANK_ACCOUNT","MOBILE_MONEY","WALLET","CRYPTO","CASH"]},"flowKind":{"type":"string","enum":["DIRECT","REDIRECT","DEVICE_PUSH","OTP_CHALLENGE","QR_DISPLAY","VOUCHER_INSTRUCTION"]},"minAmount":{"type":"object","nullable":true,"example":"100"},"maxAmount":{"type":"object","nullable":true,"example":"5000000"}},"required":["methodType","flowKind","minAmount","maxAmount"]},"AvailableMethodsResponseDto":{"type":"object","properties":{"country":{"type":"string","example":"CM"},"currency":{"type":"string","example":"XAF"},"methods":{"type":"array","items":{"$ref":"#/components/schemas/ProviderMethodDto"}}},"required":["country","currency","methods"]}}}}