Alto (Vebra / Zoopla) · AsyncAPI Specification

Alto Webhooks

Version 1.0.0

Event notifications Alto delivers to a partner-hosted HTTPS endpoint when data changes in an Alto agency tenancy. Faithfully transcribed by API Evangelist from the webhook catalogue Alto publishes at https://developers.vebraalto.com/guides/webhooks/ — Alto itself publishes no AsyncAPI document. Notifications are deliberately thin: each one names WHAT changed and WHERE to fetch it, and the receiver is expected to call the Alto REST API to read current state. Subscriptions are not self-serve; a partner emails connectsupport@altosoftwaregroup.co.uk with the integration name, the receiving endpoint URL, the event types wanted and the preferred authentication method, and Alto configures the subscription manually.

View Spec View on GitHub Real EstateUnited KingdomPropTechProperty ListingsCRMProperty ManagementRentalsConveyancingEstate AgencyTenancyWebhooksEventsLettingsSales ProgressionProperty DataReal Estate SoftwareAsyncAPIWebhooksEvents

Channels

altoNotifications
A single partner endpoint receives every subscribed event type. Alto sends one HTTP POST per notification with Content-Type application/json. The partner routes on the CloudEvents `type` field and, where one endpoint serves several integrations, on data.integrationId.

Messages

ContactCreated
Contact.Created
A contact is created
ContactModified
Contact.Modified
A contact is modified
PropertyCreated
Property.Created
A property is created
PropertyModified
Property.Modified
A property is modified
PropertyMarketingInformationSent
Property.MarketingInformationSent
Marketing information is sent for a property
BranchModified
Branch.Modified
A branch is modified
AppointmentCreated
Appointment.Created
An appointment is created
AppointmentModified
Appointment.Modified
An appointment is modified
TenancyCreated
Tenancy.Created
A tenancy is created
TenancyModified
Tenancy.Modified
A tenancy is modified
TenancyReferencingPassed
Tenancy.ReferencingPassed
A tenancy passes referencing
TenancyRenewed
Tenancy.Renewed
A tenancy is renewed
TenancyVacated
Tenancy.Vacated
A tenancy is vacated
OfferCreated
Offer.Created
An offer is created
OfferModified
Offer.Modified
An offer is modified
OfferAccepted
Offer.Accepted
An offer is accepted
OfferWithdrawn
Offer.Withdrawn
An offer is withdrawn
SalesProgressionExchanged
SalesProgression.Exchanged
A sale reaches exchange
SalesProgressionMilestoneCompleted
SalesProgression.Milestone.Completed
A sales progression milestone is completed
LeadReceived
Lead.Received
A lead is received
LeadAccepted
Lead.Accepted
A lead is accepted
LeadModified
Lead.Modified
A lead is modified
IntegrationEnabled
Integration.Enabled
Your integration is enabled for a group
IntegrationDisabled
Integration.Disabled
Your integration is disabled for a group
IntegrationActivated
Integration.Activated
Your integration is activated for a branch
IntegrationDeactivated
Integration.Deactivated
Your integration is deactivated for a branch

Servers

https
partnerEndpoint
The HTTPS endpoint the partner hosts and supplies to Alto during onboarding. Alto is the client on this channel; the partner is the server.

AsyncAPI Specification

Raw ↑
asyncapi: 3.0.0
id: urn:apievangelist:alto-vebra:webhooks
info:
  title: Alto Webhooks
  version: 1.0.0
  description: 'Event notifications Alto delivers to a partner-hosted HTTPS endpoint when data changes
    in an Alto agency tenancy. Faithfully transcribed by API Evangelist from the webhook catalogue Alto
    publishes at https://developers.vebraalto.com/guides/webhooks/ — Alto itself publishes no AsyncAPI
    document. Notifications are deliberately thin: each one names WHAT changed and WHERE to fetch it,
    and the receiver is expected to call the Alto REST API to read current state. Subscriptions are not
    self-serve; a partner emails connectsupport@altosoftwaregroup.co.uk with the integration name, the
    receiving endpoint URL, the event types wanted and the preferred authentication method, and Alto configures
    the subscription manually.'
  contact:
    name: Alto Connect Support
    email: connectsupport@altosoftwaregroup.co.uk
    url: https://developers.vebraalto.com/guides/webhooks/
  externalDocs:
    url: https://developers.vebraalto.com/guides/webhooks/
    description: Alto webhooks guide
