Paubox Subscriptions API

Subscriber opt-in and opt-out operations

Business capability
Marketing Management BC-400

Operations 10

GET /subscriptions List subscriptions #
POST /subscriptions Create a subscription #
GET /subscriptions/{subscription_id} Fetch a subscription #
DELETE /subscriptions/{subscription_id} Unsubscribe a subscription #
POST /subscriptions/subscribe Subscribe subscribers #
POST /subscriptions/unsubscribe Unsubscribe subscribers #
POST /subscriptions/bulk_global_subscribe Bulk global subscribe #
POST /subscriptions/bulk_global_unsubscribe Bulk global unsubscribe #
POST /subscriptions/dynamic_bulk_subscribe Bulk subscribe a dynamic list #
POST /subscriptions/dynamic_bulk_unsubscribe Bulk unsubscribe a dynamic list #

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/paubox-subscriptions-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 email required.

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

OpenAPI Specification

paubox-subscriptions-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Paubox Marketing Subscriptions API
  description: "Public documentation Paubox Marketing API. \n\nAll Paubox Marketing customers have access to the Paubox Marketing API to automate various tasks.\n\n## Authentication\nUse the authorization header in requests with the format: `authorization: Token token=<API_KEY>`\n\nReplace `<API_KEY>` with your API key. Find your API key in the address bar from the email builder (note: each API Key is displayed only once upon creation).\n\n## Base URL\n`https://api.paubox.com/v1/marketing`\n"
  contact:
    name: Paubox Support
    url: https://www.paubox.com
  version: 1.0.0
servers:
- url: https://api.paubox.com/v1/marketing
  description: Production server
security:
- TokenAuth: []
tags:
- name: subscriptions
  description: Subscriber opt-in and opt-out operations
