Guides
Tracking payments
How to know the money arrived: statuses, polling and the proof on the XRPL.
There are no webhooks yet. To know a link was paid, call GET /invoices/{id}: every call re-reads the XRPL, and the platform also checks everything on its own every 15 seconds.
Link statuses
| Status | Meaning |
|---|---|
open | Waiting for payment. |
paid | Paid straight to your wallet. Final. |
locked | Paid with escrow; the funds are locked on the XRPL. |
releasing › released | The payer released the escrow; the XRP is in your wallet. |
refunding › refunded | The escrow deadline passed without release; the funds went back to the payer. |
expired | Past expires_at without payment. |
cancelled | You cancelled it before payment. |
Poll until paid
const API = "https://api.pineplechain.com/v1"
const headers = { "x-api-key": process.env.PINEPLECHAIN_API_KEY }
async function waitUntilPaid(id) {
for (;;) {
const link = await fetch(`${API}/invoices/${id}`, { headers }).then((r) => r.json())
if (link.status === "paid" || link.status === "released") return link // paid
if (["expired", "cancelled", "refunded"].includes(link.status)) throw new Error(link.status)
await new Promise((r) => setTimeout(r, 3000))
}
}Interval
Polling every 3 to 5 seconds matches the XRPL's pace and stays well under the 120 calls per minute limit.The proof on the XRPL
Once the link is paid, the paid field carries the transaction hash and the explorer link. The delivered amount is what actually arrived, checked on the validated ledger.
"paid": {
"tx_hash": "9C1F…E4A2",
"ledger_index": 91234567,
"payer": "rH4kPz…9tQe",
"delivered": { "value": "250", "asset": { "type": "XRP" } },
"at": "2026-10-30T14:02:11.000Z",
"explorer_url": "https://livenet.xrpl.org/transactions/9C1F…E4A2"
}