Skip to content

Payments ​

Once a merchant is onboarded and approved, you can take payments. PayBridge uses a hosted checkout: you create a session from your backend, redirect the customer to a secure PayBridge-hosted payment page (card data is captured there and never touches your servers or ours), then confirm the result.

All requests use the base URL, X-API-Key, and X-Requested-With header from the Overview. Amounts are in cents.

Step 1: Create a checkout session ​

When a customer is ready to pay, create a session from your backend.

POST /checkout/sessions
json
{
  "merchant_id": "a1b2c3d4-...",
  "amount": 75000,
  "currency": "USD",
  "description": "Custom Shed - 10x12 Barn Style",
  "success_url": "https://yourstore.com/orders/123/confirmed",
  "cancel_url": "https://yourstore.com/orders/123/checkout",
  "customer_email": "buyer@example.com",
  "idempotency_key": "order-123-checkout-v1"
}

The success_url and cancel_url must match origins registered with your app (set during provisioning) — this prevents open-redirect attacks. The idempotency_key is required so retries never create duplicate sessions.

Response (201) — sandbox shown; the checkout_url host is always the base URL you called:

json
{
  "id": "session-uuid",
  "checkout_url": "https://sandbox.api.nfs-pay.com/checkout/session/session-uuid?st=...",
  "amount": 75000,
  "currency": "USD",
  "status": "pending",
  "expires_at": "2026-03-26T13:00:00",
  "created_at": "2026-03-26T12:00:00"
}

Step 2: Redirect the customer ​

Send the customer to the checkout_url. This opens a PayBridge-hosted payment page where they enter their card or bank details on the secure hosted page.

javascript
window.location.href = checkoutSession.checkout_url;

After payment, the customer is redirected to your success_url with query parameters:

https://yourstore.com/orders/123/confirmed
  ?pay_session_id=session-uuid
  &pay_payment_id=payment-uuid
  &pay_status=posted
  &pay_amount=75000

If they cancel, they're sent to your cancel_url.

Step 3: Confirm the payment ​

Don't trust the redirect parameters alone — verify from your backend.

GET /checkout/sessions/{session_id}
json
{
  "id": "session-uuid",
  "status": "completed",
  "amount": 75000,
  "currency": "USD",
  "payment_id": "payment-uuid",
  "completed_at": "2026-03-26T12:02:30"
}

Session statuses:

  • pending — waiting for payment
  • completed — payment succeeded
  • expired — session timed out (60 minutes)

You can also register a checkout.completed webhook to be notified when a payment succeeds; verify the X-PayBridge-Signature header and fall back to status polling for any missed event.

Refunds ​

Issue a full or partial refund against a completed payment. Refunds route back to the processor that handled the original payment.

POST /payments/{payment_id}/refund

Full refund (omit amount):

json
{
  "idempotency_key": "refund-order-123-full",
  "description": "Order cancelled by customer"
}

Partial refund:

json
{
  "amount": 25000,
  "idempotency_key": "refund-order-123-partial-v1",
  "description": "Partial refund for returned item"
}

Response (201):

json
{
  "id": "refund-uuid",
  "payment_id": "original-payment-uuid",
  "amount": 25000,
  "status": "posted",
  "created_at": "2026-03-28T10:00:00"
}

Only payments in posted or settled status can be refunded. Multiple partial refunds are allowed, up to the original payment amount. idempotency_key is required to prevent duplicate refunds on retry.

Voids ​

Cancel a card payment before it settles. A successful void stops the sale from settling, so it is never captured and the merchant pays no processing fee for it; a refund, by contrast, settles both the charge and the refund. The customer's bank may still show the original authorization as a temporary hold until the bank releases it. A void is always for the full amount.

POST /payments/{payment_id}/void
json
{
  "idempotency_key": "void-order-123",
  "description": "Order cancelled before shipping"
}

Response (201):

json
{
  "id": "void-uuid",
  "payment_id": "original-payment-uuid",
  "amount": 25000,
  "status": "voided",
  "processor_type": "clearent",
  "description": "Order cancelled before shipping",
  "created_at": "2026-10-09T10:00:00"
}

The payment itself then shows status: "voided" in GET /payments/{payment_id}, and you receive a payment.voided webhook.

  • Send the same idempotency_key again and you get the original void back; the payment is voided once.
  • Voids are available for card payments on Clearent. Bank (ACH) payments and payments on other processors can't be voided: refund them instead.
  • A payment that has already settled can't be voided. The request is refused with a 400 that says to refund the payment instead. A payment that already has a refund can't be voided either; refund the remaining amount.
  • If the processor refuses the void, the payment stays as it was and the 400 says the payment can't be voided and may have already settled. Refund it instead.

Check status on every response. A 201 does not by itself mean the payment was voided:

statusMeaning
voidedThe processor accepted the void. The payment is voided.
failedThe void did not happen. The payment is unchanged.
pendingThe processor's response didn't confirm the outcome, so it is unconfirmed. Do not treat the payment as voided.

If the processor doesn't answer or its response is unclear, the request returns 502. You can retry with the same idempotency_key: it does not void again, and returns the void with its current status, which may be pending. While a void is pending, the payment stays as it was and can't be voided again (409) or refunded until PayBridge support checks the payment with the processor and resolves the void. Contact support with the void id if a void stays pending; support tells you the outcome, and no payment.voided webhook is sent for a void resolved this way.

Sandbox testing ​

The sandbox connects to the processor's sandbox. The hosted checkout page accepts the test card or bank details directly — no VGS setup is required in sandbox — so you can run a payment end to end. Staging and production still capture card data through VGS.

See Testing for the sandbox test cards.