paths:
  /subscriptions:
    get:
      tags:
      - subscriptions
      summary: List subscriptions
      description: 'Returns every subscription belonging to the authenticated customer. A subscription is the join between a subscriber and a subscription list (or a dynamic list), and it carries the `unsubscribed_at` timestamp that marks a list-level opt-out.


        This endpoint is not paginated and returns raw subscription records.

        '
      operationId: getSubscriptions
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionsResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
    post:
      tags:
      - subscriptions
      summary: Create a subscription
      description: "Subscribes an existing subscriber to an existing subscription list.\n\nCreating a subscription fires any drip campaign configured with a `subscription_created` trigger on that list.\n\nA subscriber may only be subscribed to a given list once; a duplicate request fails validation.\n\n**Note on `subscriber_id`:** this field takes the subscriber's internal numeric ID, not the UUID returned by the subscriber endpoints. To add a subscriber to a list by UUID, use [`POST /subscribers`](/marketing/subscribers/create) with a `subscription_list_id`, or [`POST /subscriptions/subscribe`](/marketing/subscriptions/subscribe) to re-subscribe an existing subscription.\n\n**Example curl command:**\n```bash\ncurl -X POST \\\nhttps://api.paubox.com/v1/marketing/subscriptions \\\n  -H 'authorization: Token token=YOUR_API_KEY' \\\n  -H 'content-type: application/json' \\\n  -d '{\n    \"subscription\": {\n        \"subscription_list_id\": \"123e4567-e89b-12d3-a456-426614174000\",\n        \"subscriber_id\": 4821\n    }\n  }'\n```\n"
      operationId: createSubscription
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSubscriptionRequest'
            example:
              subscription:
                subscription_list_id: 123e4567-e89b-12d3-a456-426614174000
                subscriber_id: 4821
        required: true
      responses:
        '200':
          description: Subscription created. If validation fails the response is still `200` but the body contains an `errors` array instead of `data`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateSubscriptionResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/{subscription_id}:
    get:
      tags:
      - subscriptions
      summary: Fetch a subscription
      description: Returns a single subscription by its UUID.
      operationId: getSubscription
      parameters:
      - name: subscription_id
        in: path
        description: UUID of the subscription
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
    delete:
      tags:
      - subscriptions
      summary: Unsubscribe a subscription
      description: 'Unsubscribes the subscriber from the list this subscription belongs to by stamping `unsubscribed_at`. The subscription record itself is kept, and the subscriber stays subscribed to every other list and is not globally opted out.


        To re-subscribe, use [`POST /subscriptions/subscribe`](/marketing/subscriptions/subscribe).

        '
      operationId: deleteSubscription
      parameters:
      - name: subscription_id
        in: path
        description: UUID of the subscription
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Subscription unsubscribed successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/subscribe:
    post:
      tags:
      - subscriptions
      summary: Subscribe subscribers
      description: "Re-subscribes one or more subscribers, identified by their UUIDs.\n\nWhen `subscription_list_ids` is supplied, the matching subscriptions have their `unsubscribed_at` cleared. When it is omitted, only the global opt-out (`opted_out_on`) is cleared and list-level opt-outs are left untouched.\n\nIn both cases the global opt-out is cleared, because a subscriber who is subscribed to any list is by definition not globally unsubscribed.\n\n**Example curl command:**\n```bash\ncurl -X POST \\\nhttps://api.paubox.com/v1/marketing/subscriptions/subscribe \\\n  -H 'authorization: Token token=YOUR_API_KEY' \\\n  -H 'content-type: application/json' \\\n  -d '{\n    \"subscriber_ids\": [\"8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60\"],\n    \"subscription_list_ids\": [\"123e4567-e89b-12d3-a456-426614174000\"]\n  }'\n```\n"
      operationId: subscribeSubscribers
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionChangeRequest'
            example:
              subscriber_ids:
              - 8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60
              subscription_list_ids:
              - 123e4567-e89b-12d3-a456-426614174000
        required: true
      responses:
        '200':
          description: The affected subscribers. If the operation raises, the response is still `200` but the body contains an `errors` string.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionChangeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/unsubscribe:
    post:
      tags:
      - subscriptions
      summary: Unsubscribe subscribers
      description: "Unsubscribes one or more subscribers, identified by their UUIDs.\n\nWhen `subscription_list_ids` is supplied, the matching subscriptions are stamped with `unsubscribed_at` and the subscribers remain subscribed to every other list. When it is omitted, the subscribers are globally opted out by stamping `opted_out_on`, which suppresses all future marketing email to them.\n\n**Example curl command:**\n```bash\ncurl -X POST \\\nhttps://api.paubox.com/v1/marketing/subscriptions/unsubscribe \\\n  -H 'authorization: Token token=YOUR_API_KEY' \\\n  -H 'content-type: application/json' \\\n  -d '{\n    \"subscriber_ids\": [\"8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60\"],\n    \"subscription_list_ids\": [\"123e4567-e89b-12d3-a456-426614174000\"]\n  }'\n```\n"
      operationId: unsubscribeSubscribers
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriptionChangeRequest'
            example:
              subscriber_ids:
              - 8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60
              subscription_list_ids:
              - 123e4567-e89b-12d3-a456-426614174000
        required: true
      responses:
        '200':
          description: The affected subscribers. If the operation raises, the response is still `200` but the body contains an `errors` string.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubscriptionChangeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/bulk_global_subscribe:
    post:
      tags:
      - subscriptions
      summary: Bulk global subscribe
      description: "Clears the global opt-out for a whole subscription list without having to enumerate every subscriber.\n\nThis endpoint has two modes:\n\n- **Explicit** — supply `subscriber_ids` and the request behaves exactly\n  like [`POST /subscriptions/subscribe`](/marketing/subscriptions/subscribe),\n  returning the affected subscribers synchronously.\n- **Select-all** — omit `subscriber_ids` and supply\n  `from_subscription_list_id`. Every subscriber matching `search` and\n  `filters` in that list, minus `except_ids`, is queued for processing in\n  the background and a Sidekiq job ID (`jid`) is returned immediately.\n\nIn select-all mode `from_subscription_list_id` is required and must be a subscription list UUID.\n"
      operationId: bulkGlobalSubscribe
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkSubscriptionChangeRequest'
            example:
              from_subscription_list_id: 123e4567-e89b-12d3-a456-426614174000
              search: '*'
              except_ids:
              - 8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60
        required: true
      responses:
        '200':
          description: A job ID in select-all mode, or the affected subscribers when `subscriber_ids` was supplied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkSubscriptionChangeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/bulk_global_unsubscribe:
    post:
      tags:
      - subscriptions
      summary: Bulk global unsubscribe
      description: "Globally opts out every subscriber in a subscription list without having to enumerate them.\n\nThis endpoint has two modes:\n\n- **Explicit** — supply `subscriber_ids` and the request behaves exactly\n  like [`POST /subscriptions/unsubscribe`](/marketing/subscriptions/unsubscribe),\n  returning the affected subscribers synchronously.\n- **Select-all** — omit `subscriber_ids` and supply\n  `from_subscription_list_id`. Every subscriber matching `search` and\n  `filters` in that list, minus `except_ids`, is queued for processing in\n  the background and a Sidekiq job ID (`jid`) is returned immediately.\n\nIn select-all mode `from_subscription_list_id` is required and must be a subscription list UUID. Globally opting a subscriber out suppresses all future marketing email to them, across every list.\n"
      operationId: bulkGlobalUnsubscribe
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkSubscriptionChangeRequest'
            example:
              from_subscription_list_id: 123e4567-e89b-12d3-a456-426614174000
              search: '*'
              except_ids:
              - 8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60
        required: true
      responses:
        '200':
          description: A job ID in select-all mode, or the affected subscribers when `subscriber_ids` was supplied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkSubscriptionChangeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/dynamic_bulk_subscribe:
    post:
      tags:
      - subscriptions
      summary: Bulk subscribe a dynamic list
      description: "The dynamic list counterpart to [bulk global subscribe](/marketing/subscriptions/bulk-global-subscribe).\n\n- **Explicit** — supply `subscriber_ids` and the request behaves exactly\n  like [`POST /subscriptions/subscribe`](/marketing/subscriptions/subscribe).\n- **Select-all** — omit `subscriber_ids` and supply\n  `from_subscription_list_id`, which here is a **dynamic list** UUID. The\n  job resolves the list's current membership, subtracts `except_ids`, and\n  clears the global opt-out on the rest. A Sidekiq job ID (`jid`) is\n  returned immediately.\n\nA dynamic list's membership is defined by the filters saved on the list itself, so any `filters` sent with the request is ignored in select-all mode.\n"
      operationId: dynamicBulkSubscribe
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkSubscriptionChangeRequest'
            example:
              from_subscription_list_id: 7c9e6679-7425-40de-944b-e07fc1f90ae7
              except_ids:
              - 8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60
        required: true
      responses:
        '200':
          description: A job ID in select-all mode, or the affected subscribers when `subscriber_ids` was supplied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkSubscriptionChangeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /subscriptions/dynamic_bulk_unsubscribe:
    post:
      tags:
      - subscriptions
      summary: Bulk unsubscribe a dynamic list
      description: "The dynamic list counterpart to [bulk global unsubscribe](/marketing/subscriptions/bulk-global-unsubscribe).\n\n- **Explicit** — supply `subscriber_ids` and the request behaves exactly\n  like [`POST /subscriptions/unsubscribe`](/marketing/subscriptions/unsubscribe).\n- **Select-all** — omit `subscriber_ids` and supply\n  `from_subscription_list_id`, which here is a **dynamic list** UUID. The\n  job resolves the list's current membership, subtracts `except_ids`, and\n  globally opts out the rest. A Sidekiq job ID (`jid`) is returned\n  immediately.\n\nA dynamic list's membership is defined by the filters saved on the list itself, so any `filters` sent with the request is ignored in select-all mode.\n"
      operationId: dynamicBulkUnsubscribe
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkSubscriptionChangeRequest'
            example:
              from_subscription_list_id: 7c9e6679-7425-40de-944b-e07fc1f90ae7
              except_ids:
              - 8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60
        required: true
      responses:
        '200':
          description: A job ID in select-all mode, or the affected subscribers when `subscriber_ids` was supplied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkSubscriptionChangeResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  responses:
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    DetailedSubscriber_attributes:
      type: object
      properties:
        email:
          type: string
          description: Subscriber's email address
          format: email
        first_name:
          type: string
          description: Subscriber's first name
        last_name:
          type: string
          description: Subscriber's last name
        unsubscribed:
          type: boolean
          description: Whether the subscriber is unsubscribed
        created_at:
          type: string
          description: Timestamp when subscriber was created
          format: date-time
        updated_at:
          type: string
          description: Timestamp when subscriber was last updated
          format: date-time
        custom_fields:
          type: array
          items:
            $ref: '#/components/schemas/DetailedSubscriber_attributes_custom_fields'
        subscription_lists:
          type: array
          items:
            $ref: '#/components/schemas/DetailedSubscriber_attributes_subscription_lists'
        statistics:
          $ref: '#/components/schemas/DetailedSubscriber_attributes_statistics'
    DetailedSubscriber:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the subscriber
        type:
          type: string
          description: Resource type
        attributes:
          $ref: '#/components/schemas/DetailedSubscriber_attributes'
    SubscriptionsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Subscription'
    BulkSubscriptionChangeResponse:
      type: object
      properties:
        data:
          oneOf:
          - $ref: '#/components/schemas/BulkSubscriptionJob'
          - type: array
            description: The affected subscribers, returned when `subscriber_ids` was supplied.
            items:
              $ref: '#/components/schemas/DetailedSubscriber'
        errors:
          type: string
          description: Error message, present only when the operation failed
    SubscriptionChangeRequest:
      required:
      - subscriber_ids
      type: object
      properties:
        subscriber_ids:
          type: array
          description: UUIDs of the subscribers to update
          items:
            type: string
        subscription_list_ids:
          type: array
          description: UUIDs of the subscription lists to update the subscribers on. Omit to act on the subscribers' global opt-out instead.
          items:
            type: string
    SubscriptionResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Subscription'
    Subscription:
      type: object
      properties:
        id:
          type: integer
          description: Internal numeric identifier for the subscription
        uuid:
          type: string
          description: Public identifier for the subscription. Use this value as `subscription_id` in path parameters.
        subscription_list_id:
          type:
          - string
          - 'null'
          description: UUID of the subscription list. Null when the subscription belongs to a dynamic list.
        dynamic_list_id:
          type:
          - integer
          - 'null'
          description: Identifier of the dynamic list. Null when the subscription belongs to a subscription list.
        subscriber_id:
          type: integer
          description: Internal numeric identifier of the subscriber
        unsubscribed_at:
          type:
          - string
          - 'null'
          format: date-time
          description: When the subscriber opted out of this list. Null while the subscription is active.
        delete_at:
          type:
          - string
          - 'null'
          format: date-time
          description: When the subscription is scheduled for deletion
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    CreateSubscriptionRequest:
      type: object
      properties:
        subscription:
          $ref: '#/components/schemas/CreateSubscriptionRequest_subscription'
    CreateSubscriptionResponse:
      type: object
      description: Returned with HTTP 200 in both the success and the validation-failure case. Check for the presence of `errors`.
      properties:
        data:
          $ref: '#/components/schemas/Subscription'
        errors:
          type: array
          description: Validation messages, present only when the create failed
          items:
            type: string
    SubscriptionChangeResponse:
      type: object
      description: The affected subscribers in JSON:API form. Returned with HTTP 200; on failure the body carries `errors` instead of `data`.
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/DetailedSubscriber'
        errors:
          type: string
          description: Error message, present only when the operation failed
    BulkSubscriptionChangeRequest:
      type: object
      properties:
        subscriber_ids:
          type: array
          description: UUIDs of specific subscribers to update. When present the request is handled synchronously and every other field is ignored.
          items:
            type: string
        from_subscription_list_id:
          type: string
          description: UUID of the list whose members are being updated. Required when `subscriber_ids` is omitted. On the `bulk_global_*` endpoints this is a subscription list UUID; on the `dynamic_bulk_*` endpoints it is a dynamic list UUID.
        search:
          type: string
          description: Search term used to narrow the list's members. Defaults to `*` (all members) on the `bulk_global_*` endpoints.
        filters:
          type: string
          description: 'URL-encoded JSON describing additional subscriber filters, as generated by the subscriber search in the Marketing dashboard. The decoded value is an array of filter groups, each group an array of `{"field": ..., "op": ..., "terms": [...]}` objects. Ignored by the `dynamic_bulk_*` endpoints, which use the filters saved on the dynamic list.'
        except_ids:
          type: array
          description: UUIDs of subscribers to exclude from the operation. Use this to express "select all except these".
          items:
            type: string
    BulkSubscriptionJob:
      type: object
      properties:
        jid:
          type: string
          description: Identifier of the background job processing the change. The change is applied asynchronously.
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
        code:
          type: string
          description: Error code
        details:
          type: object
          description: Additional error details
    DetailedSubscriber_attributes_custom_fields:
      type: object
      properties:
        subscriber_custom_field_type_id:
          type: string
          description: ID of the custom field type
        custom_field_name:
          type: string
          description: Name of the custom field
        custom_field_value:
          type: string
          description: Value of the custom field
    DetailedSubscriber_attributes_subscription_lists:
      type: object
      properties:
        id:
          type: string
          description: Subscription list ID
        name:
          type: string
          description: Subscription list name
        unsubscribed:
          type: boolean
          description: Whether subscriber is unsubscribed from this list
    CreateSubscriptionRequest_subscription:
      required:
      - subscriber_id
      - subscription_list_id
      type: object
      properties:
        subscription_list_id:
          type: string
          description: UUID of the subscription list to subscribe to
        subscriber_id:
          type: integer
          description: Internal numeric identifier of the subscriber. This is not the subscriber UUID returned by the subscriber endpoints.
    DetailedSubscriber_attributes_statistics:
      type: object
      properties:
        deliveries:
          type: integer
          description: Number of deliveries
        delivered:
          type: integer
          description: Number of delivered emails
        opened:
          type: integer
          description: Number of opened emails
        clicked:
          type: integer
          description: Number of clicked emails
        soft_bounced:
          type: integer
          description: Number of soft bounces
        hard_bounced:
          type: integer
          description: Number of hard bounces
        unsubscribed:
          type: integer
          description: Number of unsubscribes
        global_unsubscribed:
          type: integer
          description: Number of global unsubscribes
  securitySchemes:
    TokenAuth:
      type: apiKey
      description: 'Token-based authentication. Use format: "Token token=<API_KEY>" where <API_KEY> is your API key'
      name: authorization
      in: header