> ## Documentation Index
> Fetch the complete documentation index at: https://partner.headout.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create event subscription

Register an HTTPS endpoint to receive real-time product event notifications. See [Event subscription notification](https://partner.headout.com/docs/api-partner/v2/event-subscriptions/webhook-event.md) for the delivered payload, signature verification, and retry behavior.

The response includes a one-time `signingSecret` used to verify the `X-Headout-Signature` header on delivered events — store it immediately, it cannot be retrieved again. Use [Rotate signing secret](https://partner.headout.com/docs/api-partner/v2/event-subscriptions/rotate-secret.md) if you lose it.

`authentication.value` is sent verbatim as the `Authorization` header on every delivery attempt, including retries. It must be 6–1024 characters with no control characters, and is never returned by a read — only a masked `authentication.valueHint`.

Subscriptions are created active and start receiving events immediately. Pass `"active": false` to create one paused, then enable it with [Update event subscription](https://partner.headout.com/docs/api-partner/v2/event-subscriptions/update.md).

### Error responses

Errors on the event subscription endpoints use the same envelope as the rest of the Partner API. The HTTP status tells you the class of failure; `error.code` is the stable, machine-readable value to branch on.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "timestamp": 1786441790000,
  "traceId": "aad8e04d4cb6d466",
  "traceTokenOriginal": "E33C34A07812483E9DE02FF272F48A34",
  "error": {
    "code": "CAL-P0005",
    "message": "url must use https",
    "detailedMessage": "field=url"
  }
}
```

| Field | Description |
| - | - |
| `error.code` | Stable identifier for the failure. Branch on this, not on `message`. |
| `error.message` | Human-readable explanation, safe to log or surface to an operator. Wording may change. |
| `error.detailedMessage` | Present when there is structured context: the offending field as `field=<name>`, or a limit as `limit=<n>`. Omitted otherwise. |
| `traceTokenOriginal` | Quote this when raising a support request. Also returned in the `X-Headout-Trace-Id` response header. |

| `error.code` | Status | Meaning |
| - | - | - |
| `CAL-P0005` | 400 | A field failed validation. `detailedMessage` names it. |
| `CAL-P0006` | 400 | `eventTypes` contains a value that isn't a supported event type. |
| `CAL-P0001` | 400 | The body isn't valid JSON, or a field has the wrong type. |
| `CAL-P0009` | 409 | You've reached the maximum number of subscriptions. `detailedMessage` carries the limit. Delete one before creating another. |
| `CAL-P0007` | 422 | The URL was rejected as unsafe for delivery. It must be a public HTTPS endpoint with no embedded credentials. |
| `CAL-P0008` | 404 | No subscription with that id exists for your account. Also returned for a subscription you have deleted. |
| `CAL-9901`, `CAL-P0010` | 404 | No such route. Most often a missing trailing slash, as every path ends in `/`. |
| `CAL-P0002` | 405 | That method isn't supported on this path. |
| `CAL-P0003` | 415 | Unsupported `Content-Type`. Send `application/json`. |
| `CAL-P0011`, `CAL-P0012` | 502, 503 | Temporarily unavailable. Retry with backoff. |
| `CAL-P0013`, `CAL-9904` | 5xx | Unexpected failure on our side. Retry; if it persists, quote `traceTokenOriginal`. |

> [!NOTE]
>
> `message` wording is not part of the contract and may be reworded without notice. Treat `error.code` as the only stable signal.

```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --location 'https://www.headout.com/api/public/v2/event-subscriptions/' \
--header 'Headout-Auth: <YOUR_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
  "url": "https://your-domain.com/webhooks/headout/events",
  "eventTypes": ["product.listing_status_changed"],
  "authentication": {
    "type": "AUTHORIZATION_HEADER",
    "value": "Bearer <YOUR_SECRET_TOKEN>"
  },
  "description": "Production event subscription"
}'
```

```json 201 theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "id": "whsub_01j9z8x7v6w5u4t3s2r1q0p9o8",
  "url": "https://your-domain.com/webhooks/headout/events",
  "eventTypes": ["product.listing_status_changed"],
  "description": "Production event subscription",
  "active": true,
  "createdAt": "2026-07-30T10:15:00Z",
  "updatedAt": "2026-07-30T10:15:00Z",
  "authentication": {
    "type": "AUTHORIZATION_HEADER",
    "valueHint": "oken"
  },
  "signingSecret": "dingdong_AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA",
  "signingSecretHint": "B0eHyA"
}
```

```json 400 theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "timestamp": 1786441790000,
  "traceId": "aad8e04d4cb6d466",
  "traceTokenOriginal": "E33C34A07812483E9DE02FF272F48A34",
  "error": {
    "code": "CAL-P0005",
    "message": "url must be an absolute https URL",
    "detailedMessage": "field=url"
  }
}
```

```json 409 theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "timestamp": 1786441790000,
  "traceId": "aad8e04d4cb6d466",
  "traceTokenOriginal": "E33C34A07812483E9DE02FF272F48A34",
  "error": {
    "code": "CAL-P0009",
    "message": "you already have the maximum number of event subscriptions (5)",
    "detailedMessage": "limit=5"
  }
}
```

```json 422 theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "timestamp": 1786441790000,
  "traceId": "aad8e04d4cb6d466",
  "traceTokenOriginal": "E33C34A07812483E9DE02FF272F48A34",
  "error": {
    "code": "CAL-P0007",
    "message": "url could not be verified as safe for delivery"
  }
}
```


## OpenAPI

````yaml POST /api/public/v2/event-subscriptions/
openapi: 3.1.0
info:
  title: Headout API Docs - Common v2
  version: 0.0.1
servers:
  - url: https://www.headout.com
    description: Production server
  - url: https://www.sandbox-headout.com
    description: Sandbox server
security: []
paths:
  /api/public/v2/event-subscriptions/:
    post:
      tags:
        - Event Subscriptions
      summary: Create event subscription
      operationId: v2CreateEventSubscription
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateEventSubscriptionRequest'
      responses:
        '201':
          description: >-
            Event subscription created. The `signingSecret` is only ever
            returned here and from Rotate signing secret — store it now, it
            cannot be retrieved again.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventSubscription'
        '400':
          description: >-
            Invalid `url`, an unrecognized value in `eventTypes`, or a malformed
            request body
        '409':
          description: >-
            You've reached the maximum number of event subscriptions allowed per
            account (5). Delete an existing subscription before creating
            another.
        '422':
          description: URL rejected for delivery-safety reasons
      security:
        - apiKeyAuth: []
components:
  schemas:
    CreateEventSubscriptionRequest:
      type: object
      required:
        - url
        - eventTypes
      properties:
        url:
          type: string
          format: uri
          pattern: ^https://.*
          description: >-
            HTTPS URL Headout will deliver events to. Must be a valid absolute
            URL with no embedded credentials.
        eventTypes:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/EventSubscriptionType'
          description: >-
            One or more event types to subscribe to. Must be non-empty with no
            duplicates.
        authentication:
          $ref: '#/components/schemas/EventSubscriptionAuthenticationRequest'
        description:
          type: string
          maxLength: 500
          description: Optional free-text label to help you identify this subscription.
        active:
          type: boolean
          default: true
          description: >-
            Whether the subscription should start delivering events immediately.
            Defaults to `true`. Set `false` to create it paused and enable it
            later with Update event subscription.
    EventSubscription:
      type: object
      properties:
        id:
          type: string
          description: >-
            Identifier of this subscription, e.g. `whsub_01j...`. Use in
            Get/Update/Delete/Rotate secret.
        url:
          type: string
          description: HTTPS URL events are delivered to.
        eventTypes:
          type: array
          items:
            $ref: '#/components/schemas/EventSubscriptionType'
          description: Event types this subscription is subscribed to.
        description:
          type:
            - string
            - 'null'
          description: Free-text label for this subscription, if set.
        active:
          type: boolean
          description: Whether this subscription is currently active.
        createdAt:
          type: string
          format: date-time
          description: When this subscription was created.
        updatedAt:
          type: string
          format: date-time
          description: When this subscription was last updated.
        authentication:
          $ref: '#/components/schemas/EventSubscriptionAuthentication'
        signingSecret:
          type:
            - string
            - 'null'
          description: >-
            Signing secret for this subscription, used to verify the
            `X-Headout-Signature` header on delivered events. Only present in
            the response to Create event subscription and Rotate signing secret
            — never returned again afterwards, so store it immediately.
        signingSecretHint:
          type:
            - string
            - 'null'
          description: >-
            Masked trailing characters of the current signing secret, returned
            on reads so you can tell which secret is active without exposing it.
    EventSubscriptionType:
      type: string
      enum:
        - product.listing_status_changed
        - product.variant_listing_status_changed
        - product.data_changed
        - product.variant_pricing_changed
      description: >
        The event types available for subscription:

        - `product.listing_status_changed` — A product was listed or unlisted.

        - `product.variant_listing_status_changed` — One or more variants under
        a product were listed or unlisted. Fires when a product is listed (its
        variants arrive as listed) or delisted (all its variants are reported
        delisted), and also while a product stays listed but individual variants
        under it are listed or delisted.

        - `product.data_changed` — The content of a product that is listed (and
        was listed at the previous sync) changed. `data.changedFields` names
        which fields differ. Listing/unlisting and variant add/remove are
        reported by the two events above, not here.

        - `product.variant_pricing_changed` — The near-term pricing of a variant
        under a listed product changed for a specific date. `data` names the
        `productId`, `variantId`, and `date` whose price moved, not the new
        amounts — re-fetch the price to read them.
    EventSubscriptionAuthenticationRequest:
      type: object
      required:
        - type
      description: >
        Authentication Headout attaches to webhook deliveries for this
        subscription. Tri-state on update: omit this field entirely to keep the
        current authentication unchanged, send `{"type": "NONE"}` to clear it,
        or send `{"type": "AUTHORIZATION_HEADER", "value": "..."}` to set it.
      properties:
        type:
          type: string
          enum:
            - NONE
            - AUTHORIZATION_HEADER
          description: >-
            `NONE` sends no authentication header. `AUTHORIZATION_HEADER` sends
            `value` as the `Authorization` header on every delivery.
        value:
          type: string
          minLength: 6
          maxLength: 1024
          description: >-
            Required when `type` is `AUTHORIZATION_HEADER`. Sent verbatim as the
            `Authorization` header on every delivery attempt, including retries.
            Must be 6–1024 characters and free of control characters. Not echoed
            back in any response — only a masked `valueHint` is returned.
    EventSubscriptionAuthentication:
      type: object
      properties:
        type:
          type: string
          enum:
            - NONE
            - AUTHORIZATION_HEADER
          description: Authentication type configured for this subscription.
        valueHint:
          type:
            - string
            - 'null'
          description: >-
            Masked trailing characters of the configured `Authorization` header
            value. Only present when `type` is `AUTHORIZATION_HEADER`. The full
            value is never returned.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: Headout-Auth

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.