Your first test payment
Create a hosted checkout, pay with test tokens, and verify the result on your server.
On this page
1. Prepare a merchant profile
- Sign in, choose business payments or integration, and complete your profile’s billing details.
- Create a store. Check that your profile wallet and at least one test token are ready.
- Open Developers. Create a test key for that store with invoices.write and invoices.read. Save its profile ID and store ID.
- Get test tokens and the network’s fee token for your payer wallet. Use exactly the network shown by checkout. Never send real funds.
2. Set server credentials
Store these values in your server’s environment. The documentation host, your application host and the API origin are different settings.
The hosted API address below is the configured application endpoint, not evidence of a production launch. For local development, use http://localhost:8080.
export FORWEND_API_URL=https://forwend.com/api
export FORWEND_KEY=fw_test_replace_on_your_server
export FORWEND_PROFILE_ID=replace_with_your_profile_id
export FORWEND_STORE_ID=replace_with_your_store_id3. Create the purchase attempt
Save this JavaScript as create-checkout.mjs, then run node create-checkout.mjs with Node 20 or later. Calculate the price from your own order records. Never trust an amount supplied by the browser.
Keep the idempotency key stable when retrying this purchase attempt. Use a new key for a new attempt.
const response = await fetch(
process.env.FORWEND_API_URL + "/v1/profiles/" +
process.env.FORWEND_PROFILE_ID + "/checkout-sessions",
{
method: "POST",
headers: {
Authorization: "Bearer " + process.env.FORWEND_KEY,
"Content-Type": "application/json",
"Idempotency-Key": "order-1042-attempt-1",
},
body: JSON.stringify({
storeId: process.env.FORWEND_STORE_ID,
amountUsd: "1250.00",
reference: "order-1042",
metadata: { order_id: "1042" },
}),
},
);
if (!response.ok) throw new Error("Checkout could not be created");
const session = await response.json();
// Send only the hosted URL, or the pay token for an embedded checkout, to your browser.
const hostedUrl = session.payment.hostedUrl;
const payToken = session.payment.payToken;
console.log(JSON.stringify({ sessionId: session.sessionId, hostedUrl, livemode: session.payment.livemode }, null, 2));4. Open the hosted checkout
The script prints sessionId, hostedUrl and livemode. Save the sessionId as SESSION_ID in your terminal: export SESSION_ID=the_returned_id. A new attempt returns HTTP 201. An exact retry returns HTTP 200 with the original attempt. The following excerpt shows the fields to use; IDs and the hosted URL come from your response.
- Open payment.hostedUrl in your browser.
- Choose an available token/network pair, then send the exact test amount to the displayed receive address.
- Wait for confirmation. Timing depends on the network; a detected transfer is not a paid order.
| Field | Details |
|---|---|
sessionIdstring | Save this ID beside your order. |
statusstring | The checkout state: open, complete or expired. |
payment.hostedUrlstring | null | The customer-facing payment URL. Use the returned URL; do not construct a token. |
payment.livemodeboolean | Must be false for this test integration. |
5. Verify completion on your server
Read the session again with the same store-scoped key. A redirect or browser status callback cannot authorize fulfillment.
Check the saved session ID, order reference, store, mode, expected amount and token/network identity. Fulfill once only after canonical paymentStatus is paid.
For unattended orders, verify signed webhooks, queue them durably, deduplicate event IDs, and fetch the current session before fulfilling. Settlement is a separate step.
curl "$FORWEND_API_URL/v1/profiles/$FORWEND_PROFILE_ID/checkout-sessions/$SESSION_ID" \
-H "Authorization: Bearer $FORWEND_KEY"