defaultContentType: application/json
servers:
  partnerEndpoint:
    host: '{partnerHost}'
    pathname: /{partnerPath}
    protocol: https
    description: The HTTPS endpoint the partner hosts and supplies to Alto during onboarding. Alto is
      the client on this channel; the partner is the server.
    variables:
      partnerHost:
        description: Partner-controlled host, reachable from the public internet.
        default: example.partner.com
      partnerPath:
        description: Partner-controlled path that receives the POST.
        default: alto/webhooks
    security:
    - $ref: '#/components/securitySchemes/xSignature'
    - $ref: '#/components/securitySchemes/basicAuth'
    - $ref: '#/components/securitySchemes/oauth2ClientCredentials'
channels:
  altoNotifications:
    address: /
    title: Alto notifications
    description: A single partner endpoint receives every subscribed event type. Alto sends one HTTP POST
      per notification with Content-Type application/json. The partner routes on the CloudEvents `type`
      field and, where one endpoint serves several integrations, on data.integrationId.
    servers:
    - $ref: '#/servers/partnerEndpoint'
    messages:
      ContactCreated:
        $ref: '#/components/messages/ContactCreated'
      ContactModified:
        $ref: '#/components/messages/ContactModified'
      PropertyCreated:
        $ref: '#/components/messages/PropertyCreated'
      PropertyModified:
        $ref: '#/components/messages/PropertyModified'
      PropertyMarketingInformationSent:
        $ref: '#/components/messages/PropertyMarketingInformationSent'
      BranchModified:
        $ref: '#/components/messages/BranchModified'
      AppointmentCreated:
        $ref: '#/components/messages/AppointmentCreated'
      AppointmentModified:
        $ref: '#/components/messages/AppointmentModified'
      TenancyCreated:
        $ref: '#/components/messages/TenancyCreated'
      TenancyModified:
        $ref: '#/components/messages/TenancyModified'
      TenancyReferencingPassed:
        $ref: '#/components/messages/TenancyReferencingPassed'
      TenancyRenewed:
        $ref: '#/components/messages/TenancyRenewed'
      TenancyVacated:
        $ref: '#/components/messages/TenancyVacated'
      OfferCreated:
        $ref: '#/components/messages/OfferCreated'
      OfferModified:
        $ref: '#/components/messages/OfferModified'
      OfferAccepted:
        $ref: '#/components/messages/OfferAccepted'
      OfferWithdrawn:
        $ref: '#/components/messages/OfferWithdrawn'
      SalesProgressionExchanged:
        $ref: '#/components/messages/SalesProgressionExchanged'
      SalesProgressionMilestoneCompleted:
        $ref: '#/components/messages/SalesProgressionMilestoneCompleted'
      LeadReceived:
        $ref: '#/components/messages/LeadReceived'
      LeadAccepted:
        $ref: '#/components/messages/LeadAccepted'
      LeadModified:
        $ref: '#/components/messages/LeadModified'
      IntegrationEnabled:
        $ref: '#/components/messages/IntegrationEnabled'
      IntegrationDisabled:
        $ref: '#/components/messages/IntegrationDisabled'
      IntegrationActivated:
        $ref: '#/components/messages/IntegrationActivated'
      IntegrationDeactivated:
        $ref: '#/components/messages/IntegrationDeactivated'
