postzen-dev Webhooks API

Manage outbound webhook endpoints and retained delivery logs. PostZen sends an at-least-once JSON envelope `{ id, type, apiVersion, createdAt, data }` using `POST`; automatic retries and manual redeliveries keep the same event id and raw body. Requests include `X-PostZen-Event`, `X-PostZen-Event-Id`, `X-PostZen-Delivery-Id`, and `X-PostZen-Timestamp`. When a signing secret is configured, `X-PostZen-Signature` is `v1=` where the digest is HMAC-SHA256 over `.`. Production receivers should configure signing, compare signatures in constant time, reject timestamps older than five minutes, and deduplicate by event id.

Operations 8

GET /v1/webhooks List webhooks #
POST /v1/webhooks Create a webhook #
GET /v1/webhooks/{webhookId} Get a webhook #
PUT /v1/webhooks/{webhookId} Update a webhook #
DELETE /v1/webhooks/{webhookId} Delete a webhook #
POST /v1/webhooks/{webhookId}/test Test a webhook #
GET /v1/webhook-deliveries List webhook deliveries #
POST /v1/webhook-deliveries/{deliveryId}/redeliver Redeliver a webhook event #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/postzen-dev:postzen-dev-webhooks-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

postzen-dev-webhooks-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: PostZen Public Webhooks API
  version: 1.0.0
  description: The PostZen Public API lets server-side integrations manage profiles, connected social accounts, OAuth connection flows, media uploads, post creation, and outbound webhooks.
servers:
- url: https://api.postzen.dev
  description: Production API
security:
- bearerAuth: []
tags:
- name: Webhooks
  description: Manage outbound webhook endpoints and retained delivery logs. PostZen sends an at-least-once JSON envelope `{ id, type, apiVersion, createdAt, data }` using `POST`; automatic retries and manual redeliveries keep the same event id and raw body. Requests include `X-PostZen-Event`, `X-PostZen-Event-Id`, `X-PostZen-Delivery-Id`, and `X-PostZen-Timestamp`. When a signing secret is configured, `X-PostZen-Signature` is `v1=` where the digest is HMAC-SHA256 over `.`. Production receivers should configure signing, compare signatures in constant time, reject timestamps older than five minutes, and deduplicate by event id.
