Agent Quickstart
Give this page to a coding agent when you want it to add FinCobra Checkout to an existing app.
This guide describes the standard hosted checkout integration. The agent should add the frontend checkout flow, create invoices from the merchant server, redirect customers to the hosted paymentUrl, verify webhooks, and update orders from the current invoice state.
Continuing without an agent? Start with Authentication.
Agent prompt
Integrate FinCobra Checkout using the hosted payment page.
Use the frontend for the customer checkout flow and the backend for all FinCobra API calls. Never expose the FinCobra API key or webhook signing secret to browser, mobile, or client-side code.
Required behavior:
1. Add server-side configuration for FINCOBRA_CHECKOUT_API_KEY and FINCOBRA_CHECKOUT_WEBHOOK_SECRET.
2. Add a frontend checkout action that calls the merchant backend to start checkout for the current order.
3. In the merchant backend, create a FinCobra invoice with POST https://fincobra.com/api/checkout/invoices.
4. Store the returned invoice id and paymentUrl with the local order.
5. Return paymentUrl to the frontend and redirect the customer there.
6. Add frontend handling for the return page or order page so the customer can see pending, paid, expired, or voided checkout state from the merchant backend.
7. Add a webhook endpoint that verifies X-Checkout-Signature with HMAC-SHA256 over the raw JSON request body.
8. After a valid webhook, fetch GET https://fincobra.com/api/checkout/invoices/:id from the server and update the local order from the current invoice status.
9. Treat confirmed and paid_out_of_band as paid. Keep payment_detected pending unless this business accepts unconfirmed crypto payments.
Use these docs as the source of truth:
- Overview: https://fincobra.com/docs/checkout/
- Invoices: https://fincobra.com/docs/checkout/invoices.html
- Webhooks: https://fincobra.com/docs/checkout/webhooks.html
- API Reference: https://fincobra.com/docs/checkout/api-reference.htmlIntegration shape
The integration has both frontend and backend work:
| App layer | Responsibility |
|---|---|
| Frontend | Start checkout by calling the merchant backend, redirect to paymentUrl, and render local order status after the customer returns. |
| Backend | Store secrets, create FinCobra invoices, store invoice IDs, verify webhooks, fetch current invoice state, and update local orders. |
| FinCobra hosted page | Collect payment through the hosted checkout page and show live payment status to the customer. |
Do not call FinCobra merchant endpoints directly from frontend code. The browser should only talk to the merchant backend and visit the hosted paymentUrl.
Merchant setup
Before code changes, the merchant should complete these dashboard steps:
- Configure at least one payment method.
- Set invoice timing, issuer name, and redirect URL defaults.
- Create a Checkout API key.
- Create a webhook signing secret.
- Add the production webhook URL.
Use these server-side environment variables:
FINCOBRA_CHECKOUT_API_KEY=fc_live_...
FINCOBRA_CHECKOUT_WEBHOOK_SECRET=...
FINCOBRA_CHECKOUT_BASE_URL=https://fincobra.comFrontend checkout flow
Add a checkout button or action that calls the merchant backend for the current order:
async function startCheckout(orderId) {
const response = await fetch(`/api/orders/${orderId}/checkout`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
});
if (!response.ok) {
throw new Error('Unable to start checkout');
}
const checkout = await response.json();
window.location.assign(checkout.paymentUrl);
}The merchant backend response should contain the hosted paymentUrl, not the FinCobra API key.
The hosted page redirects to the exact redirectUrl after confirmed or paid_out_of_band; no invoice params are appended.
After the customer returns to the merchant app, show the local order state from the merchant backend. Use confirmed and paid_out_of_band as paid states. Show payment_detected as pending unless the business accepts unconfirmed crypto payments.
Backend invoice creation
Create invoices from the merchant server. Store the local order ID in merchantReference and metadata so webhook handling can reconcile the invoice.
curl -X POST https://fincobra.com/api/checkout/invoices \
-H "X-Api-Key: fc_live_..." \
-H "Content-Type: application/json" \
-d '{
"amountUsd": 49.99,
"productName": "Pro Plan - Monthly",
"merchantReference": "order_123",
"customerEmail": "buyer@example.com",
"metadata": {
"orderId": "order_123"
}
}'Use the response like this:
| Field | Required action |
|---|---|
id | Store with the local order as the FinCobra invoice ID. |
paymentUrl | Redirect the customer to this URL. |
status | Store for admin display and reconciliation. |
paymentSummary | Store or read when handling partial payment and overpayment states. |
For standard hosted checkout, do not build custom payment instructions from paymentOptions[]. Redirect to paymentUrl.
Webhook handling
FinCobra sends POST requests to the configured webhook URL with X-Checkout-Signature.
The signature is an HMAC-SHA256 hex digest of the raw JSON request body using the webhook signing secret.
import crypto from 'node:crypto';
function verifyFinCobraSignature(rawBody, signature, secret) {
if (typeof signature !== 'string') {
return false;
}
if (!/^[0-9a-f]{64}$/i.test(signature)) {
return false;
}
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
const signatureBuffer = Buffer.from(signature, 'hex');
const expectedBuffer = Buffer.from(expected, 'hex');
return (
signatureBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(signatureBuffer, expectedBuffer)
);
}Use payload.invoice.id from the webhook body, then fetch the latest invoice before updating the order.
After verifying the signature, fetch the latest invoice before changing order state:
curl https://fincobra.com/api/checkout/invoices/a1b2c3d4-1111-4222-8333-abcdefabcdef \
-H "X-Api-Key: fc_live_..."Webhook delivery is at-least-once. Make the local order update idempotent.
Status mapping
| FinCobra invoice status | Merchant order action |
|---|---|
awaiting_payment | Keep pending. |
partially_paid | Keep pending and review paymentSummary.remainingAmountUsd. |
payment_detected | Keep pending unless the business accepts detected but unconfirmed payment. |
confirmed | Mark paid and fulfill if not already fulfilled. |
paid_out_of_band | Mark paid and store the payment note for reconciliation. |
expired | Mark checkout expired and let the customer start a new checkout. |
voided | Stop accepting payment for this invoice. |
Use paymentCoverage and paymentSummary for partial payment and overpayment operations. Treat confirmed as the default fulfillment trigger.
Implementation checklist
- Keep the API key and webhook secret server-side.
- Create invoices from the merchant backend, not the browser.
- Save the FinCobra invoice ID on the local order.
- Redirect customers to
paymentUrl. - Verify webhook signatures using the raw request body.
- Fetch current invoice state before updating orders.
- Make webhook processing idempotent.
- Add tests for invoice creation, webhook signature rejection, duplicate webhook delivery, and status-to-order mapping.