Signal Server

Signal-Server is the open-source server backend that supports the Signal Private Messenger applications on Android, Desktop, and iOS. Built as a Dropwizard application, it provides REST controllers for account management, message delivery, key distribution, and device provisioning, along with gRPC services and WebSocket endpoints for real-time communication. The server handles user registration, encrypted message routing, push notification delivery, and pre-key bundle management.

OpenAPI Specification

signal-server-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Signal Server API
  description: >-
    The Signal Server API is the backend REST API that supports the Signal
    Private Messenger applications on Android, Desktop, and iOS. Built as a
    Dropwizard application, it provides REST controllers for account
    registration and management, message delivery, pre-key bundle distribution,
    device provisioning, profile management, and attachment handling. The server
    handles user registration via phone number verification, encrypted message
    routing, push notification delivery, and pre-key bundle management. While
    Signal does not offer an official public REST API for third-party use, the
    server source code is available for inspection and self-hosting. All
    communication is end-to-end encrypted using the Signal Protocol.
  version: '2.0'
  contact:
    name: Signal Support
    url: https://support.signal.org/
  termsOfService: https://signal.org/legal/
  license:
    name: AGPL-3.0
    url: https://github.com/signalapp/Signal-Server/blob/main/LICENSE
externalDocs:
  description: Signal Server Source Code
  url: https://github.com/signalapp/Signal-Server
servers:
  - url: https://chat.signal.org
    description: Signal Production Server
tags:
  - name: Accounts
    description: >-
      Account management endpoints for configuring account settings,
      managing capabilities, and account lifecycle operations.
  - name: Attachments
    description: >-
      Attachment handling endpoints for uploading and downloading media
      files associated with messages.
  - name: Certificates
    description: >-
      Certificate endpoints for retrieving delivery certificates used in
      sealed sender message delivery.
  - name: Devices
    description: >-
      Device management endpoints for linking, unlinking, and managing
      devices associated with a Signal account.
  - name: Keys
    description: >-
      Pre-key bundle management endpoints for uploading and retrieving
      public key material used in the Signal Protocol key exchange.
  - name: Messages
    description: >-
      Message sending and receiving endpoints for delivering encrypted
      messages between Signal users.
  - name: Profiles
    description: >-
      Profile management endpoints for setting and retrieving user profile
      information including names, avatars, and capabilities.
  - name: Registration
    description: >-
      Account registration endpoints for creating new Signal accounts via
      phone number verification.
  - name: Stickers
    description: >-
      Sticker pack management endpoints for uploading and retrieving
      sticker packs.
security:
  - basicAuth: []
