Skip to content

Checkout

The browser half of a payment session: what a checkout page calls.

Endpoint What it does
GET /v1/checkout/sessions/{id} Retrieve a checkout session
POST /v1/checkout/sessions/{id}/confirm Confirm a checkout session
POST /v1/checkout/sessions/{id}/otp Submit a customer’s one-time code
POST /v1/checkout/sessions/{id}/otp/resend Send the customer a new one-time code

Try any of them in the API tester.

GET /v1/checkout/sessions/{id}

What a checkout page needs to render: the amount, the currency, the payee’s display name, the description and the channels this session accepts.

Requires the publishable key in Authorization AND the session’s client token in X-Paysigna-Client-Token. A wrong token and a wrong id are the same 404, so this endpoint cannot be used to discover which sessions exist.

This is also the POLLING endpoint. After confirming, call it until payment.status is terminal. The payment block is read live from the charge on every call, so it can never be stale.

It returns NOTHING about the merchant’s account, balances, fees, our partners or our risk controls, and never a full customer identifier.

Authentication: a publishable key (safe in a browser) with the scope payment_session.read.

Field Type Required Allowed values and limits What it is
X-Paysigna-Client-Token string yes The client token your server received when it created the session.
Field Type Required Allowed values and limits What it is
{id} string (uuid) yes The payment session’s id, which your server hands to the checkout page with the client token.
Field Type What it is
amount integer In minor units. Read-only: this endpoint cannot change it and neither can confirming.
channels array The channels this session accepts. Confirming with anything else is refused.
currency string ISO 4217 code of amount.
description string What the payment is for, to show the customer.
display_name string Who the customer is paying.
expires_at string (date-time) After this the session cannot be paid. Create a new one.
id string The session’s id.
object string
payment object
payment.action object
payment.action.attempts_remaining integer otp only: how many more incorrect codes are allowed before the charge fails.
payment.action.expires_at string (date-time) When the partner stops accepting this action, where it says. For otp, a code sent after this is refused; send a new one first if resendable.
payment.action.message string What to tell the customer, when the type alone does not say: for otp, where the code is (e-mailed to them, or shown in their bank’s app). Safe to show as is.
payment.action.resendable boolean otp only: the code can be sent to the customer again with POST /v1/charges/{id}/otp/resend.
payment.action.type string prompt: the customer approves a prompt on their phone. otp: they enter a one-time code, which you send to POST /v1/charges/{id}/otp. 3ds_redirect or hosted_checkout: send them to url. ussd: they dial a code (reserved, not currently used). One of: prompt, otp, 3ds_redirect, hosted_checkout, ussd
payment.action.url string Open this to complete authentication. Absent for a handset prompt.
payment.amount integer What the customer is actually debited, including any fee they bear.
payment.completed_at string (date-time) When the payment reached a final state.
payment.customer_masked string A partial identifier. The full value is never returned.
payment.failure_message string Safe to show the customer. PaySigna’s internal failure classification is not exposed.
payment.reference string Quote this to the merchant’s support, not to PaySigna.
payment.status string The payment’s state. Keep polling while it is initiated, pending, processing or awaiting_action; succeeded means paid; failed, cancelled or expired means nothing was collected. One of: initiated, pending, processing, awaiting_action, succeeded, failed, cancelled, expired, reversed, refunded, partially_refunded
return_url string Where to send the customer when the flow ends.
status string created: waiting for the customer. confirming: a confirmation is in progress. completed: a payment was started; read payment for its result. cancelled or expired: the session can no longer be paid. One of: created, confirming, completed, cancelled, expired
  • 400: the request is malformed
  • 401: the key is missing, wrong or revoked
  • 403: the key lacks the scope, or your account may not do this
  • 404: no such resource on this account
  • 422: a field is invalid; errors names it
  • 429: too many requests; wait for Retry-After
  • 500: Internal Server Error
  • 503: the payment partner is unreachable; safe to retry

Every error is a JSON problem with a stable code. See Errors.


POST /v1/checkout/sessions/{id}/confirm

Submits the customer’s choice of channel and their account, and creates the charge.

