Ethora Push API

The Push API from Ethora — 9 operation(s) for push.

GitHub OpenAPI

Operations 15

POST /v1/push/firebase-service-account/{appId} Upload Firebase service account for app push #
DELETE /v1/push/firebase-service-account/{appId} Delete the Firebase service account for app push #
POST /v1/push/apns/{appId} Upload the APNs auth key (.p8) for app push #
DELETE /v1/push/apns/{appId} Delete the APNs auth key for app push #
POST /v1/push/subscription/{appId} Register a device push token for the current user #
DELETE /v1/push/subscription/{appId} Remove a device push token for the current user #
PUT /v1/push/platform/{appId} Enable/disable platform-key push delivery for an app #
GET /v1/push/platform/{appId} Platform push status for an app #
PUT /v1/push/content-mode/{appId} Set what the chat pushes of an app say (full or generic) #
GET /v1/push/content-mode/{appId} Content mode of an app's chat pushes #
PUT /v1/push/sender-avatar/{appId} Switch the sender's avatar in an app's chat pushes on or off #
GET /v1/push/sender-avatar/{appId} Whether an app's chat pushes carry the sender's avatar #
POST /v1/push/project/{appId} Send a broadcast push for an app (project) #
POST /v1/push/validate/{appId} Validate push configuration for an app (dry-run) #
POST /v1/push/user/{appId} Send a push to a single user (jid) #

Specifications

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/ethora-com:ethora-com-push-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

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

ethora-com-push-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Platform Push API
  description: 'Ethora Platform API.


    ## Getting Started

    - For new backend and tenant integrations, start with the `/v2/...` endpoints.

    - Use `/v2/apps/{appId}/...` when your backend/admin flow manages a specific target app explicitly.

    - Some legacy operations still exist only under `/v1/...`; when so, the operation description will say so.


    ## Integration Tracks

    - `Frontend / app runtime`: app-auth login/sign-up flows, then user-auth chats/files/sharelinks.

    - `Tenant admin / B2B backend`: explicit app management and app-scoped admin flows under `/v2/apps/{appId}/...`.


    ## Auth Token Legend

    - `App JWT`: app-scoped runtime token for sign-up/login/runtime app operations.

    - `User JWT`: end-user or admin-user session token.

    - `Refresh JWT`: refresh-only token for access token renewal.

    - `Client JWT`: legacy client-side token used only for chat/client credential exchange compatibility flows.

    - `B2B Server JWT`: tenant/backend integration token. Prefer `Authorization: Bearer `; `x-custom-token` is still accepted for backward compatibility.


    ## Which Token Where

    - `App JWT`: `/v1/users/login-with-email`, `/v2/users/sign-up-with-email`, similar app-runtime auth endpoints.

    - `User JWT`: user session endpoints like chats, files, sharelinks, profile/session management.

    - `B2B Server JWT`: tenant/backend integration endpoints, especially explicit `/v2/apps/{appId}/...` admin flows.

    - `Client JWT`: only where the endpoint explicitly says `Client JWT` and typically only for legacy compatibility.


    ## Auth Approach

    - `/v2/...` endpoints are the canonical API surface for new integrations.

    - Endpoints may support one or more token types depending on the actor and scope.

    - App-scoped admin/integration endpoints use `/v2/apps/{appId}/...` so the target app is always explicit.

    - When an endpoint supports both `User JWT` and `B2B Server JWT`, Swagger will show both under Security.

    - Public Swagger excludes internal-only, operational, and experimental surfaces.'
  contact:
    name: Dappros developers team
  version: 26.11.05