operations:
  receiveAltoNotification:
    action: receive
    channel:
      $ref: '#/channels/altoNotifications'
    title: Receive an Alto change notification
    summary: Alto POSTs a CloudEvents 1.0 notification to the partner endpoint.
    description: 'The endpoint must answer 2xx to acknowledge. Alto retries a non-2xx, unreachable or
      timed-out delivery up to 10 times for up to 6 hours from when the change occurred, after which the
      notification is dropped. Delivery order is NOT guaranteed and duplicates are expected: the `id`
      field is stable across retries of the same notification and is the documented de-duplication key.
      Acknowledge fast and process asynchronously. Treat the notification as a signal, then re-fetch the
      resource named by `subject` from the Alto REST API using data.agencyRef as the AgencyRef header.'
    messages:
    - $ref: '#/channels/altoNotifications/messages/ContactCreated'
    - $ref: '#/channels/altoNotifications/messages/ContactModified'
    - $ref: '#/channels/altoNotifications/messages/PropertyCreated'
    - $ref: '#/channels/altoNotifications/messages/PropertyModified'
    - $ref: '#/channels/altoNotifications/messages/PropertyMarketingInformationSent'
    - $ref: '#/channels/altoNotifications/messages/BranchModified'
    - $ref: '#/channels/altoNotifications/messages/AppointmentCreated'
    - $ref: '#/channels/altoNotifications/messages/AppointmentModified'
    - $ref: '#/channels/altoNotifications/messages/TenancyCreated'
    - $ref: '#/channels/altoNotifications/messages/TenancyModified'
    - $ref: '#/channels/altoNotifications/messages/TenancyReferencingPassed'
    - $ref: '#/channels/altoNotifications/messages/TenancyRenewed'
    - $ref: '#/channels/altoNotifications/messages/TenancyVacated'
    - $ref: '#/channels/altoNotifications/messages/OfferCreated'
    - $ref: '#/channels/altoNotifications/messages/OfferModified'
    - $ref: '#/channels/altoNotifications/messages/OfferAccepted'
    - $ref: '#/channels/altoNotifications/messages/OfferWithdrawn'
    - $ref: '#/channels/altoNotifications/messages/SalesProgressionExchanged'
    - $ref: '#/channels/altoNotifications/messages/SalesProgressionMilestoneCompleted'
    - $ref: '#/channels/altoNotifications/messages/LeadReceived'
    - $ref: '#/channels/altoNotifications/messages/LeadAccepted'
    - $ref: '#/channels/altoNotifications/messages/LeadModified'
    - $ref: '#/channels/altoNotifications/messages/IntegrationEnabled'
    - $ref: '#/channels/altoNotifications/messages/IntegrationDisabled'
    - $ref: '#/channels/altoNotifications/messages/IntegrationActivated'
    - $ref: '#/channels/altoNotifications/messages/IntegrationDeactivated'
    bindings:
      http:
        method: POST
