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 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

paubox-subscriptions-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Paubox Marketing Subscriptions API
  description: 'Public documentation Paubox Marketing API.


    All Paubox Marketing customers have access to the Paubox Marketing API to automate various tasks.


    ## Authentication

    Use the authorization header in requests with the format: `authorization: Token token=`


    Replace `` 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).


    ## Base URL

    `https://api.paubox.com/v1/marketing`'
  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.


        Creating a subscription fires any drip campaign configured with a `subscription_created` trigger on that list.


        A subscriber may only be subscribed to a given list once; a duplicate request fails validation.


        **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` with a `subscription_list_id`, or `POST /subscriptions/subscribe` to re-subscribe an existing subscription.


        **Example curl command:**

        ```bash

        curl -X POST \

        https://api.paubox.com/v1/marketing/subscriptions \

        -H ''authorization: Token token=YOUR_API_KEY'' \

        -H ''content-type: application/json'' \

        -d ''{

        "subscription": {

        "subscription_list_id": "123e4567-e89b-12d3-a456-426614174000",

        "subscriber_id": 4821

        }

        }''

        ```'
      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`.'
      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.


        When `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.


        In both cases the global opt-out is cleared, because a subscriber who is subscribed to any list is by definition not globally unsubscribed.


        **Example curl command:**

        ```bash

        curl -X POST \

        https://api.paubox.com/v1/marketing/subscriptions/subscribe \

        -H ''authorization: Token token=YOUR_API_KEY'' \

        -H ''content-type: application/json'' \

        -d ''{

        "subscriber_ids": ["8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60"],

        "subscription_list_ids": ["123e4567-e89b-12d3-a456-426614174000"]

        }''

        ```'
      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.


        When `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.


        **Example curl command:**

        ```bash

        curl -X POST \

        https://api.paubox.com/v1/marketing/subscriptions/unsubscribe \

        -H ''authorization: Token token=YOUR_API_KEY'' \

        -H ''content-type: application/json'' \

        -d ''{

        "subscriber_ids": ["8f14e45f-ceea-467a-9f2c-4b3d2a1e5c60"],

        "subscription_list_ids": ["123e4567-e89b-12d3-a456-426614174000"]

        }''

        ```'
      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.


        This endpoint has two modes:


        - **Explicit** — supply `subscriber_ids` and the request behaves exactly

        like `POST /subscriptions/subscribe`,

        returning the affected subscribers synchronously.

        - **Select-all** — omit `subscriber_ids` and supply

        `from_subscription_list_id`. Every subscriber matching `search` and

        `filters` in that list, minus `except_ids`, is queued for processing in

        the background and a Sidekiq job ID (`jid`) is returned immediately.


        In select-all mode `from_subscription_list_id` is required and must be a subscription list UUID.'
      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.


        This endpoint has two modes:


        - **Explicit** — supply `subscriber_ids` and the request behaves exactly

        like `POST /subscriptions/unsubscribe`,

        returning the affected subscribers synchronously.

        - **Select-all** — omit `subscriber_ids` and supply

        `from_subscription_list_id`. Every subscriber matching `search` and

        `filters` in that list, minus `except_ids`, is queued for processing in

        the background and a Sidekiq job ID (`jid`) is returned immediately.


        In 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.'
      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.


        - **Explicit** — supply `subscriber_ids` and the request behaves exactly

        like `POST /subscriptions/subscribe`.

        - **Select-all** — omit `subscriber_ids` and supply

        `from_subscription_list_id`, which here is a **dynamic list** UUID. The

        job resolves the list''s current membership, subtracts `except_ids`, and

        clears the global opt-out on the rest. A Sidekiq job ID (`jid`) is

        returned immediately.


        A 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.'
      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.


        - **Explicit** — supply `subscriber_ids` and the request behaves exactly

        like `POST /subscriptions/unsubscribe`.

        - **Select-all** — omit `subscriber_ids` and supply

        `from_subscription_list_id`, which here is a **dynamic list** UUID. The

        job resolves the list''s current membership, subtracts `except_ids`, and

        globally opts out the rest. A Sidekiq job ID (`jid`) is returned

        immediately.


        A 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.'
      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:
  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'
    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
    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
    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
    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
    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
    SubscriptionResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Subscription'
    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
    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
    CreateSubscriptionRequest:
      type: object
      properties:
        subscription:
          $ref: '#/components/schemas/CreateSubscriptionRequest_subscription'
    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
    SubscriptionsResponse:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Subscription'
    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:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the subscriber
        type:
          type: string
          description: Resource type
        attributes:
          $ref: '#/components/schemas/DetailedSubscriber_attributes'
    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
    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
  responses:
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  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