paths:
  /v1/registration:
    post:
      operationId: registerAccount
      summary: Register a new account
      description: >-
        Registers a new Signal account with a phone number. Initiates the
        verification process by sending an SMS or voice call with a
        verification code to the provided phone number.
      tags:
        - Registration
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegistrationRequest'
      responses:
        '200':
          description: Registration initiated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegistrationResponse'
        '400':
          description: Invalid request parameters
        '409':
          description: Account already exists or number is rate-limited
        '429':
          description: Rate limit exceeded
  /v1/accounts/whoami:
    get:
      operationId: getAccountIdentity
      summary: Get current account identity
      description: >-
        Returns the account identity information for the currently
        authenticated user, including the account UUID and phone number.
      tags:
        - Accounts
      responses:
        '200':
          description: Account identity returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AccountIdentity'
        '401':
          description: Authentication required
  /v1/accounts/attributes:
    put:
      operationId: setAccountAttributes
      summary: Set account attributes
      description: >-
        Updates the account attributes for the authenticated user, including
        registration ID, voice and video capabilities, fetches messages
        setting, and other account-level configuration.
      tags:
        - Accounts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AccountAttributes'
      responses:
        '204':
          description: Account attributes updated successfully
        '401':
          description: Authentication required
  /v1/accounts/username_hash/{usernameHash}:
    put:
      operationId: confirmUsernameHash
      summary: Confirm a username hash
      description: >-
        Confirms and sets a username hash for the authenticated account. The
        username hash is a privacy-preserving representation of the username.
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/usernameHash'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UsernameHashConfirmation'
      responses:
        '200':
          description: Username hash confirmed successfully
        '409':
          description: Username hash already taken
        '410':
          description: Username hash reservation expired
    get:
      operationId: lookupUsernameHash
      summary: Look up account by username hash
      description: >-
        Looks up an account by its username hash and returns the account
        UUID if found.
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/usernameHash'
      responses:
        '200':
          description: Account found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsernameHashLookupResponse'
        '404':
          description: No account found for username hash
  /v1/accounts/number:
    put:
      operationId: changeNumber
      summary: Change account phone number
      description: >-
        Changes the phone number associated with the authenticated account.
        Requires re-verification of the new phone number.
      tags:
        - Accounts
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ChangeNumberRequest'
      responses:
        '200':
          description: Phone number changed successfully
        '401':
          description: Authentication required
        '409':
          description: Number already in use
  /v1/devices:
    get:
      operationId: listDevices
      summary: List linked devices
      description: >-
        Returns a list of all devices currently linked to the authenticated
        account, including device IDs, names, and last seen timestamps.
      tags:
        - Devices
      responses:
        '200':
          description: Device list returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceList'
        '401':
          description: Authentication required
  /v1/devices/link:
    put:
      operationId: linkDevice
      summary: Link a new device
      description: >-
        Links a new device to the authenticated account. The new device must
        have already been provisioned with a device code obtained through
        the provisioning process.
      tags:
        - Devices
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LinkDeviceRequest'
      responses:
        '200':
          description: Device linked successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeviceResponse'
        '403':
          description: Maximum number of linked devices reached
        '422':
          description: Invalid device verification code
  /v1/devices/{deviceId}:
    delete:
      operationId: removeDevice
      summary: Remove a linked device
      description: >-
        Removes a linked device from the authenticated account. This
        unlinks the device and invalidates its credentials.
      tags:
        - Devices
      parameters:
        - $ref: '#/components/parameters/deviceId'
      responses:
        '204':
          description: Device removed successfully
        '401':
          description: Authentication required
        '404':
          description: Device not found
  /v1/messages/{destinationUuid}:
    put:
      operationId: sendMessage
      summary: Send an encrypted message
      description: >-
        Sends one or more encrypted messages to the specified destination
        account identified by UUID. Messages are encrypted using the Signal
        Protocol and include envelope metadata for delivery. The server
        routes messages to the recipient's devices.
      tags:
        - Messages
      parameters:
        - $ref: '#/components/parameters/destinationUuid'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IncomingMessageList'
      responses:
        '200':
          description: Messages accepted for delivery
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendMessageResponse'
        '401':
          description: Authentication required
        '404':
          description: Destination account not found
        '409':
          description: Mismatched devices
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MismatchedDevices'
        '410':
          description: Stale devices
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StaleDevices'
  /v2/keys:
    get:
      operationId: getPreKeyCount
      summary: Get pre-key counts
      description: >-
        Returns the number of pre-keys currently stored on the server for
        the authenticated device. Clients use this to determine whether
        they need to upload additional pre-keys.
      tags:
        - Keys
      responses:
        '200':
          description: Pre-key count returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PreKeyCount'
        '401':
          description: Authentication required
    put:
      operationId: setKeys
      summary: Upload pre-keys
      description: >-
        Uploads a batch of pre-keys, a signed pre-key, and optionally a
        last-resort Kyber pre-key for the authenticated device. These keys
        are used by other clients to establish Signal Protocol sessions.
      tags:
        - Keys
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetKeysRequest'
      responses:
        '204':
          description: Keys uploaded successfully
        '401':
          description: Authentication required
  /v2/keys/{identifier}/{deviceId}:
    get:
      operationId: getDeviceKeys
      summary: Get pre-key bundle for a device
      description: >-
        Retrieves a pre-key bundle for a specific device belonging to the
        identified account. The bundle includes a pre-key, signed pre-key,
        and identity key needed to establish a Signal Protocol session.
      tags:
        - Keys
      parameters:
        - name: identifier
          in: path
          required: true
          description: >-
            The UUID or phone number identifying the target account.
          schema:
            type: string
        - $ref: '#/components/parameters/deviceId'
      responses:
        '200':
          description: Pre-key bundle returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PreKeyBundle'
        '404':
          description: Account or device not found
  /v1/profile/{identifier}:
    get:
      operationId: getProfile
      summary: Get a user profile
      description: >-
        Retrieves the profile for the specified account, including the
        encrypted profile name, avatar URL, identity key, and capabilities.
        Profile data is encrypted with the profile key shared between
        contacts.
      tags:
        - Profiles
      parameters:
        - name: identifier
          in: path
          required: true
          description: >-
            The UUID identifying the target account.
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Profile returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Profile'
        '401':
          description: Authentication required
        '404':
          description: Profile not found
  /v1/profile:
    put:
      operationId: setProfile
      summary: Set user profile
      description: >-
        Updates the profile for the authenticated account. Profile data
        including name, about text, emoji, and payment address are
        encrypted with the account's profile key before transmission.
      tags:
        - Profiles
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetProfileRequest'
      responses:
        '200':
          description: Profile updated successfully
        '401':
          description: Authentication required
  /v4/attachments/form/upload:
    get:
      operationId: getAttachmentUploadForm
      summary: Get attachment upload form
      description: >-
        Returns a pre-signed upload form that clients use to upload
        attachment data directly to the storage service. The form includes
        the upload URL, headers, and the attachment identifier.
      tags:
        - Attachments
      responses:
        '200':
          description: Upload form returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AttachmentUploadForm'
        '401':
          description: Authentication required
  /v1/sticker/pack/form/{packSize}:
    get:
      operationId: getStickerPackUploadForm
      summary: Get sticker pack upload form
      description: >-
        Returns a pre-signed upload form for uploading a sticker pack with
        the specified number of stickers.
      tags:
        - Stickers
      parameters:
        - name: packSize
          in: path
          required: true
          description: >-
            The number of stickers in the pack.
          schema:
            type: integer
            minimum: 1
            maximum: 200
      responses:
        '200':
          description: Upload form returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StickerPackUploadForm'
        '401':
          description: Authentication required
  /v1/certificate/delivery:
    get:
      operationId: getDeliveryCertificate
      summary: Get a sealed sender delivery certificate
      description: >-
        Returns a delivery certificate for the authenticated account. This
        certificate is used in sealed sender message delivery, which hides
        the sender's identity from the server during message transmission.
      tags:
        - Certificates
      parameters:
        - name: includeE164
          in: query
          required: false
          description: >-
            Whether to include the E164 phone number in the certificate.
          schema:
            type: boolean
            default: true
      responses:
        '200':
          description: Delivery certificate returned successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeliveryCertificate'
        '401':
          description: Authentication required
