Resolve a payment session only from an authoritative provider result. Authenticate Store API requests with the installation token for the app that owns the session.
Payment-session endpoints#
Purpose |
Request |
Required scope |
|---|---|---|
Read a payment session assigned to your app |
|
|
Report a pending or final result |
|
|
Every resolution echoes the session's exact major-unit amount and ISO currency_code. Tringify rejects an invalid currency, excess precision, or any value that differs from the durable session.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
|
|
string |
Yes |
The session's exact amount as a decimal string. |
|
string |
Yes |
The session's ISO currency code. |
|
string |
For |
The provider's stable identifier for the captured payment. |
|
string |
No |
For |
|
string |
No |
For |
Resolve a successful payment#
{
"amount": "1499.00",
"currency_code": "USD",
"provider_transaction_id": "provider_payment_…",
"status": "paid"
}
A paid result requires the provider's stable transaction identifier. Tringify atomically records the captured payment and order transaction; the identifier is retained for reconciliation and original-payment refunds.
Resolve a failed payment#
{
"amount": "1499.00",
"currency_code": "USD",
"failure_code": "PAYMENT_DECLINED",
"failure_message": "The provider declined the payment.",
"status": "failed"
}
Pending and terminal results#
Use pending while the provider payment object can still accept or complete another attempt. An attempt-level failure is not a terminal session result when the same provider order remains retryable. Reconcile the provider's complete payment object before resolving. Repeating the same result is idempotent. paid is immutable and cannot be replaced by failed; an authoritative late paid result may promote a session previously reported as failed, expired, or cancelled. Stale non-paid results after expiry or cancellation are acknowledged without changing the session. If Tringify does not receive your charge response before you have resolved the session, it fails the session and the shopper may start a replacement attempt with a new session_id; see Accept a payment. Keep reconciling the first provider payment and resolve it against its own session_id; never report one provider payment on a different session.
Expiry and late settlement#
expires_at ends the shopper's attempt in checkout, not the provider's ability to settle it. Do not assume a fixed limit: honor the expires_at in each charge request. Without a checkout stock hold it is 30 minutes after the charge request; when the checkout holds stock, it is the end of that hold, which follows the store's configured checkout duration and can be up to 120 minutes away. After it passes, Tringify marks an unresolved session expired and checkout stops waiting for it; another attempt gets a new session_id. Where the provider allows it, make the provider payment stop accepting payment at expires_at. If the provider still captures it later, resolve the session as paid: Tringify accepts the late result and records the money. When the order no longer needs it, because another attempt paid it, it was cancelled, or its stock could not be held again, Tringify refunds that payment through your refund endpoint. Late pending and failed results for an expired session are acknowledged without change. Your app cannot be uninstalled for 7 days after a session's last activity, so it can still report these late captures.
Resolve errors#
HTTP status |
Code |
When |
|---|---|---|
400 |
|
|
400 |
|
|
400 |
|
The body carries card-like data. |
403 |
|
The request does not use the installation token of the app assigned to the session. |
403 |
|
The session belongs to another app. |
404 |
|
There is no such session in this store. |
409 |
|
|
409 |
|
|
A 2xx response returns the session. Repeating the current result, a stale pending or failed result for a failed, expired, or cancelled session, and pending for a paid session are accepted without change. A different provider_transaction_id reported as paid on a session that is already paid is recorded as a duplicate capture and refunded through your refund endpoint. Retry a 5xx response with the same body.
Receive a refund request#
Tringify sends a signed request to the refund endpoint pinned to the declaration that created the payment. refund_id is the idempotency key. The exact amount and currency come from Tringify's durable refund record and may represent a full or partial refund.
{
"refund_id": "refund_…",
"session_id": "session_…",
"store_id": "store_…",
"order_id": "order_…",
"provider_transaction_id": "provider_payment_…",
"amount": "499.00",
"currency_code": "USD",
"reason": "Customer return"
}
{
"success": true,
"provider_refund_id": "provider_refund_…",
"status": "refunded"
}
Resolve an asynchronous refund#
Return pending when the provider accepted the refund without a terminal result. After provider reconciliation, call POST /api/2025-01/payments/refunds/{refund_id}/resolve with write_payment_sessions. The app and original payment ownership are verified before the transition is accepted.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
|
|
string |
No |
The provider's identifier for the refund. |
|
string |
No |
For |
|
string |
No |
For |
{
"provider_refund_id": "provider_refund_…",
"status": "refunded"
}
{
"failure_code": "INSUFFICIENT_BALANCE",
"failure_message": "The provider account balance cannot cover this refund.",
"provider_refund_id": "provider_refund_…",
"status": "failed"
}
A refund may transition from pending to refunded or failed. Repeating the same terminal result is idempotent. A late verified success may replace failed; a completed refunded result is immutable. Report verified late success even if another refund has since completed: Tringify records the money movement and flags discrepancies for the merchant without repeating inventory returns.
HTTP status |
Code |
When |
|---|---|---|
400 |
|
The body is not a JSON object of the fields above, has an unknown field, or includes |
400 |
|
|
403 |
|
The refunded payment was not collected by your app. |
404 |
|
There is no such refund in this store. |
409 |
|
The transition is not allowed: a |
A 2xx response means the result was recorded, or that it repeats the refund's current final result.
Refund retries and deadlines#
Tringify repeats a refund request, with the same refund_id, amount, and currency, when it gets no usable answer: a timeout, a transport failure, a refused redirect, a status of 400 or above, an unreadable body, or a successful response without a valid status. It sends at most 10 requests; the waits between them are 2, 4, 8, 16, 32, 64, 128, 256, 256 minutes, about 13 hours in all. A response with success: false and no status counts as failed. Once you answer refunded or failed, the result is final, apart from a later verified success. Once you answer pending, Tringify sends no more requests; resolve the refund through the Store API when the provider reaches a final result.
If all 10 requests go unanswered, the refund stays pending, marked as needing reconciliation, and its amount stays reserved; Tringify does not send it again. Look the refund up at the provider by refund_id and resolve it as refunded or failed. A pending refund has no resolution deadline, but the merchant cannot uninstall your app while one is open. Never answer failed for a refund whose outcome you do not know: answer pending and reconcile.