Developer reference

Paidly API & webhooks

The technical reference for accounting partners and developer-minded bookkeepers — built around three flows: Xero-style invoice sync, overdue push, and payment.received callbacks.

01 — Authentication

Authenticating every request

Paidly expects an API key on every request, sent as either the Authorization bearer token or the X-Paidly-Key header. Keys are issued per-account under Settings → API and can be scoped or rotated without taking the rest of your integration offline. Treat a key like a password — store it in your secrets manager, never commit it, and re-issue through the dashboard if it ever leaks.

Header
Authorization: Bearer pdly_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# or
X-Paidly-Key: pdly_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
02 — Invoice sync

Push your outstanding invoices in one call

POST /v1/invoices/sync

Bulk push outstanding invoices from your accounting platform into Paidly — idempotent on (external_id). Returns the assigned Paidly IDs and the resulting collection status.

Request
{
  "invoices": [
    {
      "external_id": "xero:INV-1047",
      "client_name": "Acme Build Ltd",
      "client_email": "ap@acmebuild.co.uk",
      "amount": 284000,
      "currency": "GBP",
      "due_date": "2026-08-01"
    }
  ]
}
Response
{
  "synced": 1,
  "invoices": [
    {
      "external_id": "xero:INV-1047",
      "id": "inv_01H...",
      "status": "overdue"
    }
  ]
}

Re-sending the same external_id with the same payload is a no-op — Paidly is idempotent on the (external_id) pair so retries are safe. To update status, POST again with the same external_id; to delete, call DELETE /v1/invoices/:id.

03 — Webhooks

payment.received callback

Fired when Paidly confirms a payment against an invoice it has chased. POSTed to the URL you configured under Settings → Webhooks.

Configure the delivery URL under Settings → Webhooks. Paidly POSTs the payload below and expects a 2xx response within 5 seconds. On a 5xx (or no response) we retry up to 5 times inside a 24-hour window with exponential back-off (1s, 2s, 4s, 8s, 16s). After 5 failed attempts, the delivery is marked dead and surfaced in the dashboard.

Payload
{
  "event": "payment.received",
  "invoice": {
    "id": "inv_01H...",
    "external_id": "xero:INV-1047",
    "amount": 284000,
    "currency": "GBP"
  },
  "paid_at": "2026-08-14T10:42:11Z",
  "source": "stripe"
}

Verifying the signature. Each delivery carries a X-Paidly-Signature header — HMAC-SHA256 of the raw body using your webhook signing secret. Reject any request whose signature does not match before you trust the payload.

04 — Errors

Status codes, error codes, and retry guidance

Errors return a JSON body of the shape { "error": { "code": "...", "message": "..." } } plus an X-Request-Id header. Quote the request id when contacting support. The table below lists every code your integration should be ready to handle.

HTTP Error code Meaning Retry
401 unauthorized Missing or invalid API key. The Authorization header was absent, expired, or did not match any active key on the account. Do not retry automatically. Confirm the key under Settings → API and re-issue the request with a fresh header.
403 forbidden The key is valid but not authorised for this resource or action (e.g. cross-account invoice ID, or the key is scoped read-only). Do not retry. Check the key scopes in Settings → API and confirm the resource belongs to your account.
404 not_found The referenced invoice, webhook delivery or endpoint does not exist (or has been deleted). Do not retry without fixing the request. Treat as a permanent error and surface to the operator.
409 conflict The same idempotency key was reused with a different payload, or an invoice is in a state that blocks the requested transition (e.g. trying to mark a paid invoice as overdue again). Do not retry without resolving the conflict. Compare the original request body or advance the invoice state from the dashboard.
422 unprocessable_entity Request body parsed cleanly but failed field-level validation — missing required field, malformed date, currency not supported, or amount below the minimum. Do not retry. Fix the offending field (the error body names it) and resubmit.
429 rate_limited You exceeded the per-key request budget. The response includes a Retry-After header (seconds) indicating when to come back. Safe to retry. Honour the Retry-After header, then back off exponentially if you keep hitting the limit.
500 server_error Unexpected error on Paidly's side. Safe to assume the request did not land and try again. Safe to retry with exponential back-off (1s, 2s, 4s, 8s, 16s). After 5 attempts inside a 24h window, escalate to support with the X-Request-Id from the response headers.
503 service_unavailable Maintenance window or downstream dependency outage. Same retry posture as 500. Safe to retry with exponential back-off. If the window exceeds 15 minutes, treat as a sustained outage and queue the requests locally.

Try Paidly free

Get your overdue invoices in front of AI in under two minutes.

Free to try. No card required.