Skip to content

Payment sessions

Fix an amount on your server, then let your checkout page collect it.

Endpoint What it does
POST /v1/payment_sessions Create a payment session
GET /v1/payment_sessions/{id} Retrieve a payment session
POST /v1/payment_sessions/{id}/cancel Cancel a payment session

Try any of them in the API tester.

POST /v1/payment_sessions

Opens a hosted-checkout session and returns a short-lived client token for your page.

THE AMOUNT IS FIXED HERE. amount, currency, fee_bearer and channels are recorded on the session by this call, with your secret key, and nothing the customer’s browser sends can change any of them. Confirming reads them back out of the session.

client_token is returned ONCE and is not recoverable: we store only a digest. Pass it to your page and do not log it or put it in a URL, where it would end up in browser history and in every referrer header the page emits.

The session and its token live for 15 minutes by default and 30 at the most. That covers a customer reading the page, choosing a network, typing a number and approving a handset prompt, with one retry. A longer window is not available: create a second session instead.

No Idempotency-Key is required. A duplicate session moves no money; use the token the successful call returned and let the other session expire.

Authentication: a secret key (server-side only) with the scope payment_session.create.

Field Type Required Allowed values and limits What it is
amount integer yes min 1; e.g. 1250 Amount in minor units — 1250 is GHS 12.50. FIXED once the session is created; the customer’s browser cannot change it.
callback_url string (uri) no HTTPS only.
channels array no Channels this session may be paid with. Omit for every channel your account is enabled for. A channel you are not enabled for is refused here rather than at checkout.
currency string yes exactly 3 characters; e.g. GHS The currency of amount, as an ISO 4217 code such as GHS. Supported currencies are listed at /v1/reference/currencies.
customer object no
customer.email string (email) no at most 255 characters; e.g. [email protected] Where the receipt goes. Takes precedence over an email the customer types at checkout, and is needed for a card payment unless the customer supplies one.
customer.id string (uuid) no An existing PaySigna customer id.
customer.name string no at most 150 characters; e.g. Ama Mensah Pre-fills the payer’s name. A name the customer types at checkout takes precedence.
description string no at most 500 characters Shown to the customer on the checkout page.
expires_in_seconds integer no min 60; max 1800 How long the session and its client token live. Default 900 (15 minutes), maximum 1800. Clamped, not refused.
fee_bearer string no One of: merchant, customer Only honoured if your account permits per-transaction choice.
metadata object no Returned on your own reads. NEVER returned to the browser.
reference string no at most 100 characters Your own identifier for this payment. Never shown to the customer.
return_url string (uri) no Where to send the customer when the flow ends. HTTPS only.
Terminal window
curl -X POST https://sandbox.paysigna.com/v1/payment_sessions \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{
"amount": 1250,
"currency": "GHS"
}'
Field Type What it is
amount integer In minor units. Fixed; nothing can change it.
cancelled_at string (date-time) When you cancelled the session.
channels array The channels the customer may pay with: mobile_money, bank or card.
client_token string Shown once, on creation. Give it to your checkout page. Not recoverable.
completed_at string (date-time) When the customer confirmed and a charge was created.
confirm_attempts integer How many times the customer has tried to confirm. A session allows at most 5.
created_at string (date-time) When the session was created.
currency string ISO 4217 code of amount.
description string Shown to the customer on the checkout page.
display_name string The payee name shown to the customer.
expired_at string (date-time) When the session expired unpaid.
expires_at string (date-time) After this the session cannot be paid.
fee_bearer string Who pays the fees: merchant (deducted from what you receive) or customer (added to what they pay). Absent means your account’s default. One of: merchant, customer
id string The session’s id. Pass it to your checkout page with the client token.
metadata object The metadata you sent, unchanged.
object string
return_url string Where the customer is sent when the flow ends.
status string The SESSION’s state, not the payment’s. Once it is completed a charge exists; read the charge for whether the money moved. One of: created, confirming, completed, cancelled, expired
transaction_id string The charge this session produced. Read it at /v1/charges/{id} for the payment’s state.
url string Shown once, on creation: PaySigna’s hosted payment page for this session, with your branding. Send the customer here if you are not building your own checkout page. It carries the client token after #, which browsers never send to a server.
your_reference string The reference you sent when creating the session.
  • 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
  • 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
  • 503: the payment partner is unreachable; safe to retry

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