components:
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >-
        HTTP Basic authentication using the account UUID (or phone number)
        and password. The password is established during account
        registration.
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Bearer token authentication used for certain provisioning and
        registration flows.
  parameters:
    deviceId:
      name: deviceId
      in: path
      required: true
      description: >-
        The numeric device identifier. Device 1 is always the primary
        device.
      schema:
        type: integer
        format: int64
    destinationUuid:
      name: destinationUuid
      in: path
      required: true
      description: >-
        The UUID of the destination account.
      schema:
        type: string
        format: uuid
    usernameHash:
      name: usernameHash
      in: path
      required: true
      description: >-
        The Base64url-encoded SHA-256 hash of the username.
      schema:
        type: string
  schemas:
    RegistrationRequest:
      type: object
      required:
        - sessionId
        - accountAttributes
      properties:
        sessionId:
          type: string
          description: >-
            The verification session identifier obtained from the
            registration service.
        accountAttributes:
          $ref: '#/components/schemas/AccountAttributes'
        skipDeviceTransfer:
          type: boolean
          description: >-
            Whether to skip the device transfer flow for existing accounts.
    RegistrationResponse:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: >-
            The UUID assigned to the newly registered account.
        number:
          type: string
          description: >-
            The E164-formatted phone number associated with the account.
        pni:
          type: string
          format: uuid
          description: >-
            The Phone Number Identity UUID for the account.
        storageCapable:
          type: boolean
          description: >-
            Whether the account supports secure storage service.
    AccountIdentity:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: >-
            The ACI (Account Identity) UUID.
        number:
          type: string
          description: >-
            The E164-formatted phone number.
        pni:
          type: string
          format: uuid
          description: >-
            The Phone Number Identity UUID.
        usernameHash:
          type: string
          description: >-
            The Base64url-encoded username hash if set.
    AccountAttributes:
      type: object
      properties:
        fetchesMessages:
          type: boolean
          description: >-
            Whether the device fetches messages via WebSocket rather than
            receiving push notifications.
        registrationId:
          type: integer
          description: >-
            The Signal Protocol registration ID for this device.
        pniRegistrationId:
          type: integer
          description: >-
            The PNI registration ID for this device.
        name:
          type: string
          description: >-
            The encrypted device name, Base64-encoded.
        capabilities:
          type: object
          description: >-
            Account capability flags indicating supported features.
          properties:
            storage:
              type: boolean
              description: >-
                Whether the account supports secure value recovery and
                storage service.
            transfer:
              type: boolean
              description: >-
                Whether the device supports account transfer.
            paymentActivation:
              type: boolean
              description: >-
                Whether the account supports payment activation.
        unidentifiedAccessKey:
          type: string
          description: >-
            The Base64-encoded unidentified access key for sealed sender.
        unrestrictedUnidentifiedAccess:
          type: boolean
          description: >-
            Whether any sender can use sealed sender without the access key.
    UsernameHashConfirmation:
      type: object
      required:
        - usernameHash
        - zkProof
      properties:
        usernameHash:
          type: string
          description: >-
            The Base64url-encoded username hash to confirm.
        zkProof:
          type: string
          description: >-
            The zero-knowledge proof that the username hash is valid.
    UsernameHashLookupResponse:
      type: object
      properties:
        uuid:
          type: string
          format: uuid
          description: >-
            The UUID of the account associated with the username hash.
    ChangeNumberRequest:
      type: object
      required:
        - number
        - registrationLock
      properties:
        number:
          type: string
          description: >-
            The new E164-formatted phone number.
        registrationLock:
          type: string
          description: >-
            The registration lock token for verification.
        pniIdentityKey:
          type: string
          description: >-
            The new PNI identity key, Base64-encoded.
    DeviceList:
      type: object
      properties:
        devices:
          type: array
          description: >-
            List of devices linked to the account.
          items:
            $ref: '#/components/schemas/Device'
    Device:
      type: object
      properties:
        id:
          type: integer
          format: int64
          description: >-
            The numeric device identifier. Primary device is always 1.
        name:
          type: string
          description: >-
            The encrypted device name, Base64-encoded.
        lastSeen:
          type: integer
          format: int64
          description: >-
            Unix timestamp in milliseconds of when the device last
            connected.
        created:
          type: integer
          format: int64
          description: >-
            Unix timestamp in milliseconds of when the device was linked.
    LinkDeviceRequest:
      type: object
      required:
        - verificationCode
        - accountAttributes
      properties:
        verificationCode:
          type: string
          description: >-
            The device verification code obtained during provisioning.
        accountAttributes:
          $ref: '#/components/schemas/AccountAttributes'
        aciSignedPreKey:
          $ref: '#/components/schemas/SignedPreKey'
        pniSignedPreKey:
          $ref: '#/components/schemas/SignedPreKey'
        aciPqLastResortPreKey:
          $ref: '#/components/schemas/KyberPreKey'
        pniPqLastResortPreKey:
          $ref: '#/components/schemas/KyberPreKey'
    DeviceResponse:
      type: object
      properties:
        deviceId:
          type: integer
          format: int64
          description: >-
            The numeric device identifier assigned to the newly linked
            device.
    IncomingMessageList:
      type: object
      required:
        - messages
        - timestamp
      properties:
        messages:
          type: array
          description: >-
            The list of encrypted message envelopes, one per destination
            device.
          items:
            $ref: '#/components/schemas/IncomingMessage'
        timestamp:
          type: integer
          format: int64
          description: >-
            The client timestamp in milliseconds.
        online:
          type: boolean
          description: >-
            Whether to only deliver to online devices (skip push
            notifications for offline devices).
        urgent:
          type: boolean
          description: >-
            Whether the message is urgent and should trigger immediate push
            notification delivery.
    IncomingMessage:
      type: object
      required:
        - type
        - destinationDeviceId
        - content
      properties:
        type:
          type: integer
          description: >-
            The message envelope type. 1 for ciphertext, 3 for prekey
            message, 6 for plaintext content, 7 for unidentified sender.
          enum:
            - 1
            - 3
            - 6
            - 7
        destinationDeviceId:
          type: integer
          format: int64
          description: >-
            The target device identifier on the destination account.
        destinationRegistrationId:
          type: integer
          description: >-
            The expected registration ID of the target device.
        content:
          type: string
          description: >-
            The Base64-encoded encrypted message content.
    SendMessageResponse:
      type: object
      properties:
        needsSync:
          type: boolean
          description: >-
            Whether the sender has other devices that need to be synced
            with this message.
    MismatchedDevices:
      type: object
      properties:
        missingDevices:
          type: array
          description: >-
            Device IDs that messages were not provided for.
          items:
            type: integer
            format: int64
        extraDevices:
          type: array
          description: >-
            Device IDs that messages were provided for but do not exist.
          items:
            type: integer
            format: int64
    StaleDevices:
      type: object
      properties:
        staleDevices:
          type: array
          description: >-
            Device IDs with stale registration IDs.
          items:
            type: integer
            format: int64
    PreKeyCount:
      type: object
      properties:
        count:
          type: integer
          description: >-
            The number of one-time pre-keys remaining on the server.
        pqCount:
          type: integer
          description: >-
            The number of post-quantum (Kyber) one-time pre-keys remaining.
    SetKeysRequest:
      type: object
      properties:
        preKeys:
          type: array
          description: >-
            A list of one-time EC pre-keys to upload.
          items:
            $ref: '#/components/schemas/PreKey'
        signedPreKey:
          $ref: '#/components/schemas/SignedPreKey'
        pqPreKeys:
          type: array
          description: >-
            A list of one-time post-quantum (Kyber) pre-keys to upload.
          items:
            $ref: '#/components/schemas/KyberPreKey'
        pqLastResortPreKey:
          $ref: '#/components/schemas/KyberPreKey'
    PreKey:
      type: object
      required:
        - keyId
        - publicKey
      properties:
        keyId:
          type: integer
          format: int64
          description: >-
            The pre-key identifier.
        publicKey:
          type: string
          description: >-
            The Base64-encoded public key.
    SignedPreKey:
      type: object
      required:
        - keyId
        - publicKey
        - signature
      properties:
        keyId:
          type: integer
          format: int64
          description: >-
            The signed pre-key identifier.
        publicKey:
          type: string
          description: >-
            The Base64-encoded public key.
        signature:
          type: string
          description: >-
            The Base64-encoded signature over the public key.
    KyberPreKey:
      type: object
      required:
        - keyId
        - publicKey
        - signature
      properties:
        keyId:
          type: integer
          format: int64
          description: >-
            The Kyber pre-key identifier.
        publicKey:
          type: string
          description: >-
            The Base64-encoded Kyber public key.
        signature:
          type: string
          description: >-
            The Base64-encoded signature over the Kyber public key.
    PreKeyBundle:
      type: object
      properties:
        identityKey:
          type: string
          description: >-
            The Base64-encoded identity public key for the account.
        devices:
          type: array
          description: >-
            Pre-key bundles for each of the account's devices.
          items:
            $ref: '#/components/schemas/DevicePreKeyBundle'
    DevicePreKeyBundle:
      type: object
      properties:
        deviceId:
          type: integer
          format: int64
          description: >-
            The device identifier.
        registrationId:
          type: integer
          description: >-
            The device's registration ID.
        signedPreKey:
          $ref: '#/components/schemas/SignedPreKey'
        preKey:
          $ref: '#/components/schemas/PreKey'
        pqPreKey:
          $ref: '#/components/schemas/KyberPreKey'
    Profile:
      type: object
      properties:
        identityKey:
          type: string
          description: >-
            The Base64-encoded identity public key.
        name:
          type: string
          description: >-
            The encrypted profile name, Base64-encoded.
        about:
          type: string
          description: >-
            The encrypted about text, Base64-encoded.
        aboutEmoji:
          type: string
          description: >-
            The encrypted about emoji, Base64-encoded.
        avatar:
          type: string
          description: >-
            The path to the profile avatar on the CDN.
        unidentifiedAccess:
          type: string
          description: >-
            The Base64-encoded unidentified access key verifier.
        unrestrictedUnidentifiedAccess:
          type: boolean
          description: >-
            Whether unrestricted unidentified access is enabled.
        capabilities:
          type: object
          description: >-
            Account capability flags.
        credential:
          type: string
          description: >-
            The Base64-encoded ExpiringProfileKeyCredentialResponse.
        uuid:
          type: string
          format: uuid
          description: >-
            The account UUID.
        paymentAddress:
          type: string
          description: >-
            The encrypted MobileCoin payment address, Base64-encoded.
    SetProfileRequest:
      type: object
      properties:
        name:
          type: string
          description: >-
            The encrypted profile name, Base64-encoded.
        about:
          type: string
          description: >-
            The encrypted about text, Base64-encoded.
        aboutEmoji:
          type: string
          description: >-
            The encrypted about emoji, Base64-encoded.
        paymentAddress:
          type: string
          description: >-
            The encrypted payment address, Base64-encoded.
        avatar:
          type: boolean
          description: >-
            Whether the profile has an avatar to upload.
        commitment:
          type: string
          description: >-
            The Base64-encoded profile key commitment.
        version:
          type: string
          description: >-
            The profile key version string.
    AttachmentUploadForm:
      type: object
      properties:
        cdn:
          type: integer
          description: >-
            The CDN number to use for the upload.
        key:
          type: string
          description: >-
            The object key for the attachment.
        headers:
          type: object
          description: >-
            HTTP headers to include in the upload r

# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/signal/refs/heads/main/openapi/signal-server-openapi.yml