AbsolutePayDocs

Payment links & invoices

Share a hosted link the customer opens to pay, or bill an amount with a deposit address up front.

A payment link mints an unguessable token and a hosted page at /pay/<token> where your customer pays. There are two symmetric resources — pick by whether the payer chooses the network or you fix it:

ResourceCreate withUse it for
checkoutPOST /v1/checkouts (ap.checkouts.create)A shareable hosted link — the payer chooses which token/chain to pay with.
invoicePOST /v1/invoices (ap.invoices.create, chain required)Billing an amount on a specific chain — mints the deposit address up front.

Both settle the same way and fire the same payment.succeeded webhook. Each is its own resource with the same create / list / get / update / del methods — the examples below use checkouts; swap in ap.invoices.* (on /v1/invoices) for the address flow.

Before you start: creating, updating, and voiding need the invoices:write scope; listing and reading need invoices:read (Authentication).

Returns a hosted URL to send the customer to; they pick the asset on the page.

const link = await ap.checkouts.create({
  reference: "order-123",
  amount: { amount: "25.00", currency: "USDT" },
});
console.log(link.token, link.checkoutUrl);
link = ap.checkouts.create(
    reference="order-123",
    amount={"amount": "25.00", "currency": "USDT"},
)
print(link["token"], link["checkoutUrl"])
link, err := ap.Checkouts.Create(ctx, absolutepay.CheckoutParams{
	Reference: "order-123",
	Amount:    absolutepay.Money{Amount: "25.00", Currency: "USDT"},
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(link.Token, link.CheckoutURL)
BODY='{"reference":"order-123","amount":{"amount":"25.00","currency":"USDT"}}'
curl https://api.absolutepay.io/v1/checkouts \
  -H "Authorization: Bearer $APP_TOKEN" -H "Content-Type: application/json" \
  $(sign POST /v1/checkouts "$BODY") -d "$BODY"

The reference is your reconciliation handle — keep it unique per order. Amounts are decimal strings ("25.00"), ≤ 6 fraction digits.

Create an invoice (mint a deposit address up front)

An invoice always mints the on-chain deposit address up front for the chain you pass (required), and the payer sends funds directly to it. If you'd rather let the payer pick the network on the hosted page, create a checkout link instead.

const invoice = await ap.invoices.create({
  reference: "order-123",
  amount: { amount: "25.00", currency: "USDT" },
  chain: "MATIC", // mint the deposit address now
});
console.log(invoice.token, invoice.address);
invoice = ap.invoices.create(
    reference="order-123",
    amount={"amount": "25.00", "currency": "USDT"},
    chain="MATIC",  # mint the deposit address now
)
print(invoice["token"], invoice["address"])
invoice, err := ap.Invoices.Create(ctx, absolutepay.InvoiceParams{
	Reference: "order-123",
	Amount:    absolutepay.Money{Amount: "25.00", Currency: "USDT"},
	Chain:     "MATIC", // mint the deposit address now
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(invoice.Token, invoice.Address)
BODY='{"reference":"order-123","amount":{"amount":"25.00","currency":"USDT"},"chain":"MATIC"}'
curl https://api.absolutepay.io/v1/invoices \
  -H "Authorization: Bearer $APP_TOKEN" -H "Content-Type: application/json" \
  $(sign POST /v1/invoices "$BODY") -d "$BODY"

Redirect the payer back after payment

Set an optional redirectUrl on create (works for both checkout links and invoices). Once the hosted page reaches a terminal state it sends the payer back to that URL with the outcome as query params — so your success page knows which order completed and how it ended.

const link = await ap.checkouts.create({
  reference: "order-123",
  amount: { amount: "25.00", currency: "USDT" },
  redirectUrl: "https://yourstore.com/thank-you",
});
link = ap.checkouts.create(
    reference="order-123",
    amount={"amount": "25.00", "currency": "USDT"},
    redirect_url="https://yourstore.com/thank-you",
)
link, err := ap.Checkouts.Create(ctx, absolutepay.CheckoutParams{
	Reference:   "order-123",
	Amount:      absolutepay.Money{Amount: "25.00", Currency: "USDT"},
	RedirectURL: "https://yourstore.com/thank-you",
})
BODY='{"reference":"order-123","amount":{"amount":"25.00","currency":"USDT"},"redirectUrl":"https://yourstore.com/thank-you"}'
curl https://api.absolutepay.io/v1/checkouts \
  -H "Authorization: Bearer $APP_TOKEN" -H "Content-Type: application/json" \
  $(sign POST /v1/checkouts "$BODY") -d "$BODY"

After the payment settles, the payer lands on https://yourstore.com/thank-you?token=<token>&status=SUCCESS. The token is the link token (the same id in /pay/<token>); status is the final outcome:

Link statestatus
PAIDSUCCESS
EXPIREDEXPIRED
VOIDCANCELED

Any query string you already put on redirectUrl is preserved (?ref=42?ref=42&token=…&status=SUCCESS).

Confirm settlement server-side

The redirect is a browser navigation — treat token/status as untrusted display hints, never fulfill an order off them alone. Confirm the real outcome server-side via the payment.succeeded webhook (primary) or ap.checkouts.get("<token>"). redirectUrl must be an http(s) URL.

List, get, update & void

Every list returns { items, nextCursor } — page by echoing nextCursor back as before (see Pagination). Filter by status (OPEN | PAID | EXPIRED | VOID) and sort with order (asc | desc); ?status=PAID is your settled pay-ins.

// List (newest first) and page:
const { items, nextCursor } = await ap.checkouts.list({ status: "OPEN", order: "desc" });
// next page: ap.checkouts.list({ status: "OPEN", before: nextCursor })

// Read one:
const link = await ap.checkouts.get("<token>");

// Pause / resume (reversible):
await ap.checkouts.update("<token>", { paused: true });   // stop accepting payment
await ap.checkouts.update("<token>", { paused: false });  // resume

// Void (terminal — cannot be paid):
await ap.checkouts.del("<token>");
# List (newest first) and page:
result = ap.checkouts.list(status="OPEN", order="desc")
items, next_cursor = result["items"], result["nextCursor"]
# next page: ap.checkouts.list(status="OPEN", before=next_cursor)

# Read one:
link = ap.checkouts.get("<token>")

# Pause / resume (reversible):
ap.checkouts.update("<token>", paused=True)   # stop accepting payment
ap.checkouts.update("<token>", paused=False)  # resume

# Void (terminal — cannot be paid):
ap.checkouts.delete("<token>")
// List (newest first) and page:
page, err := ap.Checkouts.List(ctx, absolutepay.PageQuery{Status: "OPEN", Order: "desc"})
if err != nil {
	log.Fatal(err)
}
fmt.Println(page.Items, page.NextCursor)

// Read one:
link, err := ap.Checkouts.Get(ctx, "<token>")

// Pause / resume (reversible):
_, err = ap.Checkouts.Update(ctx, "<token>", absolutepay.CheckoutPatch{Paused: absolutepay.Bool(true)})

// Void (terminal — cannot be paid):
_, err = ap.Checkouts.Delete(ctx, "<token>")
# List + filter + sort:
curl "https://api.absolutepay.io/v1/checkouts?status=OPEN&order=desc&limit=50" \
  -H "Authorization: Bearer $APP_TOKEN" $(sign GET "/v1/checkouts?status=OPEN&order=desc&limit=50" "")

# Get one:
curl "https://api.absolutepay.io/v1/checkouts/<token>" \
  -H "Authorization: Bearer $APP_TOKEN" $(sign GET "/v1/checkouts/<token>" "")

# Pause (PATCH):
BODY='{"paused":true}'
curl -X PATCH https://api.absolutepay.io/v1/checkouts/<token> \
  -H "Authorization: Bearer $APP_TOKEN" -H "Content-Type: application/json" \
  $(sign PATCH /v1/checkouts/<token> "$BODY") -d "$BODY"

# Void (DELETE — terminal):
curl -X DELETE https://api.absolutepay.io/v1/checkouts/<token> \
  -H "Authorization: Bearer $APP_TOKEN" $(sign DELETE /v1/checkouts/<token> "")

update patches a link in place — paused toggles whether it accepts payment (reversible), and you can also revise redirectUrl, expiresAt, or description (pass null to clear a field). del voids the link: it's terminal and can never be paid. The same methods exist on ap.invoices.*.

Confirm settlement

Don't fulfill until a link reaches PAID. Use the payment.succeeded webhook as the primary signal; as a fallback, read the link back with ap.checkouts.get("<token>") (or ap.invoices.get) and check status === "PAID".

Gotchas

  • The token IS the credential. Anyone with the link can view and pay it — share the URL only with the intended payer, and void links you no longer want payable.
  • Send the exact quoted amount to the deposit address. The quote is live; the invoice response includes the precise amount the payer must transfer.
  • Amounts are decimal strings ("25.00"), positive, ≤ 6 fraction digits.
  • In the sandbox, links don't settle on their own — trigger settlement yourself ("Simulate payment" in the dashboard); the same payment.succeeded webhook fires.

Next

On this page