FAQ
Frequently asked questions about the BSync API.
Common integration questions and answers.
Payment stuck in "waiting" / pending
Symptom: status is pending, matchStatus is waiting.
Causes:
- Customer has not completed payment on the hosted checkout page.
- Customer paid but SMS has not been matched yet (usually seconds).
- Payment has expired.
Actions:
- Check
expiresAt— if past, status will becomeexpired. - Ask customer to complete payment at
checkoutUrl. - Wait for
PAYMENT_MATCHEDorPAYMENT_PAIDwebhook. - If stuck > 30 minutes, check BSync Dashboard for the payment.
Webhook not received
Symptom: Payment completed but no webhook delivered.
Checks:
- Webhook URL configured in Dashboard? Must be HTTPS in production.
- Endpoint returning 2xx? Non-2xx triggers retries, then
dead_letter. - Firewall blocking BSync IPs? Ensure your server accepts inbound POST.
- Using ngrok for local testing? Tunnel must be active.
- Check webhook delivery logs in the Dashboard.
Testing: Send a sample payload from the Postman Webhooks folder.
409 Conflict on create
Symptom: IDEMPOTENCY_CONFLICT when creating a payment.
Cause: Same Idempotency-Key used with a different request body.
Fix:
- If retrying the same order: send the exact same body.
- If creating a new order: use a new idempotency key (
order-${newOrderId}).
See Idempotency.
Payment expired
Symptom: status is expired or checkout returns 410 CHECKOUT_EXPIRED.
Cause: Customer did not pay within the expiry window (default: 30 minutes).
Fix: Create a new Payment Intent. Do not reuse the expired paymentId.
const newPayment = await bsync.paymentIntents.create({
amount: 150,
currency: "EGP",
externalOrderId: "ORD-42-retry",
redirectDelay: 3,
});Review required
Symptom: matchStatus is review_required, webhook PAYMENT_REVIEW_REQUIRED received.
Cause: BSync detected an anomaly (amount mismatch, duplicate, etc.) requiring manual review.
Actions:
- Do not fulfill the order yet.
- Wait for
PAYMENT_REVIEW_APPROVEDorPAYMENT_REVIEW_REJECTEDwebhook. - Inform the customer that payment is being verified.
- Check the BSync Dashboard for review status.
Payment already paid
Symptom: 409 PAYMENT_ALREADY_PROCESSED when trying to cancel or modify.
Cause: Payment is already paid. Cannot cancel or recreate.
Actions:
- If order already fulfilled: no action needed.
- If duplicate create attempt: check idempotency key — the original payment succeeded.
- Verify via
getStatus()and webhook history.
How to retry a failed API call
The SDK retries automatically for network errors, 5xx, and 429. For manual retries:
await bsync.paymentIntents.create(
{ amount: 150, currency: "EGP", externalOrderId: "ORD-42", redirectDelay: 3 },
{ idempotencyKey: "order-ORD-42" }
);Use the same idempotency key to safely retry. See Idempotency.
How to rotate API keys
- Dashboard → API Keys → Create new key.
- Update
BSYNC_API_KEYin your deployment. - Deploy all services.
- Revoke the old key.
- Monitor logs for 401 errors.
See Authentication and Security.
Can I use the API from the browser?
No. API keys must never be exposed client-side. All BSync API calls must go through your server.
What currencies are supported?
Currently EGP (Egyptian Pound) is the default and primary currency. See OpenAPI PaymentIntentCreateRequest for the current default.
How do I test without real money?
Use a bsync_test_* API key. All operations run in sandbox mode with no real transfers. See Testing.
Where is the full API reference?
- Interactive docs: /docs/api-reference
- OpenAPI spec:
BSync-Server/openapi/openapi.yaml - Internal reference:
project-documentation/07-developer-api.md
Related
Was this page helpful?
faq