paths:
  /v1/webhooks:
    get:
      tags:
      - Webhooks
      operationId: listWebhooks
      summary: List webhooks
      description: Returns webhook endpoints visible to the API key, newest first. Secret and custom header values are never returned.
      responses:
        '200':
          description: Webhooks returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhooksListResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalError'
    post:
      tags:
      - Webhooks
      operationId: createWebhook
      summary: Create a webhook
      description: Creates an outbound webhook endpoint. A user may have up to 25 endpoints. This endpoint requires a read-write API key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCreateRequest'
            example:
              name: Production events
              url: https://example.com/webhooks/postzen
              events:
              - post.published
              - post.failed
              profileAccess: all_profiles
              secret: customer-provided-secret
      responses:
        '201':
          description: Webhook created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookWriteResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: The endpoint limit has been reached.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/webhooks/{webhookId}:
    parameters:
    - name: webhookId
      in: path
      required: true
      description: PostZen webhook endpoint id.
      schema:
        type: string
    get:
      tags:
      - Webhooks
      operationId: getWebhook
      summary: Get a webhook
      description: Returns one webhook endpoint visible to the API key without secret or custom header values.
      responses:
        '200':
          description: Webhook returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
    put:
      tags:
      - Webhooks
      operationId: updateWebhook
      summary: Update a webhook
      description: Updates one or more endpoint settings. Omitted fields are unchanged. This endpoint requires a read-write API key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookUpdateRequest'
            example:
              events:
              - post.published
              - post.partially_failed
              - post.failed
              customHeaders: []
      responses:
        '200':
          description: Webhook updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookWriteResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
    delete:
      tags:
      - Webhooks
      operationId: deleteWebhook
      summary: Delete a webhook
      description: Deletes an endpoint and stops new event fan-out. Retained delivery logs remain available until their retention period ends.
      responses:
        '200':
          description: Webhook deleted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/webhooks/{webhookId}/test:
    parameters:
    - name: webhookId
      in: path
      required: true
      description: PostZen webhook endpoint id.
      schema:
        type: string
    post:
      tags:
      - Webhooks
      operationId: testWebhook
      summary: Test a webhook
      description: Queues a `webhook.test` event through the normal delivery pipeline using the endpoint's current URL, secret, and custom headers. The endpoint must be active.
      responses:
        '202':
          description: Test delivery queued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookTestResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: The webhook endpoint is inactive.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/webhook-deliveries:
    get:
      tags:
      - Webhooks
      operationId: listWebhookDeliveries
      summary: List webhook deliveries
      description: Returns retained delivery logs visible to the API key, newest first. Results are capped to the 1000 most recent matching deliveries.
      parameters:
      - name: webhookId
        in: query
        description: Filter by webhook endpoint id.
        schema:
          type: string
      - name: event
        in: query
        description: Filter by webhook event type.
        schema:
          $ref: '#/components/schemas/WebhookEvent'
      - name: status
        in: query
        description: Filter by delivery status.
        schema:
          $ref: '#/components/schemas/WebhookDeliveryStatus'
      - name: dateFrom
        in: query
        description: Only include deliveries created at or after this ISO 8601 timestamp.
        schema:
          type: string
          format: date-time
      - name: dateTo
        in: query
        description: Only include deliveries created at or before this ISO 8601 timestamp. Must be later than `dateFrom`.
        schema:
          type: string
          format: date-time
      - name: page
        in: query
        description: 1-based page number.
        schema:
          type: integer
          minimum: 1
          default: 1
      - name: limit
        in: query
        description: Page size.
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      responses:
        '200':
          description: Webhook deliveries returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookDeliveriesListResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/webhook-deliveries/{deliveryId}/redeliver:
    parameters:
    - name: deliveryId
      in: path
      required: true
      description: PostZen webhook delivery id.
      schema:
        type: string
    post:
      tags:
      - Webhooks
      operationId: redeliverWebhookDelivery
      summary: Redeliver a webhook event
      description: Queues a new six-attempt delivery run on the retained delivery record while preserving its event id and attempt history. The endpoint must still exist and be active, and the delivery must not already be in progress.
      responses:
        '202':
          description: Webhook redelivery queued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookRedeliveryResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: The endpoint is unavailable, the delivery is expired, or a delivery is already in progress.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    WebhooksListResponse:
      type: object
      required:
      - webhooks
      properties:
        webhooks:
          type: array
          items:
            $ref: '#/components/schemas/Webhook'
    Pagination:
      type: object
      required:
      - page
      - limit
      - total
      - totalPages
      properties:
        page:
          type: integer
          minimum: 1
        limit:
          type: integer
          minimum: 1
          maximum: 100
        total:
          type: integer
          minimum: 0
        totalPages:
          type: integer
          minimum: 0
    WebhookRedeliveryResponse:
      type: object
      required:
      - message
      - delivery
      properties:
        message:
          type: string
        delivery:
          $ref: '#/components/schemas/WebhookDelivery'
    WebhookUpdateRequest:
      type: object
      description: Include at least one field. Omitted fields keep their stored values.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 80
        url:
          type: string
          format: uri
        events:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/WebhookEvent'
        profileAccess:
          type: string
          enum:
          - all_profiles
          - selected_profiles
        profileIds:
          type: array
          items:
            type: string
          description: Replacement profile selection. Must be non-empty for selected_profiles and empty for all_profiles.
        secret:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 256
          writeOnly: true
          description: Omit to keep the stored secret, send a non-empty string to replace it, or send null to remove it.
        customHeaders:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/WebhookCustomHeader'
          description: Omit to keep stored headers. Send the complete collection to replace all headers, or [] to remove all headers. Every supplied value is plaintext and is encrypted at rest.
        isActive:
          type: boolean
          description: Enable or disable delivery. Re-enabling resets the consecutive exhausted-event count.
    MessageResponse:
      type: object
      required:
      - message
      properties:
        message:
          type: string
    WebhookWriteResponse:
      type: object
      required:
      - message
      - webhook
      properties:
        message:
          type: string
        webhook:
          $ref: '#/components/schemas/Webhook'
    WebhookDelivery:
      type: object
      required:
      - event
      - eventId
      - deliveryId
      - resourceId
      - status
      - attemptCount
      - createdAt
      properties:
        event:
          $ref: '#/components/schemas/WebhookEvent'
        eventId:
          type: string
          description: Stable across automatic retries and manual redeliveries.
        deliveryId:
          type: string
        resourceId:
          type: string
        status:
          $ref: '#/components/schemas/WebhookDeliveryStatus'
        attemptCount:
          type: integer
          minimum: 0
          description: Monotonic count across automatic retries and manual redeliveries.
        lastHttpStatus:
          type: integer
          minimum: 100
          maximum: 599
        lastErrorCode:
          type: string
        lastDurationMs:
          type: number
          minimum: 0
        createdAt:
          type: string
          format: date-time
        lastAttemptAt:
          type: string
          format: date-time
        deliveredAt:
          type: string
          format: date-time
        nextAttemptAt:
          type: string
          format: date-time
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: string
        type:
          type: string
        code:
          type: string
        param:
          type:
          - string
          - 'null'
    WebhookTestResponse:
      type: object
      required:
      - message
      - eventId
      - deliveryId
      properties:
        message:
          type: string
        eventId:
          type: string
        deliveryId:
          type: string
    RateLimitError:
      type: object
      required:
      - error
      - retryAfter
      properties:
        error:
          type: string
          const: rate_limited
        retryAfter:
          type: integer
          minimum: 1
          description: Number of seconds to wait before retrying.
    WebhookCustomHeader:
      type: object
      required:
      - name
      - value
      properties:
        name:
          type: string
          description: HTTP header name. Content-Type, transport headers, and X-PostZen-* names are reserved.
        value:
          type: string
          maxLength: 4096
          writeOnly: true
          description: Plaintext header value. PostZen encrypts it at rest and never returns it.
    WebhookDeliveryStatus:
      type: string
      enum:
      - pending
      - retrying
      - delivered
      - failed
    WebhookDeliveriesListResponse:
      type: object
      required:
      - deliveries
      - pagination
      properties:
        deliveries:
          type: array
          items:
            $ref: '#/components/schemas/WebhookDelivery'
        pagination:
          $ref: '#/components/schemas/Pagination'
    WebhookEvent:
      type: string
      enum:
      - post.scheduled
      - post.published
      - post.partially_failed
      - post.failed
      - post.cancelled
      - post.platform.published
      - post.platform.failed
      - post.external.created
      - account.connected
      - account.needs_reauth
      - account.disconnected
      - analytics.synced
      - conversation.started
      - message.received
      - message.sent
      - comment.received
      - contact.tag_added
      - contact.tag_removed
      - contact.field_changed
      - webhook.test
      description: Webhook event type. See the Webhook Events section for each event's trigger and payload. Receivers should tolerate additional event types in future API versions.
    Webhook:
      type: object
      required:
      - id
      - name
      - url
      - events
      - profileAccess
      - profileIds
      - hasSigningSecret
      - customHeaderNames
      - isActive
      - consecutiveFailures
      - createdAt
      - updatedAt
      properties:
        id:
          type: string
        name:
          type: string
          minLength: 1
          maxLength: 80
        url:
          type: string
          format: uri
        events:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/WebhookEvent'
        profileAccess:
          type: string
          enum:
          - all_profiles
          - selected_profiles
        profileIds:
          type: array
          items:
            type: string
          description: Selected profile ids. Empty when profileAccess is all_profiles.
        hasSigningSecret:
          type: boolean
          description: Whether PostZen signs deliveries for this endpoint. The secret itself is never returned.
        customHeaderNames:
          type: array
          items:
            type: string
          description: Configured custom header names. Header values are never returned.
        isActive:
          type: boolean
        disabledReason:
          type: string
          enum:
          - auto_consecutive_failures
          - user_disabled
        consecutiveFailures:
          type: integer
          minimum: 0
        lastDeliveredAt:
          type: string
          format: date-time
        lastFailedAt:
          type: string
          format: date-time
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    WebhookResponse:
      type: object
      required:
      - webhook
      properties:
        webhook:
          $ref: '#/components/schemas/Webhook'
    WebhookCreateRequest:
      type: object
      required:
      - name
      - url
      - events
      - profileAccess
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 80
        url:
          type: string
          format: uri
          description: Public HTTPS endpoint URL.
        events:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/WebhookEvent'
        profileAccess:
          type: string
          enum:
          - all_profiles
          - selected_profiles
          description: all_profiles receives events for every profile. selected_profiles requires profileIds.
        profileIds:
          type: array
          items:
            type: string
          description: Required for selected_profiles and omitted or empty for all_profiles.
        secret:
          type:
          - string
          - 'null'
          minLength: 1
          maxLength: 256
          writeOnly: true
          description: Optional HMAC signing secret. Omit or send null to create an unsigned endpoint.
        customHeaders:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/WebhookCustomHeader'
        isActive:
          type: boolean
          default: true
  responses:
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Failed to create post
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Unauthorized
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Not found
    TooManyRequests:
      description: Rate limit exceeded. Retry after the interval indicated by the `Retry-After` header.
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitError'
          example:
            error: rate_limited
            retryAfter: 30
    Forbidden:
      description: The API key does not have sufficient permission or profile access.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: API key requires read_write permission
    BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: JSON body is required
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: PostZen API key.