Payment Intents
Create and manage payment intents via the Public API.
Payment Intents are the core object for accepting payments via BSync. Create one server-side, redirect the customer to checkoutUrl, then track status via API or webhooks.
OpenAPI:
PaymentIntent,PaymentIntentCreateRequestschemas — /docs/api-reference
Endpoints
| Method | Path | SDK Method | Description |
|---|---|---|---|
| POST | /v1/payment-intents | paymentIntents.create() | Create a payment |
| GET | /v1/payment-intents/{paymentId} | paymentIntents.get() | Get full payment |
| GET | /v1/payment-intents/{paymentId}/status | paymentIntents.getStatus() | Lightweight status |
| POST | /v1/payment-intents/{paymentId}/cancel | paymentIntents.cancel() | Cancel a pending payment |
Create a Payment Intent
Request Fields
| Field | Required | Default | Description |
|---|---|---|---|
amount | Yes | — | Payment amount (must be > 0) |
currency | No | EGP | ISO currency code |
customerPhone | No | null | Customer mobile number |
externalOrderId | No | — | Your order reference |
metadata | No | {} | Arbitrary key-value data |
successUrl | No | null | HTTPS redirect after successful payment |
cancelUrl | No | null | HTTPS redirect after cancellation |
redirectDelay | No | 3 | Seconds before redirect to successUrl |
expiresAt | No | 30 min from creation | Future ISO 8601 expiry |
SDK:
const payment = await bsync.paymentIntents.create({
amount: 250,
currency: "EGP",
customerPhone: "+201012345678",
externalOrderId: "ORD-42",
successUrl: "https://merchant.example/success",
cancelUrl: "https://merchant.example/cancel",
redirectDelay: 3,
metadata: { description: "Order 42", sku: "ITEM-001" },
});curl:
curl -X POST https://api.bsyncapp.com/v1/payment-intents \
-H "Authorization: Bearer bsync_test_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-ORD-42" \
-d '{
"amount": 250,
"currency": "EGP",
"externalOrderId": "ORD-42",
"redirectDelay": 3
}'Response
Returns HTTP 201 with a PaymentIntent object. Key fields:
| Field | Description |
|---|---|
paymentId | Unique payment identifier |
status | Current lifecycle status |
checkoutUrl | URL to redirect the customer |
amount, currency | Payment amount |
expiresAt | When the payment expires |
matchStatus | waiting, matched, review_required |
verificationStatus | pending, verified, manual_review, failed |
reference.externalOrderId | Your order reference |
metadata | Your custom data |
Status Lifecycle
pending → paid
pending → expired
pending → cancelled
pending → failed
| Status | Meaning |
|---|---|
pending | Awaiting customer payment |
paid | Payment confirmed |
expired | Payment window closed |
cancelled | Cancelled by merchant or customer |
failed | Payment failed (e.g. review rejected) |
Poll status:
const status = await bsync.paymentIntents.getStatus("pay_abc123");
console.log(status.status);
console.log(status.matchStatus);
console.log(status.verificationStatus);Prefer webhooks over polling for production. See Webhooks.
Cancellation
Cancel a pending payment:
const cancelled = await bsync.paymentIntents.cancel("pay_abc123");Returns the updated PaymentIntent with status: "cancelled".
Cannot cancel payments that are already paid, expired, or under review. See error codes below.
Expiration
Payments expire at expiresAt (default: 30 minutes from creation). Override with a future ISO 8601 timestamp:
await bsync.paymentIntents.create({
amount: 100,
currency: "EGP",
redirectDelay: 3,
expiresAt: "2026-07-14T20:00:00.000Z",
});Expired payments return status: "expired" and trigger a PAYMENT_EXPIRED webhook.
Idempotency
POST /v1/payment-intents supports the Idempotency-Key header. The SDK auto-generates one on every create() call. See Idempotency.
Metadata
Attach arbitrary data to a payment:
metadata: {
description: "Premium subscription",
planId: "pro-monthly",
userId: "usr_123",
}Metadata is returned in the response and included in webhook payloads where applicable. Max practical size: keep under 4 KB.
Customer Phone
Optional. When provided, BSync can use it for payment matching:
customerPhone: "+201012345678",Redirect URLs
| Field | When used |
|---|---|
successUrl | Customer redirected here after successful payment (after redirectDelay seconds) |
cancelUrl | Customer redirected here if they cancel checkout |
Both must be HTTPS in production.
Error Codes
| HTTP | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | Invalid amount, missing fields |
| 404 | RESOURCE_NOT_FOUND | Payment ID not found |
| 409 | PAYMENT_NOT_CANCELLABLE | Cannot cancel this payment |
| 409 | PAYMENT_ALREADY_PROCESSED | Payment already completed |
| 409 | IDEMPOTENCY_CONFLICT | Same key, different body |
| 422 | PAYMENT_CANNOT_BE_CANCELLED | Business rule prevents cancellation |
| 422 | PAYMENT_UNDER_REVIEW | Payment is under manual review |
| 422 | REVIEW_REQUIRED | Manual review required |
Related
- Hosted Checkout — what happens after redirect
- Webhooks — event-driven status updates
- Idempotency — safe create retries
- Error Handling — full error reference
Was this page helpful?
payment-intents