pineplechainDocs

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

StatusMeaning
openWaiting for payment.
paidPaid straight to your wallet. Final.
lockedPaid with escrow; the funds are locked on the XRPL.
releasing › releasedThe payer released the escrow; the XRP is in your wallet.
refunding › refundedThe escrow deadline passed without release; the funds went back to the payer.
expiredPast expires_at without payment.
cancelledYou 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"
}

Something wrong on this page? Let us know.