GET /v1/payment_sessions/{id}

Reads a session’s own state: whether it has been confirmed, cancelled or expired, and which charge it produced.

status describes the SESSION, not the payment. Once it is completed a charge exists at transaction_id, and that charge is the authority on whether the money moved — this endpoint deliberately carries no copy of its status, because two records of one fact drift. Read /v1/charges/{id} for the payment.

Authentication: a secret key (server-side only) with the scope payment_session.read.

Field Type Required Allowed values and limits What it is
{id} string (uuid) yes The payment session’s id, as returned when it was created.
Field Type What it is
amount integer In minor units. Fixed; nothing can change it.
cancelled_at string (date-time) When you cancelled the session.
channels array The channels the customer may pay with: mobile_money, bank or card.
client_token string Shown once, on creation. Give it to your checkout page. Not recoverable.
completed_at string (date-time) When the customer confirmed and a charge was created.
confirm_attempts integer How many times the customer has tried to confirm. A session allows at most 5.
created_at string (date-time) When the session was created.
currency string ISO 4217 code of amount.
description string Shown to the customer on the checkout page.
display_name string The payee name shown to the customer.
expired_at string (date-time) When the session expired unpaid.
expires_at string (date-time) After this the session cannot be paid.
fee_bearer string Who pays the fees: merchant (deducted from what you receive) or customer (added to what they pay). Absent means your account’s default. One of: merchant, customer
id string The session’s id. Pass it to your checkout page with the client token.
metadata object The metadata you sent, unchanged.
object string
return_url string Where the customer is sent when the flow ends.
status string The SESSION’s state, not the payment’s. Once it is completed a charge exists; read the charge for whether the money moved. One of: created, confirming, completed, cancelled, expired
transaction_id string The charge this session produced. Read it at /v1/charges/{id} for the payment’s state.
url string Shown once, on creation: PaySigna’s hosted payment page for this session, with your branding. Send the customer here if you are not building your own checkout page. It carries the client token after #, which browsers never send to a server.
your_reference string The reference you sent when creating the session.
  • 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/payment_sessions/{id}/cancel

Withdraws a session nobody has paid yet. The client token stops working immediately — there is no denylist and no cache to wait for, because the token is a lookup key and this is its row.

Only a session in created can be cancelled. One that is mid-confirmation would race the charge, and one that is completed has already been sent to a partner: the answer there is a refund, not a cancellation.

Authentication: a secret key (server-side only) with the scope payment_session.create.

Field Type Required Allowed values and limits What it is
{id} string (uuid) yes The payment session to cancel. Only a session still in created status can be cancelled.
Field Type Required Allowed values and limits What it is
reason string no at most 200 characters Recorded for your own audit. Never shown to the customer.
Terminal window
curl -X POST https://sandbox.paysigna.com/v1/payment_sessions/{id}/cancel \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-d '{}'
Field Type What it is
amount integer In minor units. Fixed; nothing can change it.
cancelled_at string (date-time) When you cancelled the session.
channels array The channels the customer may pay with: mobile_money, bank or card.
client_token string Shown once, on creation. Give it to your checkout page. Not recoverable.
completed_at string (date-time) When the customer confirmed and a charge was created.
confirm_attempts integer How many times the customer has tried to confirm. A session allows at most 5.
created_at string (date-time) When the session was created.
currency string ISO 4217 code of amount.
description string Shown to the customer on the checkout page.
display_name string The payee name shown to the customer.
expired_at string (date-time) When the session expired unpaid.
expires_at string (date-time) After this the session cannot be paid.
fee_bearer string Who pays the fees: merchant (deducted from what you receive) or customer (added to what they pay). Absent means your account’s default. One of: merchant, customer
id string The session’s id. Pass it to your checkout page with the client token.
metadata object The metadata you sent, unchanged.
object string
return_url string Where the customer is sent when the flow ends.
status string The SESSION’s state, not the payment’s. Once it is completed a charge exists; read the charge for whether the money moved. One of: created, confirming, completed, cancelled, expired
transaction_id string The charge this session produced. Read it at /v1/charges/{id} for the payment’s state.
url string Shown once, on creation: PaySigna’s hosted payment page for this session, with your branding. Send the customer here if you are not building your own checkout page. It carries the client token after #, which browsers never send to a server.
your_reference string The reference you sent when creating the session.
  • 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
  • 503: the payment partner is unreachable; safe to retry

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