THERE IS NO AMOUNT IN THIS REQUEST. There is no currency and no fee bearer either. All three were fixed on the session by your secret key and are read back out of it here, so a page you do not fully control — or one an attacker has modified — cannot change what is charged.

IDEMPOTENT WITHOUT A HEADER. A customer double-tapping, or a page reloading while the prompt is on their handset, cannot produce two charges: a conditional UPDATE decides which request proceeds and the charge is created under a key derived from the session id. A second confirmation of a session that is already done returns the FIRST one’s result with 200, not an error. One arriving while another is genuinely in flight gets 409; retry in a second.

A 202-like outcome is normal: most payments come back pending or awaiting_action and complete asynchronously. Poll GET /v1/checkout/sessions/{id} or wait for your webhook.

An expired session is refused here on its own authority, not when a sweeper gets round to it.

Authentication: a publishable key (safe in a browser) with the scope payment_session.confirm.

Field Type Required Allowed values and limits What it is
X-Paysigna-Client-Token string yes The client token your server received when it created the session.
Field Type Required Allowed values and limits What it is
{id} string (uuid) yes The payment session’s id, which your server hands to the checkout page with the client token.
Field Type Required Allowed values and limits What it is
bank string no at most 30 characters The bank’s code. Required for bank unless bank_id is sent instead.
bank_id string (uuid) no The bank’s id from /v1/reference/banks. An alternative to bank; send one, not both.
channel string yes One of: mobile_money, bank, card Must be one of the channels the session lists.
customer object yes
customer.email string (email) no at most 255 characters; e.g. [email protected] Used only when the session has no email. A card payment needs one.
customer.identifier string no at most 100 characters The customer’s mobile-money number or bank account. Optional for card, where the email is used.
customer.name string no at most 150 characters; e.g. Ama Mensah The payer’s name. Takes precedence over a name pre-filled on the session.
momo_network string no at most 30 characters; e.g. mtn The network’s code, such as mtn, telecel or airteltigo. Required for mobile_money unless momo_network_id is sent instead.
momo_network_id string (uuid) no The network’s id from /v1/reference/momo-networks. An alternative to momo_network; send one, not both.
Terminal window
curl -X POST https://sandbox.paysigna.com/v1/checkout/sessions/{id}/confirm \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"channel": "mobile_money",
"customer": {
"email": "[email protected]",
"name": "Ama Mensah"
},
"momo_network": "mtn"
}'
Field Type What it is
amount integer In minor units. Read-only: this endpoint cannot change it and neither can confirming.
channels array The channels this session accepts. Confirming with anything else is refused.
currency string ISO 4217 code of amount.
description string What the payment is for, to show the customer.
display_name string Who the customer is paying.
expires_at string (date-time) After this the session cannot be paid. Create a new one.
id string The session’s id.
object string
payment object
payment.action object
payment.action.attempts_remaining integer otp only: how many more incorrect codes are allowed before the charge fails.
payment.action.expires_at string (date-time) When the partner stops accepting this action, where it says. For otp, a code sent after this is refused; send a new one first if resendable.
payment.action.message string What to tell the customer, when the type alone does not say: for otp, where the code is (e-mailed to them, or shown in their bank’s app). Safe to show as is.
payment.action.resendable boolean otp only: the code can be sent to the customer again with POST /v1/charges/{id}/otp/resend.
payment.action.type string prompt: the customer approves a prompt on their phone. otp: they enter a one-time code, which you send to POST /v1/charges/{id}/otp. 3ds_redirect or hosted_checkout: send them to url. ussd: they dial a code (reserved, not currently used). One of: prompt, otp, 3ds_redirect, hosted_checkout, ussd
payment.action.url string Open this to complete authentication. Absent for a handset prompt.
payment.amount integer What the customer is actually debited, including any fee they bear.
payment.completed_at string (date-time) When the payment reached a final state.
payment.customer_masked string A partial identifier. The full value is never returned.
payment.failure_message string Safe to show the customer. PaySigna’s internal failure classification is not exposed.
payment.reference string Quote this to the merchant’s support, not to PaySigna.
payment.status string The payment’s state. Keep polling while it is initiated, pending, processing or awaiting_action; succeeded means paid; failed, cancelled or expired means nothing was collected. One of: initiated, pending, processing, awaiting_action, succeeded, failed, cancelled, expired, reversed, refunded, partially_refunded
return_url string Where to send the customer when the flow ends.
status string created: waiting for the customer. confirming: a confirmation is in progress. completed: a payment was started; read payment for its result. cancelled or expired: the session can no longer be paid. One of: created, confirming, completed, cancelled, expired
  • 400: the request is malformed
  • 401: the key is missing, wrong or revoked
  • 402: your balance cannot cover it
  • 403: the key lacks the scope, or your account may not do this
  • 404: no such resource on this account
  • 409: it conflicts with the current state, or the idempotency key was used for a different request
  • 422: a field is invalid; errors names it
  • 429: too many requests; wait for Retry-After
  • 500: Internal Server Error
  • 502: the payment partner refused it
  • 503: the payment partner is unreachable; safe to retry
  • 504: the partner timed out; read the resource before retrying