servers:
- url: https://api.chat.ethora.com
security:
- JwtAuth: []
tags:
- name: Push
paths:
  /v1/push/firebase-service-account/{appId}:
    post:
      summary: Upload Firebase service account for app push
      description: Uploads a Firebase service account JSON for the specified app. The backend proxies it to the configured push service.
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - firebaseServiceAccount
              properties:
                firebaseServiceAccount:
                  type: string
                  format: binary
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: forbidden
        '404':
          description: app not found
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: post_v1_push_firebase_service_account_appid
    delete:
      summary: Delete the Firebase service account for app push
      description: 'Removes the app''s Firebase service account from the push service and

        clears the `firebaseServiceAccountUploaded` flag on the app. Idempotent:

        succeeds even if no service account was uploaded. Device subscriptions

        are left intact.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: forbidden
        '404':
          description: app not found
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: delete_v1_push_firebase_service_account_appid
  /v1/push/apns/{appId}:
    post:
      summary: Upload the APNs auth key (.p8) for app push
      description: 'Uploads an APNs auth key for direct APNs delivery (e.g. VoIP/PushKit

        pushes, which FCM cannot deliver). The backend proxies it to the push

        service, which stores it server-side — the key is never exposed back.

        Sets `apnsKeyUploaded: true` on the app. `bundleId` defaults to the

        app''s `bundleId` when omitted.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
              - apnsKey
              - keyId
              - teamId
              - environment
              properties:
                apnsKey:
                  type: string
                  format: binary
                  description: The APNs auth key file (.p8, PEM private key)
                keyId:
                  type: string
                  description: Apple Key ID of the .p8 key (10 characters)
                teamId:
                  type: string
                  description: Apple Developer Team ID (10 characters)
                bundleId:
                  type: string
                  description: 'Target app bundle id (the apns-topic). May be omitted only

                    when the app record has `bundleId` set - the resolved value

                    is required, otherwise 422 BUNDLE_ID_REQUIRED.

                    '
                environment:
                  type: string
                  enum:
                  - production
                  - sandbox
                  description: APNs environment the key will be used against
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: forbidden
        '404':
          description: app not found
        '422':
          description: validation failed (missing/invalid keyId, teamId, environment, bundleId, or .p8 file)
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: post_v1_push_apns_appid
    delete:
      summary: Delete the APNs auth key for app push
      description: 'Removes the app''s APNs auth key from the push service and clears the

        `apnsKeyUploaded` flag on the app. Idempotent: succeeds even if no key

        was uploaded.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: forbidden
        '404':
          description: app not found
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: delete_v1_push_apns_appid
  /v1/push/subscription/{appId}:
    post:
      summary: Register a device push token for the current user
      description: 'Creates or updates a push subscription for the current authenticated user (jid = req.user.xmppUsername).

        Proxies to the configured push service.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - registrationToken
              - deviceType
              properties:
                registrationToken:
                  type: string
                  description: FCM registration token, or a raw APNs/PushKit device token when tokenType is apns/apns-voip
                tokenType:
                  type: string
                  enum:
                  - fcm
                  - apns
                  - apns-voip
                  description: '''fcm'' (default) - Firebase registration token, delivered via FCM.

                    ''apns'' - raw APNs device token, delivered via direct APNs

                    (requires the app''s APNs auth key to be uploaded).

                    ''apns-voip'' - PushKit VoIP token; registered alongside the

                    device''s regular ''apns'' subscription and used ONLY for

                    incoming-call pushes (apns-push-type voip, topic

                    bundleId.voip). Regular messages never go to it.

                    '
                buildOrigin:
                  type: string
                  enum:
                  - tenant
                  - platform
                  description: 'Which build family issued the token — delivery keys must

                    match the BUILD that produced it, not the tenant.

                    ''tenant'' (default) - the tenant''s own white-label build;

                    delivered with the keys uploaded for this app.

                    ''platform'' - the universal store app; delivered with the

                    platform''s keys regardless of tenant.

                    '
                deviceType:
                  type: string
                  enum:
                  - android
                  - ios
                  - web
                language:
                  type: string
                  description: 'Language of the pushes to this device (BCP-47, e.g. en, fr,

                    es; the region part is ignored). The fixed texts (generic

                    mode, "New message", attachment words, reaction texts) and

                    the pick of a translated message text follow it; without

                    it the user''s profile language is used, then English.

                    Available: en, fr, es. Absent keeps the stored value, ""

                    clears it.

                    '
                pushKey:
                  type: string
                  description: 'Encrypted pushes: base64 of the device''s raw 32-byte X25519

                    public key. Chat pushes to this token then arrive data-only

                    with their content in a libsodium sealed box for this key

                    (see the push service README, "Encrypted pushes"). An empty

                    string removes a stored key; omitting the field keeps it.

                    '
                pushKeyAlg:
                  type: string
                  enum:
                  - sealed-box-x25519
                  description: Construction the key is for (default sealed-box-x25519).
                pushKeyId:
                  type: string
                  description: 'Key id returned in every sealed push as `kid`. Default: the

                    first 16 hex characters of SHA-256 over the raw key.

                    '
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: post_v1_push_subscription_appid
    delete:
      summary: Remove a device push token for the current user
      description: 'Deletes a push subscription for the current authenticated user (jid = req.user.xmppUsername).

        Proxies to the configured push service.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - registrationToken
              properties:
                registrationToken:
                  type: string
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: delete_v1_push_subscription_appid
  /v1/push/platform/{appId}:
    put:
      summary: Enable/disable platform-key push delivery for an app
      description: 'Push keys uploaded to the base app serve every app of the install, with

        no limits and no settings: an app without keys of its own sends with

        the base app''s keys, an app that uploads its own keys sends with those,

        and parent/child relations between apps play no role. This switch only

        turns platform-key delivery off for one app (enabled: false) or back

        on; it can also be set when the app is created (`platformPushEnabled`

        on POST /v1/apps and /v2/apps). Accepts a user token with

        appSettings.update permission on the target app, or a server (B2B)

        token of that app or of its parent app.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - enabled
              properties:
                enabled:
                  type: boolean
      responses:
        '200':
          description: ok ({ ok, enabled })
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: put_v1_push_platform_appid
    get:
      summary: Platform push status for an app
      description: Returns { enabled, platformProjectId } for the app's platform-key delivery (platformProjectId is the app whose keys serve it, normally the base app).
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        schema:
          type: string
        required: true
      responses:
        '200':
          description: ok ({ enabled, platformProjectId })
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: get_v1_push_platform_appid
  /v1/push/content-mode/{appId}:
    put:
      summary: Set what the chat pushes of an app say (full or generic)
      description: '`full` (the default) is the usual chat push: the sender as the title,

        the text or the attachment type as the body, the sender''s avatar or

        the attachment preview as the picture. `generic` sends a fixed

        "New message" / "You have a new message" with ids only in the data

        payload (room JID, message id, receiver JID): no text, no names, no

        pictures and no mutable-content, so nothing about the message passes

        through Google or Apple; on Android the notification is sent with

        visibility public. One notification per room and high priority apply

        to both modes. Applies to chat messages only: call pushes and the

        text pushes of /v1/push/user and /v1/push/project keep their text.

        An app without a value of its own takes the mode of the nearest

        parent app that has one, so one call on the base app covers its

        child apps; `inherit` removes the app''s own value.

        Accepts a user token with appSettings.update permission on the

        target app, or a server (B2B) token of that app or of its parent app.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - mode
              properties:
                mode:
                  type: string
                  enum:
                  - full
                  - generic
                  - inherit
      responses:
        '200':
          description: ok ({ ok, mode })
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: put_v1_push_content_mode_appid
    get:
      summary: Content mode of an app's chat pushes
      description: Returns { mode, own, inheritedFrom }, the mode in effect ("full" or "generic"), the app's own value or null, and the app the mode is inherited from or null.
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        schema:
          type: string
        required: true
      responses:
        '200':
          description: ok ({ mode, own, inheritedFrom })
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: get_v1_push_content_mode_appid
  /v1/push/sender-avatar/{appId}:
    put:
      summary: Switch the sender's avatar in an app's chat pushes on or off
      description: 'On (the default), a chat push carries the sender''s avatar (the

        `photo` of the message, else the sender''s profile image). The app

        shows it the way messengers do: the avatar next to the text with

        the app icon as a small badge (iOS communication notification,

        Android MessagingStyle), where the app draws the notification

        itself. Off leaves the avatar out of every chat push of the app,

        plain and encrypted; attachment previews stay. The `generic`

        content mode sends no avatar either way. Accepts a user token with

        appSettings.update permission on the target app, or a server (B2B)

        token of that app or of its parent app.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - enabled
              properties:
                enabled:
                  type: boolean
      responses:
        '200':
          description: ok ({ ok, enabled })
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: put_v1_push_sender_avatar_appid
    get:
      summary: Whether an app's chat pushes carry the sender's avatar
      description: Returns { enabled }, true unless switched off.
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        schema:
          type: string
        required: true
      responses:
        '200':
          description: ok ({ enabled })
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: get_v1_push_sender_avatar_appid
  /v1/push/project/{appId}:
    post:
      summary: Send a broadcast push for an app (project)
      description: Proxies a broadcast push request to the configured push service.
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - text
              properties:
                text:
                  type: string
                title:
                  type: string
                ttl:
                  type: integer
                  minimum: 0
                jid:
                  type: string
                  description: Optional JID to target a specific segment/user group (push service dependent)
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: post_v1_push_project_appid
  /v1/push/validate/{appId}:
    post:
      summary: Validate push configuration for an app (dry-run)
      description: 'Calls the push service to perform a **dry-run** Firebase send to a topic.

        This validates that the Firebase service account for the app is configured and usable,

        without requiring a mobile app/device token.'
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                topic:
                  type: string
                  description: Optional FCM topic to use for dry-run validation.
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: app/project not found
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
        '502':
          description: FCM validation failed (bad service account / permissions)
      operationId: post_v1_push_validate_appid
  /v1/push/user/{appId}:
    post:
      summary: Send a push to a single user (jid)
      description: Proxies a single-user push request to the configured push service.
      tags:
      - Push
      parameters:
      - in: path
        name: appId
        description: 'Target App ID. Must be an app the calling actor owns or has been

          delegated access to.

          '
        schema:
          type: string
        required: true
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - jid
              - text
              properties:
                jid:
                  type: string
                text:
                  type: string
                title:
                  type: string
                ttl:
                  type: integer
                  minimum: 0
      responses:
        '200':
          description: ok
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          description: validation error
        '500':
          $ref: '#/components/responses/InternalServerError'
      operationId: post_v1_push_user_appid
components:
  responses:
    NotFound:
      description: Not Found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnprocessableEntity:
      description: Unprocessable Entity
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalServerError:
      description: Internal Server Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: Forbidden
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Unauthorized
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    BadRequest:
      description: Bad Request
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          description: Always false for error responses.
          example: false
        error:
          type: string
          description: A brief, human-readable message about the error.
        code:
          type: string
          description: A stable machine-readable error code.
          example: VALIDATION_ERROR
        details:
          type: object
          description: Optional, more specific details about the error (e.g., validation errors).
        errors:
          description: Legacy validation errors (if applicable).
        requestId:
          type: string
          description: Request correlation id for debugging/support.
      required:
      - error
      example:
        success: false
        error: Validation Failed
        code: VALIDATION_ERROR
        details:
          field: Reason
        requestId: '...'
  securitySchemes:
    JwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Authorization: Bearer <JWT>'
    AppJwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'App JWT (data.type="app"). Use this token to call app-authorized endpoints (e.g. create user, login, signup). Authorization: Bearer <JWT>. Wrong token type returns code=INVALID_TOKEN_TYPE.'
    UserJwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'User JWT (data.type="user"). Use this token for user-authorized endpoints (e.g. chats/files/sharelinks/me). Authorization: Bearer <JWT>. Wrong token type returns code=INVALID_TOKEN_TYPE.'
    RefreshJwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Refresh JWT (data.type="refresh"). Use this token only for refresh flow. Authorization: Bearer <JWT>. Wrong token type returns code=INVALID_TOKEN_TYPE.'
    ClientJwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Client JWT (data.type="client"). Legacy compatibility token used only for client credential exchange endpoints. Preferred header: x-custom-token; Authorization Bearer may also be accepted by some deployments.'
    B2BServerJwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'B2B Server JWT (data.type="server"). Use this token for tenant/backend integration endpoints. Preferred header: Authorization: Bearer <JWT>. Legacy header x-custom-token is also accepted for backward compatibility.'