components:
  securitySchemes:
    xSignature:
      type: httpApiKey
      name: x-signature
      in: header
      description: Shared secret agreed during onboarding and presented by Alto on every callback. The
        partner rejects any request that does not present the expected value.
    basicAuth:
      type: http
      scheme: basic
      description: HTTP Basic credentials issued to Alto during onboarding.
    oauth2ClientCredentials:
      type: oauth2
      description: Alto obtains a bearer token from the partner's own authorization server using the client-credentials
        grant and presents it on each request.
      flows:
        clientCredentials:
          tokenUrl: https://partner.example.com/oauth2/token
          availableScopes: {}
      scopes: []
  messages:
    ContactCreated:
      name: Contact.Created
      title: Contact.Created
      summary: A contact is created
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Contact.Created
      x-subject-resource: Contact
      x-fetch-resource: /contacts/{contactId}
      x-fetch-operation-id: GetContact
    ContactModified:
      name: Contact.Modified
      title: Contact.Modified
      summary: A contact is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Contact.Modified
      x-subject-resource: Contact
      x-fetch-resource: /contacts/{contactId}
      x-fetch-operation-id: GetContact
    PropertyCreated:
      name: Property.Created
      title: Property.Created
      summary: A property is created
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Property.Created
      x-subject-resource: Property
      x-fetch-resource: /inventory/{inventoryId}
    PropertyModified:
      name: Property.Modified
      title: Property.Modified
      summary: A property is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Property.Modified
      x-subject-resource: Property
      x-fetch-resource: /inventory/{inventoryId}
    PropertyMarketingInformationSent:
      name: Property.MarketingInformationSent
      title: Property.MarketingInformationSent
      summary: Marketing information is sent for a property
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Property.MarketingInformationSent
      x-subject-resource: Property
      x-fetch-resource: /inventory/{inventoryId}
    BranchModified:
      name: Branch.Modified
      title: Branch.Modified
      summary: A branch is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Branch.Modified
      x-subject-resource: Branch
      x-fetch-resource: /branches/{branchId}
    AppointmentCreated:
      name: Appointment.Created
      title: Appointment.Created
      summary: An appointment is created
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Appointment.Created
      x-subject-resource: Appointment
      x-fetch-resource: /appointments/{appointmentId}/{instanceId}
    AppointmentModified:
      name: Appointment.Modified
      title: Appointment.Modified
      summary: An appointment is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Appointment.Modified
      x-subject-resource: Appointment
      x-fetch-resource: /appointments/{appointmentId}/{instanceId}
    TenancyCreated:
      name: Tenancy.Created
      title: Tenancy.Created
      summary: A tenancy is created
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Tenancy.Created
      x-subject-resource: Tenancy
      x-fetch-resource: /tenancies/{tenancyId}
    TenancyModified:
      name: Tenancy.Modified
      title: Tenancy.Modified
      summary: A tenancy is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Tenancy.Modified
      x-subject-resource: Tenancy
      x-fetch-resource: /tenancies/{tenancyId}
    TenancyReferencingPassed:
      name: Tenancy.ReferencingPassed
      title: Tenancy.ReferencingPassed
      summary: A tenancy passes referencing
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Tenancy.ReferencingPassed
      x-subject-resource: Tenancy
      x-fetch-resource: /tenancies/{tenancyId}
    TenancyRenewed:
      name: Tenancy.Renewed
      title: Tenancy.Renewed
      summary: A tenancy is renewed
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Tenancy.Renewed
      x-subject-resource: Tenancy
      x-fetch-resource: /tenancies/{tenancyId}
    TenancyVacated:
      name: Tenancy.Vacated
      title: Tenancy.Vacated
      summary: A tenancy is vacated
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Tenancy.Vacated
      x-subject-resource: Tenancy
      x-fetch-resource: /tenancies/{tenancyId}
    OfferCreated:
      name: Offer.Created
      title: Offer.Created
      summary: An offer is created
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Offer.Created
      x-subject-resource: Offer / Sales Progression
      x-fetch-resource: /offers/sales-offer/{offerId}
    OfferModified:
      name: Offer.Modified
      title: Offer.Modified
      summary: An offer is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Offer.Modified
      x-subject-resource: Offer / Sales Progression
      x-fetch-resource: /offers/sales-offer/{offerId}
    OfferAccepted:
      name: Offer.Accepted
      title: Offer.Accepted
      summary: An offer is accepted
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Offer.Accepted
      x-subject-resource: Sales Progression
      x-fetch-resource: /sales-progressions/{offerId}
    OfferWithdrawn:
      name: Offer.Withdrawn
      title: Offer.Withdrawn
      summary: An offer is withdrawn
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Offer.Withdrawn
      x-subject-resource: Offer / Sales Progression
      x-fetch-resource: /offers/sales-offer/{offerId}
    SalesProgressionExchanged:
      name: SalesProgression.Exchanged
      title: SalesProgression.Exchanged
      summary: A sale reaches exchange
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: SalesProgression.Exchanged
      x-subject-resource: Sales Progression
      x-fetch-resource: /sales-progressions/{offerId}
    SalesProgressionMilestoneCompleted:
      name: SalesProgression.Milestone.Completed
      title: SalesProgression.Milestone.Completed
      summary: A sales progression milestone is completed
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: SalesProgression.Milestone.Completed
      x-subject-resource: Sales Progression
      x-fetch-resource: /sales-progressions/{offerId}
    LeadReceived:
      name: Lead.Received
      title: Lead.Received
      summary: A lead is received
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Lead.Received
      x-subject-resource: Lead
      x-fetch-resource: /leads/{leadId}
      x-fetch-operation-id: GetById
    LeadAccepted:
      name: Lead.Accepted
      title: Lead.Accepted
      summary: A lead is accepted
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Lead.Accepted
      x-subject-resource: Lead
      x-fetch-resource: /leads/{leadId}
      x-fetch-operation-id: GetById
    LeadModified:
      name: Lead.Modified
      title: Lead.Modified
      summary: A lead is modified
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Lead.Modified
      x-subject-resource: Lead
      x-fetch-resource: /leads/{leadId}
      x-fetch-operation-id: GetById
    IntegrationEnabled:
      name: Integration.Enabled
      title: Integration.Enabled
      summary: Your integration is enabled for a group
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Integration.Enabled
      x-subject-resource: Integration
      x-fetch-resource: /partners/integration
    IntegrationDisabled:
      name: Integration.Disabled
      title: Integration.Disabled
      summary: Your integration is disabled for a group
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Integration.Disabled
      x-subject-resource: Integration
      x-fetch-resource: /partners/integration
    IntegrationActivated:
      name: Integration.Activated
      title: Integration.Activated
      summary: Your integration is activated for a branch
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Integration.Activated
      x-subject-resource: Integration
      x-fetch-resource: /partners/integration
    IntegrationDeactivated:
      name: Integration.Deactivated
      title: Integration.Deactivated
      summary: Your integration is deactivated for a branch
      contentType: application/json
      payload:
        allOf:
        - $ref: '#/components/schemas/CloudEvent'
        - type: object
          properties:
            type:
              type: string
              const: Integration.Deactivated
      x-subject-resource: Integration
      x-fetch-resource: /partners/integration
  schemas:
    CloudEvent:
      type: object
      description: CloudEvents 1.0 JSON envelope as published in the Alto webhooks guide.
      required:
      - specversion
      - id
      - type
      - source
      - subject
      - time
      - datacontenttype
      - data
      properties:
        specversion:
          type: string
          const: '1.0'
          description: The CloudEvents specification version. Always 1.0.
        id:
          type: string
          description: Unique identifier for this notification, formatted "<event-uuid>|<integrationId>".
            Stable across retries of the same notification — use it to de-duplicate.
          examples:
          - b1e9b0f0-1c2d-4e3f-9a8b-7c6d5e4f3a2b|11111111-2222-3333-4444-555555555555
        type:
          type: string
          description: The event type that was raised.
        source:
          type: string
          const: alto
          description: The system that produced the event. Always "alto".
        subject:
          type: string
          description: Relative URI identifying the resource that changed. Combine with the Alto API base
            URL to re-fetch it.
          examples:
          - /inventory/123456
        time:
          type: string
          format: date-time
          description: The time the originating change occurred, in UTC (ISO 8601).
        datacontenttype:
          type: string
          const: application/json
        data:
          $ref: '#/components/schemas/EventData'
    EventData:
      type: object
      description: Details needed to identify and retrieve the changed resource.
      required:
      - integrationId
      - agencyRef
      - subjectId
      properties:
        integrationId:
          type: string
          description: Identifier of the receiving integration. Use it to route when one endpoint serves
            more than one integration.
        agencyRef:
          type: string
          description: The agency reference associated with the change. Use it as the AgencyRef header
            when calling the Alto REST API.
        branchId:
          type: string
          description: Identifier of the branch the resource belongs to, where applicable.
        subjectId:
          type: string
          description: Identifier of the resource that changed; also the final segment of `subject`.
        relatedSubjects:
          type: array
          description: Related resources, each with its own subjectUri and subjectId. May be empty.
          items:
            type: object
            properties:
              subjectUri:
                type: string
              subjectId:
                type: string
      examples:
      - integrationId: 11111111-2222-3333-4444-555555555555
        agencyRef: YOUR_AGENCY_REF
        branchId: '2681'
        subjectId: '123456'
        relatedSubjects: []
x-apievangelist:
  generated: '2026-07-26'
  method: generated
  source: https://developers.vebraalto.com/guides/webhooks/
  note: Alto publishes no AsyncAPI document. This file is a faithful AsyncAPI 3.0.0 rendering of the webhook
    catalogue, envelope, field table, retry policy and callback security options Alto documents in prose.
    Every event type, field description and constraint here is transcribed from that page; nothing was
    invented. Message payload schemas beyond the CloudEvents envelope are NOT published by Alto — by design,
    the notification carries no resource snapshot.
  event_count: 26
  subscription: manual — email connectsupport@altosoftwaregroup.co.uk
  related_rest_api: openapi/alto-api-openapi.json