Every error is a JSON problem with a stable code. See Errors.


POST /v1/checkout/sessions/{id}/otp

When payment.action.type is otp, send the code the customer received. The answer is the session, as GET returns it. The payment may ask for a SECOND code (an enrolment code first, then the payment code): keep asking while payment.action.type is otp.

A wrong code is a 422 otp_rejected and the payment keeps waiting; payment.action.attempts_remaining says how many tries are left. After the last one the payment fails (otp_attempts_exceeded). Two submissions at once reach the partner once: the second gets 409 request_in_progress.

Authentication: a publishable key (safe in a browser) with the scope payment_session.confirm.

Field Type Required Allowed values and limits What it is
X-Paysigna-Client-Token string yes The client token your server received when it created the session.
Field Type Required Allowed values and limits What it is
{id} string (uuid) yes The payment session’s id.
Field Type Required Allowed values and limits What it is
code string yes at most 12 characters The code the customer received.
Terminal window
curl -X POST https://sandbox.paysigna.com/v1/checkout/sessions/{id}/otp \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"code": "string"
}'
Field Type What it is
amount integer In minor units. Read-only: this endpoint cannot change it and neither can confirming.
channels array The channels this session accepts. Confirming with anything else is refused.
currency string ISO 4217 code of amount.
description string What the payment is for, to show the customer.
display_name string Who the customer is paying.
expires_at string (date-time) After this the session cannot be paid. Create a new one.
id string The session’s id.
object string
payment object
payment.action object
payment.action.attempts_remaining integer otp only: how many more incorrect codes are allowed before the charge fails.
payment.action.expires_at string (date-time) When the partner stops accepting this action, where it says. For otp, a code sent after this is refused; send a new one first if resendable.
payment.action.message string What to tell the customer, when the type alone does not say: for otp, where the code is (e-mailed to them, or shown in their bank’s app). Safe to show as is.
payment.action.resendable boolean otp only: the code can be sent to the customer again with POST /v1/charges/{id}/otp/resend.
payment.action.type string prompt: the customer approves a prompt on their phone. otp: they enter a one-time code, which you send to POST /v1/charges/{id}/otp. 3ds_redirect or hosted_checkout: send them to url. ussd: they dial a code (reserved, not currently used). One of: prompt, otp, 3ds_redirect, hosted_checkout, ussd
payment.action.url string Open this to complete authentication. Absent for a handset prompt.
payment.amount integer What the customer is actually debited, including any fee they bear.
payment.completed_at string (date-time) When the payment reached a final state.
payment.customer_masked string A partial identifier. The full value is never returned.
payment.failure_message string Safe to show the customer. PaySigna’s internal failure classification is not exposed.
payment.reference string Quote this to the merchant’s support, not to PaySigna.
payment.status string The payment’s state. Keep polling while it is initiated, pending, processing or awaiting_action; succeeded means paid; failed, cancelled or expired means nothing was collected. One of: initiated, pending, processing, awaiting_action, succeeded, failed, cancelled, expired, reversed, refunded, partially_refunded
return_url string Where to send the customer when the flow ends.
status string created: waiting for the customer. confirming: a confirmation is in progress. completed: a payment was started; read payment for its result. cancelled or expired: the session can no longer be paid. One of: created, confirming, completed, cancelled, expired
  • 400: the request is malformed
  • 401: the key is missing, wrong or revoked
  • 403: the key lacks the scope, or your account may not do this
  • 404: no such resource on this account
  • 409: it conflicts with the current state, or the idempotency key was used for a different request
  • 422: a field is invalid; errors names it
  • 429: too many requests; wait for Retry-After
  • 500: Internal Server Error
  • 502: the payment partner refused it
  • 503: the payment partner is unreachable; safe to retry
  • 504: the partner timed out; read the resource before retrying

