{"openapi":"3.1.0","info":{"title":"Jervis Pay API","version":"2026-10-01","description":"Payment orchestration and confirmation for direct-transfer payments (InstaPay, wallets) in Egypt.\nJervis Pay never holds or moves money. A receipt is evidence, not proof: a payment only\nsucceeds when the merchant confirms it (`assurance: merchant`).\n\nAuthenticate with a secret key: `Authorization: Bearer sk_test_…` or `sk_live_…`. The key\ndecides the project and the mode; test keys never see live data.\n\nWebhooks are signed: `Jervis-Signature: v1=<hex HMAC-SHA256 of \"<timestamp>.<raw body>\">`,\n`Jervis-Timestamp` (reject anything older than 300 s) and\n`Jervis-Event-Id`. Failed deliveries are retried immediately, 1 min, 5 min, 30 min, 120 min, 360 min, 1440 min. The event id never\nchanges between retries, so process events idempotently."},"servers":[{"url":"https://jervis-pay-api-42a71b70.apps.devops.jervis.cloud"}],"security":[{"secretKey":[]}],"tags":[{"name":"Checkout"},{"name":"Payments"},{"name":"Customers"},{"name":"Subscriptions","description":"Recurring billing by renewal payments the merchant confirms (spec §43)."},{"name":"Disputes","description":"Customer and merchant disputes about the Jervis status of a payment (spec §46)."},{"name":"Events"},{"name":"Test helpers","description":"Only with `sk_test_` keys (spec §41)."}],"paths":{"/v1/checkout-sessions":{"post":{"tags":["Checkout"],"operationId":"createCheckoutSession","summary":"Create a hosted checkout session","description":"Pass `amount` + `currency`, or a `priceId`. Redirect the customer to `url`.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"currency":{"type":"string","enum":["EGP"]},"priceId":{"type":"string","pattern":"^[A-Za-z0-9_]{1,64}$"},"description":{"type":"string","minLength":1,"maxLength":200},"orderId":{"type":"string","minLength":1,"maxLength":100},"customerId":{"type":"string","pattern":"^[A-Za-z0-9_]{1,64}$"},"customer":{"type":"object","properties":{"externalId":{"type":"string","minLength":1,"maxLength":100},"name":{"type":"string","minLength":1,"maxLength":120},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","pattern":"^\\+?[0-9 ()-]{6,20}$"},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40},"additionalProperties":{"type":"string","maxLength":500}}},"additionalProperties":false},"returnUrl":{"type":"string","maxLength":2048},"cancelUrl":{"type":"string","maxLength":2048},"expiresInMinutes":{"type":"integer","minimum":5,"maximum":1440},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40},"additionalProperties":{"type":"string","maxLength":500}}},"additionalProperties":false}}}},"responses":{"201":{"description":"The session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSession"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/checkout-sessions/{id}":{"get":{"tags":["Checkout"],"operationId":"getCheckoutSession","summary":"Retrieve a checkout session","parameters":[{"name":"id","in":"path","required":true,"description":"Checkout session id (`cs_…`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSession"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/payments":{"get":{"tags":["Payments"],"operationId":"listPayments","summary":"List payments, newest first","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"From `nextCursor`.","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["created","awaiting_payment","receipt_submitted","merchant_review","succeeded","rejected","expired","cancelled","disputed"]}}],"responses":{"200":{"description":"A page of payments.","content":{"application/json":{"schema":{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/payments/{id}":{"get":{"tags":["Payments"],"operationId":"getPayment","summary":"Retrieve a payment","description":"Fulfil an order only when `status` is `succeeded` (and `assurance` is `merchant`).","parameters":[{"name":"id","in":"path","required":true,"description":"Payment id (`pay_…`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The payment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/customers":{"post":{"tags":["Customers"],"operationId":"upsertCustomer","summary":"Create a customer, or update the one with the same `externalId`","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"externalId":{"type":"string","minLength":1,"maxLength":100},"name":{"type":"string","minLength":1,"maxLength":120},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","pattern":"^\\+?[0-9 ()-]{6,20}$"},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40},"additionalProperties":{"type":"string","maxLength":500}}},"additionalProperties":false}}}},"responses":{"200":{"description":"The customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"get":{"tags":["Customers"],"operationId":"listCustomers","summary":"List customers","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"From `nextCursor`.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of customers.","content":{"application/json":{"schema":{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/customers/{id}":{"get":{"tags":["Customers"],"operationId":"getCustomer","summary":"Retrieve a customer","parameters":[{"name":"id","in":"path","required":true,"description":"Customer id (`cus_…`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The customer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Customer"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/subscriptions":{"post":{"tags":["Subscriptions"],"operationId":"createSubscription","summary":"Start a subscription with a free trial","description":"Paid subscriptions start from a checkout session on a recurring `priceId` (with a customer): the subscription is created when the merchant confirms that first payment. This endpoint starts a free trial instead; the first renewal payment is issued shortly before the trial ends.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"priceId":{"type":"string","minLength":1,"maxLength":64},"trialDays":{"type":"integer","minimum":1,"maximum":365},"customerId":{"type":"string","minLength":1,"maxLength":64},"customer":{"type":"object","properties":{"externalId":{"type":"string","minLength":1,"maxLength":100},"name":{"type":"string","minLength":1,"maxLength":120},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","pattern":"^\\+?[0-9 ()-]{6,20}$"}},"additionalProperties":false},"metadata":{"type":"object","propertyNames":{"type":"string","minLength":1,"maxLength":40},"additionalProperties":{"type":"string","maxLength":500}}},"required":["priceId","trialDays"],"additionalProperties":false}}}},"responses":{"201":{"description":"The trialing subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}},"get":{"tags":["Subscriptions"],"operationId":"listSubscriptions","summary":"List subscriptions, newest first","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"From `nextCursor`.","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["trialing","active","past_due","cancelled","expired"]}},{"name":"customerId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of subscriptions.","content":{"application/json":{"schema":{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Subscription"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/subscriptions/{id}":{"get":{"tags":["Subscriptions"],"operationId":"getSubscription","summary":"Retrieve a subscription","parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id (`sub_…`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/subscriptions/{id}/cancel":{"post":{"tags":["Subscriptions"],"operationId":"cancelSubscription","summary":"Cancel now, or at the end of the current period","description":"Cancelling now voids the open renewal and cancels its payment unless a receipt was already submitted.","parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id (`sub_…`).","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"atPeriodEnd":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/subscriptions/{id}/resume":{"post":{"tags":["Subscriptions"],"operationId":"resumeSubscription","summary":"Undo a cancellation scheduled for the period end","parameters":[{"name":"id","in":"path","required":true,"description":"Subscription id (`sub_…`).","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"responses":{"200":{"description":"The subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/events":{"get":{"tags":["Events"],"operationId":"listEvents","summary":"List events, newest first","description":"The same events webhooks deliver, with their delivery status.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"From `nextCursor`.","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string","enum":["payment.created","payment.awaiting_payment","receipt.submitted","payment.review_required","payment.succeeded","payment.rejected","payment.expired","payment.cancelled","subscription.created","subscription.due","subscription.succeeded","subscription.past_due","subscription.cancelled","subscription.expired","dispute.opened","dispute.resolved"]}}],"responses":{"200":{"description":"A page of events.","content":{"application/json":{"schema":{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/EventWithDeliveries"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/events/{id}":{"get":{"tags":["Events"],"operationId":"getEvent","summary":"Retrieve an event","parameters":[{"name":"id","in":"path","required":true,"description":"Event id (`evt_…`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventWithDeliveries"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/disputes":{"get":{"tags":["Disputes"],"operationId":"listDisputes","summary":"List disputes, newest first","description":"A customer disputes a rejection (\"I paid\"); the merchant disputes a confirmation (\"confirmed incorrectly\"). Disputes are decided by the merchant's team in the dashboard. Resolution changes the Jervis payment status only: Jervis Pay never moves or reverses money.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","description":"From `nextCursor`.","schema":{"type":"string"}},{"name":"status","in":"query","description":"`active` (still to decide), `resolved` (decided or withdrawn), or one status.","schema":{"type":"string","enum":["active","resolved","open","under_review","awaiting_customer","awaiting_merchant","resolved_customer","resolved_merchant","closed"]}},{"name":"paymentId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of disputes.","content":{"application/json":{"schema":{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Dispute"}},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}]}}}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/disputes/{id}":{"get":{"tags":["Disputes"],"operationId":"getDispute","summary":"Retrieve a dispute","parameters":[{"name":"id","in":"path","required":true,"description":"Dispute id (`dsp_…`).","schema":{"type":"string"}}],"responses":{"200":{"description":"The dispute.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Dispute"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/test-helpers/payments/{id}/simulate":{"post":{"tags":["Test helpers"],"operationId":"simulatePayment","summary":"Simulate a receipt, decision, expiry or dispute on a test payment","description":"`receipt` submits a simulated receipt (the payment waits for review). `confirm` and `reject` submit one first when needed, then decide. `expire` closes the payment window now. `dispute` opens a dispute: the merchant's on a succeeded payment, otherwise the customer's (rejecting an open payment first). `resolve_dispute` decides it for `outcome` (default `customer`). Live keys get `403 test_mode_only`.","parameters":[{"name":"id","in":"path","required":true,"description":"Test payment id (`pay_…`).","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["receipt","confirm","reject","expire","dispute","resolve_dispute"]},"reason":{"type":"string","enum":["not_received","wrong_amount","wrong_recipient","invalid_receipt","duplicate_receipt","expired","other"]},"outcome":{"type":"string","enum":["customer","merchant"]}},"required":["action"],"additionalProperties":false}}}},"responses":{"200":{"description":"The payment after the simulation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payment"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}},"/v1/test-helpers/subscriptions/{id}/simulate":{"post":{"tags":["Test helpers"],"operationId":"simulateSubscription","summary":"Move a test subscription through time","description":"`open_renewal`: the period ends in 24 h and its renewal payment is issued now. `end_period`: the period ends now (past due, or cancelled if scheduled). `end_grace`: the grace period ends now and an unpaid subscription expires. Live keys get `403 test_mode_only`.","parameters":[{"name":"id","in":"path","required":true,"description":"Test subscription id (`sub_…`).","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":false,"description":"Makes a retried POST safe: the same key returns the first response (spec §52).","schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["open_renewal","end_period","end_grace"]}},"required":["action"],"additionalProperties":false}}}},"responses":{"200":{"description":"The subscription after the simulation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Subscription"}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"}}}}},"webhooks":{"event":{"post":{"summary":"An event, POSTed to each subscribed endpoint","parameters":[{"name":"Jervis-Signature","in":"header","required":true,"schema":{"type":"string"}},{"name":"Jervis-Timestamp","in":"header","required":true,"schema":{"type":"string"}},{"name":"Jervis-Event-Id","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"2XX":{"description":"Received. Anything else is retried."}}}}},"components":{"securitySchemes":{"secretKey":{"type":"http","scheme":"bearer","description":"`sk_test_…` or `sk_live_…`. Server-side only."}},"responses":{"Error":{"description":"An error with a stable `code`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{"type":"array","items":{"type":"object","required":["path","message"],"properties":{"path":{"type":"string"},"message":{"type":"string"}}}}}}}},"Payment":{"type":"object","description":"A payment intent. Only `succeeded` means the merchant confirmed the money arrived.","required":["id","object","livemode","status","assurance","amount","currency","orderId","customerId","checkoutSessionId","subscriptionId","paymentMethodType","expiresAt","metadata","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"object":{"const":"payment"},"livemode":{"type":"boolean"},"status":{"type":"string","enum":["created","awaiting_payment","receipt_submitted","merchant_review","succeeded","rejected","expired","cancelled","disputed"]},"assurance":{"type":"string","enum":["none","evidence","merchant","network"]},"amount":{"type":"integer","description":"Integer minor units: 15000 = 150.00 EGP."},"currency":{"type":"string","enum":["EGP"]},"orderId":{"anyOf":[{"type":"string"},{"type":"null"}]},"customerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"checkoutSessionId":{"anyOf":[{"type":"string"},{"type":"null"}]},"subscriptionId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Set on subscription payments."},"paymentMethodType":{"anyOf":[{"type":"string","enum":["instapay","vodafone_cash","orange_cash","etisalat_cash","we_pay","bank_transfer","custom"]},{"type":"null"}]},"expiresAt":{"type":"string","format":"date-time"},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CheckoutSession":{"type":"object","required":["id","object","livemode","paymentId","url","status","amount","currency","orderId","customerId","productId","priceId","returnUrl","cancelUrl","expiresAt","createdAt"],"properties":{"id":{"type":"string"},"object":{"const":"checkout_session"},"livemode":{"type":"boolean"},"paymentId":{"type":"string"},"url":{"type":"string","description":"Redirect the customer here."},"status":{"type":"string","enum":["created","awaiting_payment","receipt_submitted","merchant_review","succeeded","rejected","expired","cancelled","disputed"]},"amount":{"type":"integer"},"currency":{"type":"string","enum":["EGP"]},"orderId":{"anyOf":[{"type":"string"},{"type":"null"}]},"customerId":{"anyOf":[{"type":"string"},{"type":"null"}]},"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"priceId":{"anyOf":[{"type":"string"},{"type":"null"}]},"returnUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"cancelUrl":{"anyOf":[{"type":"string"},{"type":"null"}]},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}},"Customer":{"type":"object","required":["id","object","livemode","externalId","name","email","phone","metadata","createdAt"],"properties":{"id":{"type":"string"},"object":{"const":"customer"},"livemode":{"type":"boolean"},"externalId":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"email":{"anyOf":[{"type":"string"},{"type":"null"}]},"phone":{"anyOf":[{"type":"string"},{"type":"null"}]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"}}},"SubscriptionRenewal":{"type":"object","description":"One period to pay, with its payment.","required":["id","object","subscriptionId","sequence","periodStart","periodEnd","dueAt","amount","currency","status","paymentId","checkoutUrl","paidAt","createdAt"],"properties":{"id":{"type":"string"},"object":{"const":"subscription_renewal"},"subscriptionId":{"type":"string"},"sequence":{"type":"integer","description":"Which period this renewal pays for (1 = first paid period)."},"periodStart":{"type":"string","format":"date-time"},"periodEnd":{"type":"string","format":"date-time"},"dueAt":{"type":"string","format":"date-time"},"amount":{"type":"integer"},"currency":{"type":"string","enum":["EGP"]},"status":{"type":"string","enum":["open","paid","void"]},"paymentId":{"anyOf":[{"type":"string"},{"type":"null"}]},"checkoutUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Send the customer here while the renewal is open."},"paidAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"}}},"Subscription":{"type":"object","description":"Grant access while `status` is `trialing` or `active` (`past_due`: your call).","required":["id","object","livemode","status","customerId","productId","priceId","amount","currency","interval","intervalCount","currentPeriodStart","currentPeriodEnd","trialEnd","cancelAtPeriodEnd","cancelledAt","endedAt","latestRenewal","metadata","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"object":{"const":"subscription"},"livemode":{"type":"boolean"},"status":{"type":"string","enum":["trialing","active","past_due","cancelled","expired"]},"customerId":{"type":"string"},"productId":{"type":"string"},"priceId":{"type":"string"},"amount":{"type":"integer"},"currency":{"type":"string","enum":["EGP"]},"interval":{"type":"string","enum":["day","week","month","year"]},"intervalCount":{"type":"integer"},"currentPeriodStart":{"type":"string","format":"date-time"},"currentPeriodEnd":{"type":"string","format":"date-time"},"trialEnd":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"cancelAtPeriodEnd":{"type":"boolean"},"cancelledAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"endedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"latestRenewal":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionRenewal"},{"type":"null"}]},"metadata":{"type":"object","additionalProperties":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Dispute":{"type":"object","description":"A dispute about a payment's Jervis status. While it is active the payment is `disputed`.","required":["id","object","livemode","paymentId","openedBy","reason","status","createdAt","updatedAt","resolvedAt"],"properties":{"id":{"type":"string"},"object":{"const":"dispute"},"livemode":{"type":"boolean"},"paymentId":{"type":"string"},"openedBy":{"type":"string","enum":["customer","merchant"]},"reason":{"type":"string","enum":["paid_but_rejected","confirmed_incorrectly"]},"status":{"type":"string","enum":["open","under_review","awaiting_customer","awaiting_merchant","resolved_customer","resolved_merchant","closed"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"resolvedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]}}},"Event":{"type":"object","description":"A webhook event (spec §36, §37).","required":["id","object","type","apiVersion","livemode","createdAt","data"],"properties":{"id":{"type":"string","description":"Immutable: identical on every retry."},"object":{"const":"event"},"type":{"type":"string","enum":["payment.created","payment.awaiting_payment","receipt.submitted","payment.review_required","payment.succeeded","payment.rejected","payment.expired","payment.cancelled","subscription.created","subscription.due","subscription.succeeded","subscription.past_due","subscription.cancelled","subscription.expired","dispute.opened","dispute.resolved"]},"apiVersion":{"const":"2026-10-01"},"livemode":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["object"],"properties":{"object":{"description":"The payment for `payment.*`, `receipt.*` and `dispute.*` events, the subscription for `subscription.*`.","anyOf":[{"$ref":"#/components/schemas/Payment"},{"$ref":"#/components/schemas/Subscription"}]},"disputeId":{"type":"string","description":"`dispute.*` only."},"openedBy":{"type":"string","enum":["customer","merchant"],"description":"`dispute.opened` only."},"resolution":{"type":"string","enum":["resolved_customer","resolved_merchant","closed"],"description":"`dispute.resolved` only. `closed` means the opener withdrew it. `object.status` is the payment status that follows: `succeeded` (grant access) or `rejected` (revoke it)."},"receiptId":{"type":"string","description":"`receipt.submitted` only."},"renewalId":{"type":"string","description":"`subscription.due` and `subscription.succeeded`."},"reason":{"type":"string","enum":["not_received","wrong_amount","wrong_recipient","invalid_receipt","duplicate_receipt","expired","other","merchant","period_end"],"description":"`payment.rejected`: the rejection reason. `subscription.cancelled`: `merchant` or `period_end`."}}}}},"EventWithDeliveries":{"type":"object","required":["id","object","type","apiVersion","livemode","createdAt","data"],"properties":{"id":{"type":"string","description":"Immutable: identical on every retry."},"object":{"const":"event"},"type":{"type":"string","enum":["payment.created","payment.awaiting_payment","receipt.submitted","payment.review_required","payment.succeeded","payment.rejected","payment.expired","payment.cancelled","subscription.created","subscription.due","subscription.succeeded","subscription.past_due","subscription.cancelled","subscription.expired","dispute.opened","dispute.resolved"]},"apiVersion":{"const":"2026-10-01"},"livemode":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"data":{"type":"object","required":["object"],"properties":{"object":{"description":"The payment for `payment.*`, `receipt.*` and `dispute.*` events, the subscription for `subscription.*`.","anyOf":[{"$ref":"#/components/schemas/Payment"},{"$ref":"#/components/schemas/Subscription"}]},"disputeId":{"type":"string","description":"`dispute.*` only."},"openedBy":{"type":"string","enum":["customer","merchant"],"description":"`dispute.opened` only."},"resolution":{"type":"string","enum":["resolved_customer","resolved_merchant","closed"],"description":"`dispute.resolved` only. `closed` means the opener withdrew it. `object.status` is the payment status that follows: `succeeded` (grant access) or `rejected` (revoke it)."},"receiptId":{"type":"string","description":"`receipt.submitted` only."},"renewalId":{"type":"string","description":"`subscription.due` and `subscription.succeeded`."},"reason":{"type":"string","enum":["not_received","wrong_amount","wrong_recipient","invalid_receipt","duplicate_receipt","expired","other","merchant","period_end"],"description":"`payment.rejected`: the rejection reason. `subscription.cancelled`: `merchant` or `period_end`."}}},"deliveries":{"type":"array","description":"Where this event was sent (event log only, not in webhook bodies).","items":{"type":"object","required":["id","endpointId","status","attempts"],"properties":{"id":{"type":"string"},"endpointId":{"type":"string"},"status":{"type":"string","enum":["pending","succeeded","failed"]},"attempts":{"type":"integer"}}}}}}}}}