Keller Williams · AsyncAPI Specification

Keller Williams Marketplace Webhooks

Version

View Spec View on GitHub Real EstateUnited StatesResidential Real EstateBrokerageFranchiseProperty ListingsPropTechAgent PlatformCRMPartner APIsMarketplaceAustin TexasAsyncAPIWebhooksEvents

AsyncAPI Specification

Raw ↑
generated: '2026-07-26'
method: searched
spec_type: Webhooks
asyncapi_published: false
source:
  - https://developer.kw.com/marketplace-documentation
  - https://developer.kw.com/docs-subscription-creation
  - https://developer.kw.com/docs-subscription-creation-teams
  - https://developer.kw.com/docs-subscription-change
  - https://developer.kw.com/docs-subscription-cancel
  - https://developer.kw.com/docs-status-notification
  - https://developer.kw.com/docs-user-assignment
  - https://developer.kw.com/docs-user-unassignment
  - https://developer.kw.com/docs-synchronous-subscription
  - https://developer.kw.com/docs-asynchronous-subscription
  - https://developer.kw.com/subscription-lifecycle-walkthrough
asyncapi_note: >-
  Keller Williams publishes NO AsyncAPI document. This was confirmed
  structurally, not just by absence of a link: the DevHub portal's own
  catalog record for the one anonymous API returns
  "asyncApiSpecContent": null, "asyncApiSpecId": null and
  "asyncApiSpecFormat": null, and no other API in the catalog is
  anonymously visible. What KW does publish is a complete, sample-payload
  documented webhook catalog for the KW Marketplace, captured verbatim
  below. No AsyncAPI was generated from it — this is the webhook surface
  as published, not a fabricated spec.
summary:
  events: 7
  notice_types: 4
  subscription_states: 5
  delivery: KW Gateway -> partner-registered HTTPS endpoint
  direction: outbound (KW is the publisher, the partner is the subscriber)
transport:
  protocol: https
  method: POST
  content_type: application/json
  endpoint: >-
    Partner-supplied secured HTTPS endpoint registered with the KW team.
    KW recommends one endpoint for sandbox/testing and one for production.
  auth_to_partner:
    supported: [basic, oauth2]
    note: The KW Gateway supports only HTTP Basic authentication or OAuth 2.0 when calling a partner endpoint.
  signing: none published
  retries: not documented
  ordering: not documented
envelope:
  fields:
    app-name: The partner application name.
    access-token: Per-user OAuth access token, present on SUBSCRIPTION_ORDER and USER_ASSIGNMENT only.
    refresh-token: Per-user refresh token, present on SUBSCRIPTION_ORDER and USER_ASSIGNMENT only.
    refresh_token_expires_in: Seconds until the refresh token expires (seen on the teams variant, e.g. "31557599").
    payload.event.type: The event type — SUBSCRIPTION_ORDER, SUBSCRIPTION_CHANGE, SUBSCRIPTION_CANCEL, SUBSCRIPTION_NOTICE, USER_ASSIGNMENT, USER_UNASSIGNMENT.
    payload.event.marketplace.baseUrl: https://marketplace.kw.com
    payload.event.marketplace.partner: KELLERWILLIAMS
    payload.event.flag: DEVELOPMENT in the published samples — the test/live discriminator.
    payload.event.link: '{rel: oidcClient, href: .../api/account/v2/subscriptions/{id}/oidcClient} on order events.'
    payload.event.creator: The KW user who triggered the event (address, email, names, language, locale, openId, uuid).
    payload.event.payload.account.accountIdentifier: The partner-issued unique subscription identifier.
    payload.event.payload.account.status: ACTIVE | SUSPENDED | CANCELLED | FREE_TRIAL | FREE_TRIAL_EXPIRED.
    payload.event.payload.company: Purchasing company/market center (uuid, name, country, phoneNumber, website, externalId).
    payload.event.payload.configuration.entry: Key/value list — KWID, and on team orders roleId and orgId.
    payload.event.payload.order: editionCode, pricingDuration, freeTrial.active, customAttributes.
    payload.event.payload.user: The assigned/unassigned KW user on USER_ASSIGNMENT and USER_UNASSIGNMENT.
    payload.event.payload.notice.type: DEACTIVATED | REACTIVATED | CLOSED | UPCOMING_INVOICE.
  note: >-
    The transport identity of an event is the KWUID delivered in
    configuration.entry — a missing or invalid KWUID is rejected by the
    gateway with BAD_KWUID.
