Send Xero invoice reminders through IllyVoIP SMS

Send IllyVoIP SMS reminders for eligible Xero invoices using verified webhooks, tenant-scoped invoice reads and duplicate-safe reminder records.

Use Xero invoice events to update your reminder queue, then send an IllyVoIP SMS only after rereading the invoice and confirming that a reminder is still appropriate. An invoice-created event is not proof that payment is overdue, and an old event must not cause a paid invoice to receive another reminder.

Prepare the two services and your worker

This is a custom backend integration. You need authorized Xero access for the intended organisation, suitable read scopes, an HTTPS webhook receiver, a durable reminder store and a worker that can run scheduled tasks. You also need IllyVoIP API access, an allowed SMS sender and a recipient who may receive this type of notification. Neither service creates the reminder scheduler described here automatically.

Keep Xero OAuth credentials, webhook signing key and IllyVoIP API key separately in server-side secret storage. Bind each Xero tenant to the correct application customer/account. Never select a tenant or recipient solely from an untrusted browser parameter.

1. Verify and accept invoice events

  1. Configure your Xero app’s webhook subscription and receiver according to the current Xero developer instructions. Complete its validation challenge before expecting normal delivery.
  2. Read the original request bytes. Verify x-xero-signature as a base64 HMAC-SHA256 of those bytes using the webhook key, with a constant-time comparison. Do not reuse IllyVoIP’s timestamp-prefixed signature format for Xero.
  3. Accept only the event categories and tenant identities your integration is configured to handle. Treat the event as a notification of a change, not as a complete invoice record.
  4. Persist the event or a refresh job durably before acknowledging it. Repeated deliveries must converge on the same invoice-refresh work rather than create a fresh SMS for each delivery.

2. Read the current invoice from the correct tenant

For each permitted invoice event, request the current invoice by its resourceId through the fixed Xero Accounting API host, with the authorised OAuth token and xero-tenant-id. Construct the documented invoice path from the validated ID rather than following an arbitrary event URL with your credentials.

For example, use the read endpoint GET /api.xro/2.0/Invoices/{InvoiceID}. Check the returned InvoiceID, contact, type, status, due date, currency and amount due. A normal customer sales-invoice reminder policy might require Type: ACCREC, Status: AUTHORISED and a positive AmountDue, plus your own overdue-date rule. Do not send for drafts, voided, deleted or paid invoices merely because an older event requested a refresh.

3. Map the approved recipient explicitly

Use your application’s reviewed contact mapping to select one complete international phone number. An accounting contact’s first phone field is not automatically the person authorised to receive invoice messages. Preserve consent, exclusions and the customer’s preferred channel. If no valid recipient is mapped, record a review item rather than guessing a number.

Keep the SMS brief and avoid exposing a full financial record on a shared phone. If it contains a payment link, use your recognised authenticated service or approved Xero link mechanism; do not invent a public invoice URL by concatenating the invoice ID.

4. Persist one reminder intent

Store a unique reminder identity containing tenant, invoice, reminder stage and the intended due/send revision. Freeze its recipient, sender and message when authorising the send. A changed schedule or invoice must invalidate the old pending intent. Keep already accepted message IDs and unresolved submissions separate from unsent work.

A periodic reconciliation job should reread pending eligible invoices even if a webhook was missed. It should not recreate reminders whose ledger records already show acceptance. Just before dispatch, reread the invoice and recipient eligibility to reduce the chance of sending after payment; a payment racing the send can still occur, so word the reminder politely.

5. Submit through IllyVoIP and keep the result

Use POST /api/v1/sms/messages at https://api.illyvoip.com, with X-Api-Key, JSON content type and the reminder’s persisted Idempotency-Key. The body has this shape:

{"from":"YOUR_ALLOWED_SENDER","to":["YOUR_AUTHORIZED_NUMBER"],"message":"Your invoice reminder text."}

Replace placeholders using the reviewed intent. Use a stable key of 8–128 permitted letters, numbers, dots, colons, underscores or dashes. An identical retry uses the same key and unchanged body. Store queued_message_ids, invalid_numbers and any error reference. An accepted message is queued, not necessarily delivered; use the returned ID for status checks or verified delivery events.

6. Check payment, duplicate and failure scenarios

Use synthetic fixtures for duplicate invoice events, wrong tenant, invalid signature, invoice paid after scheduling, a rescheduled reminder and a send response lost after acceptance. None should blindly create a replacement SMS. Keep Xero API throttling and authentication recovery separate from IllyVoIP submission recovery. A failed invoice read means “not verified,” not “still unpaid.” Start live operation only with one authorised recipient and a reviewed template; production SMS can incur charges.

Related guides

Reference

Current instructions and technical reference: Xero webhook specification, Xero Accounting API specification.

Reviewed 12 October 2026 against the current IllyVoIP controls, implementation and applicable references. Available options depend on account permissions and service state.