Xero · AsyncAPI Specification

Xero Webhooks

Version 1.0.0

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 Spec View on GitHub AccountingBank FeedsFinanceFinancial ServicesInvoicingPayrollSmall BusinessAsyncAPIWebhooksEvents

Channels

invoices
subscribe receiveInvoiceEvent
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
subscribe receiveContactEvent
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 Specification

Raw ↑
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'