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

> ## Agent Instructions
> BuzzKit is an open source notification orchestration layer. Send mobile push from a backend with one POST to /v1/messages, targeting a subscriber id, a topic, a saved segment or an inline expression. Subscribers are addressed by the caller's own user ids. Authenticate with a bearer API key from the dashboard; workspace keys pick a tenant with the BuzzKit-Tenant header. Every response is the envelope { success, data, error, metadata } and errors carry a stable snake_case code. iOS is the supported client SDK. The machine-readable API description is at https://buzzkit.dev/openapi.json.

# Upsert a subscriber



## OpenAPI

````yaml /openapi.json put /v1/subscribers/{externalId}
openapi: 3.0.3
info:
  title: BuzzKit API
  version: 1.0.0
  description: >-
    The BuzzKit REST API: subscribers, subscriptions, topics, events, segments,
    messages, workflows, sources and webhooks, all under /v1. Every response is
    a JSON envelope { success, data, error, metadata }; errors carry a lowercase
    snake_case code, a message and, when a field is at fault, its param.
  contact:
    name: BuzzKit
    url: https://buzzkit.dev
    email: hello@buzzkit.dev
  license:
    name: AGPL-3.0
    url: https://github.com/buzzkit-dev/buzzkit/blob/main/LICENSE
servers:
  - url: https://api.buzzkit.dev
    description: BuzzKit Cloud
  - url: http://localhost:8790
    description: Local development
security:
  - bearerAuth: []
externalDocs:
  description: BuzzKit documentation
  url: https://docs.buzzkit.dev
paths:
  /v1/subscribers/{externalId}:
    put:
      tags:
        - Subscribers
      summary: Upsert a subscriber
      operationId: upsertSubscriber
      parameters:
        - name: externalId
          in: path
          required: true
          schema:
            minLength: 1
            maxLength: 256
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                attributes:
                  type: object
                  additionalProperties:
                    type: object
                    additionalProperties: true
                email:
                  format: email
                  maxLength: 254
                  type: string
                timezone:
                  minLength: 1
                  maxLength: 64
                  type: string
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                attributes:
                  type: object
                  additionalProperties:
                    type: object
                    additionalProperties: true
                email:
                  format: email
                  maxLength: 254
                  type: string
                timezone:
                  minLength: 1
                  maxLength: 64
                  type: string
          multipart/form-data:
            schema:
              type: object
              properties:
                attributes:
                  type: object
                  additionalProperties:
                    type: object
                    additionalProperties: true
                email:
                  format: email
                  maxLength: 254
                  type: string
                timezone:
                  minLength: 1
                  maxLength: 64
                  type: string
      responses:
        '200':
          description: Response for status 200
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                  - error
                  - metadata
                properties:
                  success:
                    type: boolean
                  data:
                    nullable: true
                    type: object
                    additionalProperties: true
                  error:
                    nullable: true
                    type: object
                    required:
                      - code
                      - message
                    properties:
                      code:
                        type: string
                      message:
                        type: string
                      param:
                        type: string
                      details:
                        type: object
                        additionalProperties: true
                  metadata:
                    type: object
                    required:
                      - timestamp
                    properties:
                      timestamp:
                        type: string
                      requestId:
                        type: string
        '400':
          description: >-
            The request is malformed or fails validation; `error.code` is
            `validation`, `bad_request` or `parse` and `error.details` lists
            every failing field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: >-
            No credential, or an invalid, expired or revoked one:
            `missing_authorization`, `invalid_api_key`, `api_key_expired`,
            `invalid_session`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            The credential cannot do this: `missing_permission` for a missing
            scope, `forbidden` for another workspace, tenant or key kind.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            The addressed resource does not exist for this credential, including
            malformed ids.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: 'The write conflicts with existing state: `conflict`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - bearerAuth:
            - subscribers:write
components:
  schemas:
    Error:
      type: object
      description: >-
        The envelope every error uses. `error.code` is a stable lowercase
        snake_case code, `error.param` names the offending field when there is
        one, and `metadata.requestId` is what to quote in support requests.
      required:
        - success
        - data
        - error
        - metadata
      properties:
        success:
          type: boolean
          enum:
            - false
        data:
          type: object
          nullable: true
          description: Always null on an error.
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              example: invalid_api_key
            message:
              type: string
            param:
              type: string
              nullable: true
            details:
              type: array
              nullable: true
              description: 'Present on validation errors: one entry per failing field.'
              items:
                type: object
                properties:
                  param:
                    type: string
                  message:
                    type: string
        metadata:
          type: object
          required:
            - timestamp
          properties:
            timestamp:
              type: string
              format: date-time
            requestId:
              type: string
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An API key from the dashboard. The scopes listed on each operation are
        the `resource:action` grants a key needs (`messages:send`,
        `subscribers:read`, `topics:*`, `*`); `account:*` scopes and key
        management are session-only. Workspace keys (bk_ws_) reach every tenant
        and pick one with the buzzkit-tenant header; tenant keys (bk_tn_) are
        locked to one tenant; client keys (bk_pk_) ship inside an app and only
        work on /v1/client/*.

````