AsyncAPI 2.6 description of Xero's outbound webhook surface for the INVOICE and CONTACT event categories. Xero delivers event notifications by issuing HTTP POST requests with a JSON body to a single subscriber URL configured per application in the Xero developer portal. Each delivery carries one batch payload (`WebhookEvent`) containing one or more `events`. Every event declares the `eventCategory` (`INVOICE` or `CONTACT`) and the `eventType` (`CREATE` or `UPDATE`). Xero does not push the changed resource itself; the subscriber dereferences `resourceUrl` / `resourceId` against the Xero Accounting API to fetch the current state of the resource for the identified `tenantId`. Source documentation: - Webhooks overview: https://developer.xero.com/documentation/guides/webhooks/overview/ - Webhooks OpenAPI (canonical schema source): https://github.com/XeroAPI/Xero-OpenAPI/blob/master/xero-webhooks.yaml Security and signing: Every webhook POST is signed by Xero. The `x-xero-signature` HTTP request header carries a Base64-encoded HMAC-SHA256 of the raw, unmodified JSON request body, computed with the application's webhook signing key (configured in the Xero developer portal) as the secret. Subscribers MUST recompute the HMAC over the raw bytes of the body and compare it against the header using a constant-time comparison. On mismatch the subscriber MUST respond `401 Unauthorized`; on match it MUST respond `200 OK`. The same signed request shape is used during the initial "intent to receive" verification handshake.
View SpecView on GitHubAccountingBank FeedsFinanceFinancial ServicesInvoicingPayrollSmall BusinessAsyncAPIWebhooksEvents
Channels
invoices
subscribereceiveInvoiceEvent
Receive Invoice webhook events (CREATE, UPDATE).
Notifications for organisation invoice events. Xero emits an event when an invoice is created or updated (including state transitions such as AUTHORISED, PAID, VOIDED, or archival). The payload does not include the invoice body; subscribers GET `resourceUrl` against the Xero Accounting API using credentials for `tenantId` to retrieve the current resource.
contacts
subscribereceiveContactEvent
Receive Contact webhook events (CREATE, UPDATE).
Notifications for organisation contact events. Xero emits an event when a contact is created or updated (including archival, which Xero models as an update). The payload does not include the contact body; subscribers GET `resourceUrl` against the Xero Accounting API using credentials for `tenantId` to retrieve the current resource.
Messages
✉
InvoiceCreateEvent
Invoice Create
Emitted when an invoice resource is created in a Xero organisation.
✉
InvoiceUpdateEvent
Invoice Update
Emitted when an invoice resource is updated (including archival) in a Xero organisation.
✉
ContactCreateEvent
Contact Create
Emitted when a contact resource is created in a Xero organisation.
✉
ContactUpdateEvent
Contact Update
Emitted when a contact resource is updated (including archival) in a Xero organisation.
Servers
https
subscriber{webhookUrl}
Customer-hosted HTTPS endpoint that receives webhook POSTs from Xero. The full URL is configured per application in the Xero developer portal (My Apps -> Webhooks). A single delivery URL receives events for every event category the application subscribes to.
asyncapi: 2.6.0
info:
title: Xero Webhooks
version: '1.0.0'
description: |-
AsyncAPI 2.6 description of Xero's outbound webhook surface for the INVOICE
and CONTACT event categories. Xero delivers event notifications by issuing
HTTP POST requests with a JSON body to a single subscriber URL configured
per application in the Xero developer portal.
Each delivery carries one batch payload (`WebhookEvent`) containing one or
more `events`. Every event declares the `eventCategory` (`INVOICE` or
`CONTACT`) and the `eventType` (`CREATE` or `UPDATE`). Xero does not push
the changed resource itself; the subscriber dereferences `resourceUrl` /
`resourceId` against the Xero Accounting API to fetch the current state of
the resource for the identified `tenantId`.
Source documentation:
- Webhooks overview:
https://developer.xero.com/documentation/guides/webhooks/overview/
- Webhooks OpenAPI (canonical schema source):
https://github.com/XeroAPI/Xero-OpenAPI/blob/master/xero-webhooks.yaml
Security and signing:
Every webhook POST is signed by Xero. The `x-xero-signature` HTTP request
header carries a Base64-encoded HMAC-SHA256 of the raw, unmodified JSON
request body, computed with the application's webhook signing key
(configured in the Xero developer portal) as the secret. Subscribers
MUST recompute the HMAC over the raw bytes of the body and compare it
against the header using a constant-time comparison. On mismatch the
subscriber MUST respond `401 Unauthorized`; on match it MUST respond
`200 OK`. The same signed request shape is used during the initial
"intent to receive" verification handshake.
contact:
name: Xero Platform Team
url: https://developer.xero.com
email: [email protected]
license:
name: Xero Developer Platform Terms and Conditions
url: https://developer.xero.com/xero-developer-platform-terms-conditions/
defaultContentType: application/json
servers:
subscriber:
url: '{webhookUrl}'
protocol: https
description: |-
Customer-hosted HTTPS endpoint that receives webhook POSTs from Xero.
The full URL is configured per application in the Xero developer
portal (My Apps -> Webhooks). A single delivery URL receives events
for every event category the application subscribes to.
variables:
webhookUrl:
default: https://example.com/xero/webhook
description: Fully-qualified HTTPS URL of the subscriber endpoint.
security:
- xeroSignature: []
channels:
invoices:
description: |-
Notifications for organisation invoice events. Xero emits an event when
an invoice is created or updated (including state transitions such as
AUTHORISED, PAID, VOIDED, or archival). The payload does not include the
invoice body; subscribers GET `resourceUrl` against the Xero Accounting
API using credentials for `tenantId` to retrieve the current resource.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
operationId: receiveInvoiceEvent
summary: Receive Invoice webhook events (CREATE, UPDATE).
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
message:
oneOf:
- $ref: '#/components/messages/InvoiceCreateEvent'
- $ref: '#/components/messages/InvoiceUpdateEvent'
contacts:
description: |-
Notifications for organisation contact events. Xero emits an event when
a contact is created or updated (including archival, which Xero models
as an update). The payload does not include the contact body;
subscribers GET `resourceUrl` against the Xero Accounting API using
credentials for `tenantId` to retrieve the current resource.
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
subscribe:
operationId: receiveContactEvent
summary: Receive Contact webhook events (CREATE, UPDATE).
bindings:
http:
type: request
method: POST
bindingVersion: 0.3.0
message:
oneOf:
- $ref: '#/components/messages/ContactCreateEvent'
- $ref: '#/components/messages/ContactUpdateEvent'
components:
securitySchemes:
xeroSignature:
type: httpApiKey
in: header
name: x-xero-signature
description: |-
Base64-encoded HMAC-SHA256 of the raw JSON request body, keyed by the
application's webhook signing key (a per-application secret displayed
in the Xero developer portal). HTTP header names are case-insensitive;
Xero documents the header as `x-xero-signature` and it is also
commonly referenced as `X-Xero-Signature`.
Verification (subscriber side):
1. Read the raw, unmodified request body bytes.
2. Compute HMAC-SHA256(signingKey, rawBody) and Base64-encode it.
3. Constant-time compare against the `x-xero-signature` header.
4. On match respond `200 OK`; on mismatch respond `401 Unauthorized`.
messages:
InvoiceCreateEvent:
name: InvoiceCreateEvent
title: Invoice Create
summary: Emitted when an invoice resource is created in a Xero organisation.
contentType: application/json
bindings:
http:
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
bindingVersion: 0.3.0
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
payload:
$ref: '#/components/schemas/InvoiceWebhookEvent'
examples:
- name: invoiceCreate
summary: Single INVOICE / CREATE event batch.
payload:
events:
- resourceUrl: https://api.xero.com/api.xro/2.0/Invoices/55d84274-a3da-4829-a7c0-0cab601b95cc
resourceId: 55d84274-a3da-4829-a7c0-0cab601b95cc
tenantId: aef86862-2015-4b6b-88bc-d89032cecc50
tenantType: ORGANISATION
eventCategory: INVOICE
eventType: CREATE
eventDateUtc: '2026-05-30T00:44:09.923'
firstEventSequence: 1
lastEventSequence: 1
entropy: FXNGWLCCGVANWHKILRUB
InvoiceUpdateEvent:
name: InvoiceUpdateEvent
title: Invoice Update
summary: Emitted when an invoice resource is updated (including archival) in a Xero organisation.
contentType: application/json
bindings:
http:
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
bindingVersion: 0.3.0
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
payload:
$ref: '#/components/schemas/InvoiceWebhookEvent'
examples:
- name: invoiceUpdate
summary: Single INVOICE / UPDATE event batch.
payload:
events:
- resourceUrl: https://api.xero.com/api.xro/2.0/Invoices/55d84274-a3da-4829-a7c0-0cab601b95cc
resourceId: 55d84274-a3da-4829-a7c0-0cab601b95cc
tenantId: aef86862-2015-4b6b-88bc-d89032cecc50
tenantType: ORGANISATION
eventCategory: INVOICE
eventType: UPDATE
eventDateUtc: '2026-05-30T00:48:11.117'
firstEventSequence: 2
lastEventSequence: 2
entropy: PQRSTUVWXYZABCDEFGHI
ContactCreateEvent:
name: ContactCreateEvent
title: Contact Create
summary: Emitted when a contact resource is created in a Xero organisation.
contentType: application/json
bindings:
http:
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
bindingVersion: 0.3.0
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
payload:
$ref: '#/components/schemas/ContactWebhookEvent'
examples:
- name: contactCreate
summary: Single CONTACT / CREATE event batch.
payload:
events:
- resourceUrl: https://api.xero.com/api.xro/2.0/Contacts/717f2bfc-c6d4-41fd-b238-3f2f0c0cf777
resourceId: 717f2bfc-c6d4-41fd-b238-3f2f0c0cf777
tenantId: c2cc9b6e-9458-4c7d-93cc-f02b81b0594f
tenantType: ORGANISATION
eventCategory: CONTACT
eventType: CREATE
eventDateUtc: '2026-05-30T01:15:39.902'
firstEventSequence: 1
lastEventSequence: 1
entropy: S0m3r4Nd0mt3xt
ContactUpdateEvent:
name: ContactUpdateEvent
title: Contact Update
summary: Emitted when a contact resource is updated (including archival) in a Xero organisation.
contentType: application/json
bindings:
http:
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
bindingVersion: 0.3.0
headers:
type: object
properties:
x-xero-signature:
type: string
description: Base64-encoded HMAC-SHA256 of the raw request body.
required:
- x-xero-signature
payload:
$ref: '#/components/schemas/ContactWebhookEvent'
examples:
- name: contactUpdate
summary: Single CONTACT / UPDATE event batch.
payload:
events:
- resourceUrl: https://api.xero.com/api.xro/2.0/Contacts/717f2bfc-c6d4-41fd-b238-3f2f0c0cf777
resourceId: 717f2bfc-c6d4-41fd-b238-3f2f0c0cf777
tenantId: c2cc9b6e-9458-4c7d-93cc-f02b81b0594f
tenantType: ORGANISATION
eventCategory: CONTACT
eventType: UPDATE
eventDateUtc: '2026-05-30T01:17:02.418'
firstEventSequence: 2
lastEventSequence: 2
entropy: A1B2C3D4E5F6G7H8I9J0
schemas:
WebhookEvent:
type: object
description: |-
Batch envelope POSTed by Xero to the subscriber URL. One delivery may
contain multiple `events`. The envelope is the canonical payload that
is HMAC-SHA256 signed and surfaced in the `x-xero-signature` header.
required:
- events
- firstEventSequence
- lastEventSequence
- entropy
properties:
events:
type: array
description: A list of events that have occurred.
items:
$ref: '#/components/schemas/Event'
firstEventSequence:
type: integer
minimum: 1
maximum: 2147483647
description: The sequence number of the first event in the list.
lastEventSequence:
type: integer
minimum: 1
maximum: 2147483647
description: The sequence number of the last event in the list.
entropy:
type: string
description: A random string included by Xero for security or validation purposes.
Event:
type: object
description: A single change notification emitted by Xero.
required:
- resourceUrl
- resourceId
- eventDateUtc
- eventType
- eventCategory
- tenantId
- tenantType
properties:
resourceUrl:
type: string
format: uri
description: The URL to retrieve the resource that has changed.
resourceId:
type: string
format: uuid
description: The ID of the resource that has changed (e.g. InvoiceID or ContactID).
eventDateUtc:
type: string
format: date-time
description: The date and time the event occurred (UTC).
eventType:
type: string
description: The type of event that occurred.
enum:
- CREATE
- UPDATE
eventCategory:
type: string
description: The category of event that occurred. Only categories the application is subscribed to are delivered.
enum:
- INVOICE
- CONTACT
tenantId:
type: string
format: uuid
description: The ID of the tenant (OrganisationID) the event relates to.
tenantType:
type: string
description: The type of tenant. INVOICE and CONTACT events are always emitted for an ORGANISATION tenant.
enum:
- ORGANISATION
InvoiceEvent:
allOf:
- $ref: '#/components/schemas/Event'
- type: object
properties:
eventCategory:
type: string
enum:
- INVOICE
resourceUrl:
type: string
format: uri
description: URL of the invoice resource on the Xero Accounting API.
example: https://api.xero.com/api.xro/2.0/Invoices/55d84274-a3da-4829-a7c0-0cab601b95cc
ContactEvent:
allOf:
- $ref: '#/components/schemas/Event'
- type: object
properties:
eventCategory:
type: string
enum:
- CONTACT
resourceUrl:
type: string
format: uri
description: URL of the contact resource on the Xero Accounting API.
example: https://api.xero.com/api.xro/2.0/Contacts/717f2bfc-c6d4-41fd-b238-3f2f0c0cf777
InvoiceWebhookEvent:
description: Batch envelope whose `events[]` are constrained to the INVOICE category.
allOf:
- $ref: '#/components/schemas/WebhookEvent'
- type: object
properties:
events:
type: array
items:
$ref: '#/components/schemas/InvoiceEvent'
ContactWebhookEvent:
description: Batch envelope whose `events[]` are constrained to the CONTACT category.
allOf:
- $ref: '#/components/schemas/WebhookEvent'
- type: object
properties:
events:
type: array
items:
$ref: '#/components/schemas/ContactEvent'