{"openapi":"3.1.0","info":{"title":"ArvonaPay Sandbox API","version":"1.5.0","description":"Sandbox payment orchestration. xxxxpays sends reference and merchant customer UID/name/email only; the customer enters amount on ArvonaPay. Customer verification method is not configured and store handoff remains blocked for this flow."},"servers":[{"url":"https://api.arvonapay.com","description":"Sandbox only"}],"security":[{"BearerAuth":[]}],"paths":{"/v1/payments":{"post":{"operationId":"createPayment","summary":"Create a sandbox payment","description":"Requires payments:create. Mandatory Idempotency-Key, bound to merchant, method, path and body. Concurrent retries return the original result; a different body returns 409. Withdrawals require approval by a different authorized console user. Merchant pricing and daily/monthly limits apply. Cross-currency payments require a direct rate for the current Dubai business day; FX_RATE_MISSING returns 409. Original and charge currencies may differ; inspect the immutable pricing snapshot. No real charge is made in sandbox.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePayment"}}}},"responses":{"201":{"description":"Created or replayed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}},"get":{"operationId":"listPayments","summary":"List your own payments","description":"Requires payments:read. Page size up to 100.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Paginated payments","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"total":{"type":"integer"},"page":{"type":"integer"},"limit":{"type":"integer"},"pages":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/Error"}}}},"/v1/payments/{id}":{"get":{"operationId":"getPayment","summary":"Read one of your payments","description":"Cross-merchant identifiers return 404.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"404":{"$ref":"#/components/responses/Error"}}}},"/v1/sandbox/payments/{id}/complete":{"post":{"operationId":"simulatePayment","summary":"Complete a pending sandbox payment","description":"Requires sandbox:simulate and an Idempotency-Key. No money is moved. A withdrawal must already have received independent approval.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["outcome"],"properties":{"outcome":{"enum":["SUCCEEDED","FAILED"]}}}}}},"responses":{"200":{"description":"Final sandbox payment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"409":{"$ref":"#/components/responses/Error"}}}},"/v1/store-payments":{"post":{"operationId":"createStorePayment","summary":"Create a fixed-amount store checkout","description":"Requires payments:create and Idempotency-Key. Merchant sends reference, amount and currency. ArvonaPay applies the configured risk, limits, route and FX snapshot and queues a signed handoff to Dynostech. Charge currency must be AED. The store matches its catalog and records subtotal minus discount equal to locked charge. No vehicle or service data is required in this request. Poll GET /v1/payments/{id} every 3–5 seconds until checkout.url is ready, then direct the customer there. QUEUED and READY are not payment success. Complete only from a verified payment.succeeded webhook or authenticated payment query. Generic sandbox simulation cannot bypass a store checkout. Legacy endpoint: unavailable for xxxxpays after customer amount-entry is enabled. Use /v1/checkout-sessions instead.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateStorePayment"}}}},"responses":{"201":{"description":"Queued checkout or replay with current checkout state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"503":{"$ref":"#/components/responses/Error"}}}},"/v1/checkout-sessions":{"post":{"operationId":"createCustomerCheckout","summary":"Create an ArvonaPay customer amount-entry session","description":"Requires payments:create, approved merchant server IP and Idempotency-Key. Send reference and customer.id/firstName/lastName/email. Amount, currency, FX rate, markup and commission fields are forbidden. Return customerCheckout.url to the customer. Verification is not configured; amount confirmation does not create a payment or release store handoff.","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCheckoutSession"}}}},"responses":{"201":{"description":"Created or replayed session","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSession"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/checkout-sessions/{id}":{"get":{"operationId":"getCustomerCheckout","summary":"Read your customer checkout state","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Current customer session; confirmed amount is not payment success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSession"}}}},"404":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"A server-side avp_test_ key from your merchant portal. Never expose it in browser or mobile code."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[-a-zA-Z0-9_.:]+$"}}},"responses":{"Error":{"description":"Structured error; retry only transient errors and keep the same idempotency key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"CreatePayment":{"type":"object","additionalProperties":false,"required":["reference","amount","currency","method","direction"],"properties":{"reference":{"type":"string","maxLength":120},"amount":{"type":"string","pattern":"^\\d{1,10}(\\.\\d{1,2})?$","examples":["1250.50"]},"currency":{"enum":["TRY","EUR","USD","GBP","AED","SAR","CHF"]},"method":{"enum":["BANK_TRANSFER","GATEWAY"]},"direction":{"enum":["DEPOSIT","WITHDRAWAL"]},"description":{"type":"string","maxLength":500},"customer":{"type":"object","additionalProperties":false,"description":"Legacy merchant context. xxxxpays uses POST /v1/checkout-sessions with customer.id (merchant UID), firstName, lastName and email. Merchant-supplied amounts and pricing parameters are not accepted on that endpoint.","properties":{"id":{"type":"string","maxLength":120},"email":{"type":"string","format":"email"},"phone":{"type":"string","pattern":"^\\+[1-9][0-9]{7,14}$"},"ip":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"username":{"type":"string","maxLength":120},"firstName":{"type":"string","maxLength":120},"lastName":{"type":"string","maxLength":120}}}}},"Payment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"merchantId":{"type":"string","format":"uuid"},"reference":{"type":"string"},"amount":{"type":"string"},"fee":{"type":"string"},"currency":{"type":"string"},"method":{"type":"string"},"direction":{"type":"string"},"environment":{"const":"sandbox"},"status":{"enum":["PENDING_APPROVAL","PENDING","SUCCEEDED","FAILED","CANCELLED","EXPIRED"]},"pricing":{"$ref":"#/components/schemas/PricingSnapshot"},"bankAccountId":{"type":["string","null"],"format":"uuid"},"createdAt":{"type":"string","format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"approvedAt":{"type":["string","null"],"format":"date-time"},"finalizedAt":{"type":["string","null"],"format":"date-time"},"checkout":{"type":"object","description":"Present on GET/detail and store-payment creation only. The URL is a bearer payment link; protect it. Store currency can differ from original merchant currency.","properties":{"store":{"const":"Dynostech"},"legalName":{"const":"Trainexa LLC"},"state":{"enum":["QUEUED","READY","REJECTED","SUCCEEDED","FAILED","EXPIRED"]},"chargeCurrency":{"const":"AED"},"chargeAmount":{"type":"string"},"url":{"type":["string","null"],"format":"uri"},"subtotal":{"type":["string","null"]},"discount":{"type":["string","null"]},"matchType":{"type":["string","null"]},"expiresAt":{"type":"string","format":"date-time"},"error":{"type":["string","null"]},"livePayment":{"const":false}}},"customer":{"type":["object","null"],"additionalProperties":false,"description":"Authorized detail response only. Not included in lists or webhook payloads.","properties":{"id":{"type":"string","maxLength":120},"email":{"type":"string","format":"email"},"phone":{"type":"string","pattern":"^\\+[1-9][0-9]{7,14}$"},"ip":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"username":{"type":"string","maxLength":120},"firstName":{"type":"string","maxLength":120},"lastName":{"type":"string","maxLength":120}}}}},"PricingSnapshot":{"type":["object","null"],"description":"Immutable commercial terms from creation time. Minor-unit values are integer strings in the indicated two-decimal currency. Internal provider costs and company profit are never included. Historical v0.1 payments may return null.","properties":{"schema":{"const":1},"fallback":{"type":"boolean"},"ruleId":{"type":["string","null"],"format":"uuid"},"ruleVersion":{"type":"integer"},"rateDay":{"type":"string","format":"date"},"timezone":{"const":"Asia/Dubai"},"originalCurrency":{"type":"string"},"chargeCurrency":{"type":"string"},"settlementCurrency":{"type":"string"},"baseRate":{"type":"string"},"effectiveRate":{"type":"string"},"settlementRate":{"type":"string"},"commissionBps":{"type":"integer"},"markupBps":{"type":"integer"},"bufferBps":{"type":"integer"},"reserveBps":{"type":"integer"},"amountMinor":{"type":"string"},"fee":{"type":"string"},"reserve":{"type":"string"},"merchantNet":{"type":"string"},"settlementNet":{"type":"string"},"gateway":{"type":"string"},"atBase":{"type":"string"},"markupIncome":{"type":"string"},"bufferIncome":{"type":"string"},"fxIncome":{"type":"string"},"delayDays":{"type":"integer"},"reserveDays":{"type":"integer"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string"}}}}},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"type":{"enum":["payment.succeeded","payment.failed","payment.expired"]},"createdAt":{"type":"string","format":"date-time"},"data":{"$ref":"#/components/schemas/Payment"}}},"CreateStorePayment":{"type":"object","additionalProperties":false,"required":["reference","amount","currency"],"properties":{"reference":{"type":"string","maxLength":120},"amount":{"type":"string","pattern":"^\\d{1,10}(\\.\\d{1,2})?$","examples":["1250.50"]},"currency":{"enum":["TRY","EUR","USD","GBP","AED","SAR","CHF"]},"description":{"type":"string","maxLength":500},"customer":{"type":"object","additionalProperties":false,"description":"Legacy merchant context. xxxxpays uses POST /v1/checkout-sessions with customer.id (merchant UID), firstName, lastName and email. Merchant-supplied amounts and pricing parameters are not accepted on that endpoint.","properties":{"id":{"type":"string","maxLength":120},"email":{"type":"string","format":"email"},"phone":{"type":"string","pattern":"^\\+[1-9][0-9]{7,14}$"},"ip":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"username":{"type":"string","maxLength":120},"firstName":{"type":"string","maxLength":120},"lastName":{"type":"string","maxLength":120}}}}},"CreateCheckoutSession":{"type":"object","additionalProperties":false,"required":["reference","customer"],"properties":{"reference":{"type":"string","maxLength":120},"customer":{"type":"object","additionalProperties":false,"description":"Legacy merchant context. xxxxpays uses POST /v1/checkout-sessions with customer.id (merchant UID), firstName, lastName and email. Merchant-supplied amounts and pricing parameters are not accepted on that endpoint.","properties":{"id":{"type":"string","maxLength":120},"email":{"type":"string","format":"email"},"phone":{"type":"string","pattern":"^\\+[1-9][0-9]{7,14}$"},"ip":{"type":"string"},"country":{"type":"string","pattern":"^[A-Z]{2}$"},"username":{"type":"string","maxLength":120},"firstName":{"type":"string","maxLength":120},"lastName":{"type":"string","maxLength":120}},"required":["id","firstName","lastName","email"]}}},"CheckoutSession":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"reference":{"type":"string"},"state":{"enum":["AWAITING_AMOUNT","QUOTED","AWAITING_VERIFICATION","EXPIRED"]},"customerCheckout":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"}}},"amount":{"type":["string","null"]},"currency":{"type":["string","null"]},"verification":{"type":"object","properties":{"state":{"const":"NOT_CONFIGURED"},"verified":{"const":false},"storeHandoffAllowed":{"const":false}}},"paymentId":{"type":"null"},"storeCheckoutUrl":{"type":"null"},"environment":{"const":"sandbox"},"livePayment":{"const":false}}}}}}