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

# Create a webhook subscription

> Subscribes a URL to one or more lifecycle events. Every delivery is a signed POST carrying `X-Trackplay-Event`, `X-Trackplay-Signature` (an HMAC-SHA256 of the payload using the subscription's secret), and `X-Trackplay-Timestamp`.

`secret` is never returned by the API, not even in the response to this call: the model hides it from every JSON response, always. If you omit it, one is generated for you, but there is then no way to retrieve it afterward, so you cannot verify a signature against it. Always send your own `secret` if you plan to verify delivery signatures.

Requires a token with the `webhooks:write` scope.



## OpenAPI

````yaml /api-reference/openapi.json post /webhooks
openapi: 3.1.0
info:
  title: TrackPlay API
  description: >-
    Send conversions and events to TrackPlay, and read them back. Authenticated
    with scoped tokens you mint in the dashboard.
  version: 1.0.0
servers:
  - url: https://app.trackplay.io/api/v1
    description: App API. Conversions, videos, webhooks.
  - url: https://e.trackplay.io
    description: Events API. High-volume event ingest.
security:
  - bearerAuth: []
tags:
  - name: Videos
    description: Create, read, update, and delete videos, and read workspace metadata.
  - name: Video settings
    description: Save a settings draft, publish it live, and read or restore past deploys.
  - name: Uploads
    description: >-
      Upload a source video file in one request or in resumable chunks, and poll
      its processing status.
  - name: Captions and chapters
    description: >-
      Manage caption tracks, chapter markers, AI-generated segments, and CTA
      cards on a video.
  - name: Playlists
    description: Group videos into a playlist or course, and manage the videos inside it.
  - name: Webhooks
    description: Subscribe a URL to TrackPlay lifecycle events and test deliveries.
  - name: Zapier
    description: >-
      The REST-hook endpoints Zapier calls to connect a workspace and manage
      triggers.
  - name: Analytics
    description: Read play, retention, event, and conversion analytics for a video.
  - name: Exports
    description: Queue and download bulk analytics exports.
  - name: Conversions
    description: Report a sale or a lead, from your own server or from a browser fallback.
  - name: Events
    description: Send a custom event tied to a viewer's session.
  - name: Identity
    description: Resolve a viewer's identity from the page, with no token required.
paths:
  /webhooks:
    post:
      tags:
        - Webhooks
      summary: Create a webhook subscription
      description: >-
        Subscribes a URL to one or more lifecycle events. Every delivery is a
        signed POST carrying `X-Trackplay-Event`, `X-Trackplay-Signature` (an
        HMAC-SHA256 of the payload using the subscription's secret), and
        `X-Trackplay-Timestamp`.


        `secret` is never returned by the API, not even in the response to this
        call: the model hides it from every JSON response, always. If you omit
        it, one is generated for you, but there is then no way to retrieve it
        afterward, so you cannot verify a signature against it. Always send your
        own `secret` if you plan to verify delivery signatures.


        Requires a token with the `webhooks:write` scope.
      operationId: createWebhook
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: >-
            Retry-safe key. The first response for a given key is cached for 24
            hours and replayed on a repeat, with `Idempotency-Replayed: true`
            set.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCreateRequest'
      responses:
        '201':
          description: >-
            The subscription. `secret` is not included, even if you sent one
            yourself: keep your own copy.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookEnvelope'
        '401':
          description: >-
            `AUTH_REQUIRED`: no token sent. `INVALID_TOKEN`: the token is
            invalid, expired, or revoked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '403':
          description: '`INSUFFICIENT_SCOPE`: the token does not carry `webhooks:write`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '422':
          description: >-
            Validation failed. Check every entry in `events` is a supported
            event name.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '429':
          description: Rate limited. 60 requests per minute per token.
components:
  schemas:
    WebhookCreateRequest:
      type: object
      required:
        - name
        - url
        - events
      properties:
        name:
          type: string
          maxLength: 128
        url:
          type: string
          format: uri
          maxLength: 2048
          description: Where deliveries are POSTed.
        events:
          type: array
          minItems: 1
          items:
            type: string
            enum:
              - video.created
              - video.uploaded
              - video.settings.deployed
              - video.deleted
              - video.viewed
              - conversion
              - conversion.created
              - play
              - play.milestone
              - cta.clicked
              - ended
              - lead.captured
              - lesson.completed
              - playlist.ended
              - lead_form.submitted
              - quiz.answered
              - split_test.winner_declared
          description: >-
            Which events this subscription fires on. Every entry must be one of
            the supported event names.
        secret:
          type: string
          minLength: 16
          maxLength: 128
          description: >-
            Used to HMAC-SHA256 sign deliveries in the `X-Trackplay-Signature`
            header. Generated for you if omitted, but a generated secret can
            never be read back, only rotated by deleting and recreating the
            subscription. Send your own if you need to know it ahead of time.
    WebhookEnvelope:
      type: object
      properties:
        webhook:
          $ref: '#/components/schemas/Webhook'
    ApiError:
      type: object
      description: The error shape the app API returns on a failed read or export.
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: >-
                A stable error code, e.g. `INSUFFICIENT_SCOPE`,
                `VIDEO_NOT_FOUND`, `EXPORT_NOT_FOUND`.
            message:
              type: string
              description: What went wrong, in plain English.
    ValidationError:
      type: object
      description: >-
        Laravel's default validation-failure body. `errors` maps each invalid
        field to its list of messages.
      properties:
        message:
          type: string
          examples:
            - The given data was invalid.
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
    Webhook:
      type: object
      description: >-
        A webhook subscription. `secret` is never included in any response,
        including the response to the call that created it: the value is
        write-only. If you did not set your own `secret` on creation, save the
        one you sent, because a server-generated secret cannot be read back
        later.
      properties:
        id:
          type: integer
        workspace_id:
          type: integer
        name:
          type: string
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            type: string
        is_active:
          type: boolean
        last_success_at:
          type:
            - string
            - 'null'
          format: date-time
        last_failure_at:
          type:
            - string
            - 'null'
          format: date-time
        failure_count:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        A scoped token minted in **Settings → API tokens**. Send it as
        `Authorization: Bearer tplt_…` or `X-API-Key: tplt_…`.

````

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