events:
  - name: Subscription Creation
    type: SUBSCRIPTION_ORDER
    docs: https://developer.kw.com/docs-subscription-creation
    description: A KW agent purchases the partner product in the Marketplace. Carries the per-user access and refresh tokens.
    carries_tokens: true
    partner_response:
      synchronous: '200 {"success": "true", "accountIdentifier": "unique-value-for-subscription-order"}'
      asynchronous: '202 {"success": "true"}'
      rejection: '409 {"success": "false", "errorCode": "<partner error code>", "message": "..."}'
  - name: Subscription Creation (Teams)
    type: SUBSCRIPTION_ORDER
    docs: https://developer.kw.com/docs-subscription-creation-teams
    description: >-
      Team/organization variant of the order event. Adds roleId and orgId
      to configuration.entry, a company.externalId, and an
      order.customAttributes.customAttribute of name external_company_role.
    carries_tokens: true
  - name: Subscription Change
    type: SUBSCRIPTION_CHANGE
    docs: https://developer.kw.com/docs-subscription-change
    description: >-
      Edition switch, seat-count change, or metered-item change. Carries
      the updated order (e.g. editionCode "Tier 2") and the existing
      account.accountIdentifier.
    carries_tokens: false
    partner_response: '200 {"success": "true"}'
  - name: Subscription Cancel
    type: SUBSCRIPTION_CANCEL
    docs: https://developer.kw.com/docs-subscription-cancel
    description: The agent cancels; the subscription is removed from the account and charges cease.
    carries_tokens: false
    partner_response: '200 {"success": "true"}'
  - name: Status Notification
    type: SUBSCRIPTION_NOTICE
    docs: https://developer.kw.com/docs-status-notification
    description: Lifecycle state notification carrying a notice.type and the new account.status.
    notice_types: [DEACTIVATED, REACTIVATED, CLOSED, UPCOMING_INVOICE]
    account_states: [SUSPENDED, FREE_TRIAL_EXPIRED, ACTIVE, FREE_TRIAL, CANCELLED]
    carries_tokens: false
  - name: User Assignment
    type: USER_ASSIGNMENT
    docs: https://developer.kw.com/docs-user-assignment
    description: >-
      An additional KW user is assigned a seat on an existing
      subscription. Carries that user's own access and refresh tokens.
    carries_tokens: true
  - name: User Unassignment
    type: USER_UNASSIGNMENT
    docs: https://developer.kw.com/docs-user-unassignment
    description: A KW user's seat is removed from the subscription.
    carries_tokens: false
subscription_lifecycle:
  docs: https://developer.kw.com/subscription-lifecycle-walkthrough
  states: [FREE_TRIAL, ACTIVE, SUSPENDED, FREE_TRIAL_EXPIRED, CANCELLED]
  transitions:
    - trigger: Agent subscribes
      event: SUBSCRIPTION_ORDER
      to: FREE_TRIAL or ACTIVE
    - trigger: Edition / seat / metered change
      event: SUBSCRIPTION_CHANGE
    - trigger: Free trial expires without conversion
      event: SUBSCRIPTION_NOTICE (DEACTIVATED)
      to: FREE_TRIAL_EXPIRED
    - trigger: Free trial cancelled before expiry
      event: SUBSCRIPTION_CANCEL
      to: CANCELLED
      note: No SUBSCRIPTION_NOTICE is emitted in this path.
    - trigger: Manual upgrade to a paid edition during trial
      event: SUBSCRIPTION_CHANGE then SUBSCRIPTION_NOTICE (REACTIVATED)
      to: ACTIVE
    - trigger: Automatic upgrade at trial end
      event: SUBSCRIPTION_NOTICE (REACTIVATED)
      to: ACTIVE
      note: No SUBSCRIPTION_CHANGE is emitted in this path.
    - trigger: Grace period expires after FREE_TRIAL_EXPIRED
      event: SUBSCRIPTION_NOTICE (CLOSED)
      to: CANCELLED
    - trigger: Missed invoice payment
      event: SUBSCRIPTION_NOTICE (DEACTIVATED)
      to: SUSPENDED
      note: company_entitlement suspension reason is set to PAYMENT_OVERDUE. Delinquency defaults to three missed payments.
    - trigger: Overdue invoice paid
      event: SUBSCRIPTION_NOTICE (REACTIVATED)
      to: ACTIVE
    - trigger: Agent or owner cancels
      event: SUBSCRIPTION_CANCEL
      to: CANCELLED
provisioning_modes:
  - mode: synchronous
    docs: https://developer.kw.com/docs-synchronous-subscription
    description: >-
      Everything turns on at once. The partner confirms the
      accountIdentifier in its 200 response and billing begins
      immediately. KW states most Marketplace partners need only this.
  - mode: asynchronous
    docs: https://developer.kw.com/docs-asynchronous-subscription
    description: >-
      Used when the partner needs extra steps (profile completion,
      identity confirmation, onboarding/training). The partner returns 202,
      the subscription enters PENDING, and NO billing of any kind starts
      until the partner confirms.
    confirm_endpoint: https://<ENVIRONMENT>/v1/subscription/async/confirm
    confirm_body: '{"success": "true", "accountIdentifier": "unique-value-for-subscription-order"}'
    confirm_response: '201 {"success": true, "kwuid": "1"}'
    reject_body: '{"success": "false", "errorCode": "USER_ALREADY_EXISTS", "message": "..."}'
    reject_response: '200 {"success": true, "kwuid": "1"}'
    enablement: Async subscriptions must be enabled per partner by KW (INTERNAL_SERVER_ERROR otherwise).
partner_callbacks:
  errors: errors/keller-williams-error-codes.yml#partner_response_errors
related_apis:
  metered_billing:
    endpoint: https://<ENVIRONMENT>/v1/subscription/billing/usage
    docs: https://developer.kw.com/metered-billing
    description: >-
      Partner reports consumption back to KW against a pre-configured unit
      type and price. Body is {account.accountIdentifier, items[{quantity, unit}]}.
    unit_types_published: 130
    example_units: [USER, ACTIVE_USERS, API_CALLS, CONTACT, EMAIL, TRANSACTION_FEE, PROPERTY, DOCUMENT, LICENSE, SESSION]
  timelines:
    docs: https://developer.kw.com/timelines
    description: >-
      Third-party authored contact timeline events posted into Command.
      Common fields type/date/isInteraction/addedBy{author:"THIRDPARTY",id}/attributes,
      with per-type attribute shapes (NOTE, INFO, ...). Timeline data is
      persisted asynchronously and may take seconds to appear on GET.