Payins Quickstart

Accept your first payment in sandbox: create a checkout, pay it with a test card on the hosted page, and confirm the result from your server.

This walkthrough collects 49.99 USD from a test buyer in sandbox, using the hosted checkout page. Run the steps in order. It takes about 5 minutes.

Before you start

  • Sandbox API credentials with the Merchant Write permission (the User role or higher). See Permissions.
  • USD enabled for payins on your sandbox account. Your Payment Labs contact sets which currencies you accept.
  • A browser, to pay as the buyer.
  • Your terms of service and privacy policy URLs. The buyer sees links to both on the payment page.
export BASE_URL="https://api-sandbox.paymentlabs.io"

Step 1: Get a token

Call Create Access Token with your client ID and secret.

export TOKEN=$(curl -s -X POST "$BASE_URL/login" \
  -H "Content-Type: application/json" \
  -d '{"method": "client-secret", "key": "<client-id>", "secret": "<secret>"}' | jq -r .token)
const BASE_URL = "https://api-sandbox.paymentlabs.io";

const { token } = await fetch(`${BASE_URL}/login`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ method: "client-secret", key: process.env.PL_CLIENT_ID, secret: process.env.PL_SECRET }),
}).then((r) => r.json() as Promise<{ token: string }>);

This is the single Payment Labs login: the same operation and token serve payins, payouts and every other API. See Environments and Authentication.

Step 2: Create a checkout

A checkout is a request for one payment from one buyer. Create it with Create Checkout.

curl -s -X POST "$BASE_URL/checkouts" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "alias": "Annual membership",
    "referenceId": "order-50213",
    "amount": 49.99,
    "currency": "USD",
    "buyer": { "email": "[email protected]", "referenceId": "customer-881" },
    "termsOfServiceUrl": "https://shop.example.com/terms",
    "privacyPolicyUrl": "https://shop.example.com/privacy",
    "redirectLinks": {
      "successRedirectUrl": "https://shop.example.com/orders/50213/thanks",
      "failureRedirectUrl": "https://shop.example.com/orders/50213/payment-failed",
      "expiredRedirectUrl": "https://shop.example.com/orders/50213/expired"
    }
  }'
type Checkout = {
  id: string;
  status: "PENDING" | "PROCESSING" | "PAID" | "FAILED" | "EXPIRED" | "UNKNOWN";
  links: { checkout: string; embeddable: string };
  chargedAmount?: { value: number; currency: string };
};

const checkout = await fetch(`${BASE_URL}/checkouts`, {
  method: "POST",
  headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    alias: "Annual membership",
    referenceId: "order-50213",
    amount: 49.99,
    currency: "USD",
    buyer: { email: "[email protected]", referenceId: "customer-881" },
    termsOfServiceUrl: "https://shop.example.com/terms",
    privacyPolicyUrl: "https://shop.example.com/privacy",
    redirectLinks: {
      successRedirectUrl: "https://shop.example.com/orders/50213/thanks",
      failureRedirectUrl: "https://shop.example.com/orders/50213/payment-failed",
      expiredRedirectUrl: "https://shop.example.com/orders/50213/expired",
    },
  }),
}).then(async (r) => {
  if (!r.ok) throw new Error(`Create checkout failed with ${r.status}: ${await r.text()}`);
  return r.json() as Promise<Checkout>;
});

The response is 200 with the checkout in PENDING:

  • id: the checkout ID, for example S-01JBXA3C7D9F2H4K6M8N0P1Q3R. Store it with your order.
  • links.checkout: the hosted payment page. Send the buyer there.
  • links.embeddable: the same page for an iframe in your site.
  • amount is a JSON number in decimal notation (49.99), not a string.
  • Payment Labs creates the buyer from buyer.email if it is new to you.
export CHECKOUT_ID="<id from the response>"

Step 3: Pay as the buyer

Open links.checkout in a browser and pay with a sandbox test card:

FieldValue
Card number4111 1111 1111 1111 (Visa) or 5454 5454 5454 5454 (Mastercard)
CVC555
ExpiryAny future date
NameAny value

When the payment succeeds, the page sends the buyer to successRedirectUrl. To test a decline, see Credit Card Payin Test Values.

Step 4: Confirm the payment on your server

The redirect only tells you the buyer finished the page. Before you fulfil the order, confirm the checkout status from your server with Get Checkout.

curl -s "$BASE_URL/checkouts/$CHECKOUT_ID" -H "Authorization: Bearer $TOKEN" | jq '{status, chargedAmount: .chargedAmount.formattedValue}'
const current = await fetch(`${BASE_URL}/checkouts/${checkout.id}`, {
  headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json() as Promise<Checkout>);

if (current.status === "PAID") {
  // fulfil the order
}
statusMeaningWhat to do
PENDINGNot paid yet.Wait.
PROCESSINGA charge is in progress.Wait for the final status.
PAIDThe buyer paid. chargedAmount holds the amount charged.Fulfil the order.
FAILEDThe charge failed. The hosted page does not offer the buyer another attempt on this checkout.To let the buyer try again, create a new checkout. You can charge a saved card on the same checkout yourself; see Checkout Statuses and Failure Reasons.
EXPIREDThe checkout passed expiresAt without being paid.Create a new checkout.
UNKNOWNThe charge was never confirmed as succeeded or failed. The checkout cannot be charged again.Do not charge the buyer again or cancel the order. Contact Payment Labs support with the checkout ID.

In production, do not poll. Register a webhook for checkout-status-changed and Payment Labs posts the checkout to your endpoint when its status changes. See Webhooks.

Errors and edge cases

StatusMeaningWhat to do
400 VALIDATION_ERRORA required field is missing or invalid. details names each field.Fix the fields and retry. See Errors.
400 other codesYour account cannot accept this amount or currency.Check the currency is enabled for your account.
403 FORBIDDEN_INSUFFICIENT_TAGSYour credential lacks the Merchant Write permission.Use a credential whose role includes it.

A timed-out create request may still have created the checkout. Search by referenceId before you create another. See Idempotency and Retries.

Next steps


What’s Next

Next: Errors.

Did this page help you?