Verify Payments
Confirm transaction status server-side before fulfilling orders or granting access.
⬡ API product
Requires developer access and an API keyAfter a customer completes a payment, you must verify the result on your server before fulfilling the order. The redirect back to your app is not proof of payment — it can be triggered by anyone who knows your callback URL. Always verify server-side.
Seev gives you two ways to verify a payment: callback verification (at redirect time) and transaction lookup (at any time using a reference or transaction ID).
Never fulfil an order, grant access, or send goods based on the redirect alone. Always call Seev.callback() or Seev.transaction() before acting on a payment.
Method 1: Callback verification
When Seev redirects the customer back to your redirectUrl, it appends a session_id query parameter. Call Seev.callback() in that route handler to verify the session and get the payment result.
// GET /payment/callback?session_id=checkout_abc123
import Seev from '@seev/sdk';
export async function GET(req: Request) {
const session = await Seev.callback();
// or pass the session ID explicitly:
// const session = await Seev.callback('checkout_abc123');
if (session.isSuccessful()) {
// Payment confirmed — safe to fulfil
await db.orders.update({
ref: session.reference,
status: 'paid',
});
return Response.redirect('/order/confirmed');
} else {
// Payment failed, cancelled, or pending
return Response.redirect(`/order/failed?status=${session.status}`);
}
}Callback session object
| Property / Method | Type | Description |
|---|---|---|
session.isSuccessful() | boolean | true if the payment completed successfully |
session.id | string | The checkout session ID |
session.status | string | 'success', 'failed', or 'pending' |
session.reference | string | Transaction reference — store this with your order |
session.getSession() | object | Full session object from the API |
Method 2: Transaction lookup
Use Seev.transaction() to fetch the status of any transaction at any time using its reference or ID. This is useful for:
- Verifying payments that came through webhooks
- Checking the status of a payment initiated elsewhere
- Building an order status page that polls for updates
const transaction = await Seev.transaction('txn_abc123xyz');
console.log(transaction.id);
console.log(transaction.status); // 'completed' | 'pending' | 'failed'
console.log(transaction.amount); // in smallest currency unit
console.log(transaction.currency);
console.log(transaction.reference);Transaction statuses
| Status | Meaning |
|---|---|
completed | Payment was successful — safe to fulfil |
pending | Payment initiated but not yet confirmed — do not fulfil yet |
failed | Payment did not go through — prompt the customer to retry |
Method 3: Webhooks (recommended for fulfilment)
For fulfilment workflows, webhooks are more reliable than callback verification alone. Seev sends a checkout.completed event to your webhook endpoint as soon as a payment is confirmed — even if the customer closes the browser before being redirected.
Use Seev.callback() to give the customer immediate feedback in the UI, and use the checkout.completed webhook to trigger your fulfilment logic.
// Webhook handler — POST /webhooks/seev
const event = await Seev.webhook(req.body, req.headers['x-seev-signature']);
if (event.is('checkout.completed')) {
const data = event.getData();
await fulfillOrder(data.reference);
}See the Webhooks guide for setup, delivery logs, retries, and signature verification.
Which method should I use?
| Scenario | Recommended method |
|---|---|
| Giving the customer immediate feedback after redirect | Seev.callback() |
| Triggering fulfilment (send goods, grant access, send email) | Webhook checkout.completed |
| Looking up a past transaction by reference | Seev.transaction() |
| Polling for status on a pending payment | Seev.transaction() with a delay |
Using both Seev.callback() and webhooks together is the most robust pattern — the callback handles the UI, and the webhook handles fulfilment independently.