Get checkout

Supports guest users.

Returns the current state of a checkout.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…

Why this endpoint exists

Two jobs.

Re-read the priced basket. The response is the same Checkout object Create returns, freshly priced. Use it to re-render a review page after a reload, or to check the remaining time on the reservation.

Find out whether payment succeeded. This is the important one. The payment provider tells the platform the outcome asynchronously, and the customer's return to your return_url carries no trustworthy status. This endpoint is how you learn the truth.

Request

curl "https://api.acc.funtrips.io/v2/checkouts/$CHECKOUT_ID" \
  -H "x-campaign-id: $CAMPAIGN_ID" \
  -H "Authorization: Bearer $END_USER_TOKEN"

The response is a Checkout object — see Create for the full field walkthrough. After Confirm it also carries payment_url.

Polling after the redirect

The customer lands back on your return_url. You do not know yet whether they paid.

CREATED / OPEN            → not confirmed; they abandoned the payment page
PENDING_PAYMENT           → confirmed, outcome not in yet — keep polling
SUCCESS                   → paid. Tickets are being issued
FAILED                    → declined, or the reservation expired

SUCCESS and FAILED are terminal; stop polling. PENDING_PAYMENT means the provider has not reported yet.

Poll with backoff — start around 1 second, back off to a few seconds, and give up after roughly 60. Then show a "we are still processing your payment, you will receive an e-mail" page rather than spinning forever. The order is not lost; the confirmation e-mail goes out independently of whether your page is still open.

async function awaitOutcome(checkoutId, campaignId) {
  const terminal = new Set(['SUCCESS', 'FAILED']);
  let delay = 1000;

  for (let attempt = 0; attempt < 12; attempt++) {
    const res = await fetch(`${BASE}/checkouts/${checkoutId}`, {
      headers: { 'x-campaign-id': campaignId },
    });
    if (res.status === 404) return 'EXPIRED';

    const { data } = await res.json();
    if (terminal.has(data.status)) return data.status;

    await new Promise(r => setTimeout(r, delay));
    delay = Math.min(delay * 1.5, 5000);
  }
  return 'PENDING';
}

A SUCCESS immediately on the first poll is normal — a fast provider can report before Confirm even returned to you.

📘

SUCCESS means paid, not "tickets ready".

Fulfillment runs after capture: barcodes get assigned, a PDF is produced, an e-mail goes out. For a signed-in customer, GET /me/fulfillment/orders shows the tickets once they exist and returns an empty tickets array until then. Guests receive theirs by e-mail.

Access control

The rule differs by how the checkout was created, and it is worth being precise about because it affects how you handle checkout_id.

Guest checkouts have no owner. The checkout_id is the credential — anyone who holds it can read the checkout. That is what makes guest checkout work without a session.

Signed-in checkouts are bound to their customer. Only the same authenticated user can read them. Any other caller — different user, or no token — gets 404, never 403, so ids cannot be probed across accounts.

Treat a guest checkout_id as a secret.

Keep it out of URLs you log, analytics pageviews, referrer headers and error reports. It grants read access to the customer's basket and, after Confirm, their payment URL.

Errors

StatustypeMeaning
401A token was sent and rejected as structurally invalid
404checkout-not-foundUnknown id — or it belongs to a different customer
404checkout-reservation-expiredThe reservation window elapsed
500Unexpected fault. Retryable

For reconciliation — matching a charge against a provider statement, or handing support a PSP reference — read the payment record instead; a refund is recorded there and does not move the checkout back out of SUCCESS.

Both 404s are worth distinguishing in your UI: checkout-not-found is "we cannot find that", checkout-reservation-expired is "your basket timed out, let's rebuild it". Branch on type.

Path Params
uuid
required
Headers
uuid
required

Campaign scope for this request. Filters content to the specified campaign.

string
enum
Defaults to application/json

Generated from available response content types

Allowed:
Responses

Language
Credentials
Header
URL
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json
application/problem+json