Every error is a JSON problem with a stable code. See Errors.


POST /v1/checkout/sessions/{id}/otp/resend

Only when payment.action.resendable is true; otherwise 422 unsupported. Attempts already used still count.

Authentication: a publishable key (safe in a browser) with the scope payment_session.confirm.

Field Type Required Allowed values and limits What it is
X-Paysigna-Client-Token string yes The client token your server received when it created the session.
Field Type Required Allowed values and limits What it is
{id} string (uuid) yes The payment session’s id.
Field Type What it is
amount integer In minor units. Read-only: this endpoint cannot change it and neither can confirming.
channels array The channels this session accepts. Confirming with anything else is refused.
currency string ISO 4217 code of amount.
description string What the payment is for, to show the customer.
display_name string Who the customer is paying.
expires_at string (date-time) After this the session cannot be paid. Create a new one.
id string The session’s id.
object string
payment object
payment.action object
payment.action.attempts_remaining integer otp only: how many more incorrect codes are allowed before the charge fails.
payment.action.expires_at string (date-time) When the partner stops accepting this action, where it says. For otp, a code sent after this is refused; send a new one first if resendable.
payment.action.message string What to tell the customer, when the type alone does not say: for otp, where the code is (e-mailed to them, or shown in their bank’s app). Safe to show as is.
payment.action.resendable boolean otp only: the code can be sent to the customer again with POST /v1/charges/{id}/otp/resend.
payment.action.type string prompt: the customer approves a prompt on their phone. otp: they enter a one-time code, which you send to POST /v1/charges/{id}/otp. 3ds_redirect or hosted_checkout: send them to url. ussd: they dial a code (reserved, not currently used). One of: prompt, otp, 3ds_redirect, hosted_checkout, ussd
payment.action.url string Open this to complete authentication. Absent for a handset prompt.
payment.amount integer What the customer is actually debited, including any fee they bear.
payment.completed_at string (date-time) When the payment reached a final state.
payment.customer_masked string A partial identifier. The full value is never returned.
payment.failure_message string Safe to show the customer. PaySigna’s internal failure classification is not exposed.
payment.reference string Quote this to the merchant’s support, not to PaySigna.
payment.status string The payment’s state. Keep polling while it is initiated, pending, processing or awaiting_action; succeeded means paid; failed, cancelled or expired means nothing was collected. One of: initiated, pending, processing, awaiting_action, succeeded, failed, cancelled, expired, reversed, refunded, partially_refunded
return_url string Where to send the customer when the flow ends.
status string created: waiting for the customer. confirming: a confirmation is in progress. completed: a payment was started; read payment for its result. cancelled or expired: the session can no longer be paid. One of: created, confirming, completed, cancelled, expired
  • 400: the request is malformed
  • 401: the key is missing, wrong or revoked
  • 403: the key lacks the scope, or your account may not do this
  • 404: no such resource on this account
  • 409: it conflicts with the current state, or the idempotency key was used for a different request
  • 422: a field is invalid; errors names it
  • 429: too many requests; wait for Retry-After
  • 500: Internal Server Error
  • 502: the payment partner refused it
  • 503: the payment partner is unreachable; safe to retry
  • 504: the partner timed out; read the resource before retrying

Every error is a JSON problem with a stable code. See Errors.