Register built-in calls device reachability

POST https://z.u1v.ru/api/v1/calls/devices/register

Register the authenticated user's current device for built-in direct call reachability.

This endpoint preserves the same Zulip-authenticated trust boundary as POST /calls/bootstrap. Clients submit device capabilities and contact hints, but the server remains authoritative for the authenticated user's projected SIP identity and any broker-facing credentials or headers.

The response always declares whether direct calling remains available or must fail closed to the existing provider_link fallback contract.

Usage examples

The -u line implements HTTP Basic authentication. See the Authorization header documentation for how to get those credentials for Zulip users and bots.

curl -sSX POST https://z.u1v.ru/api/v1/calls/devices/register \
    -u EMAIL_ADDRESS:API_KEY \
    --data-urlencode user_id=42 \
    --data-urlencode device_instance_id=device-1 \
    --data-urlencode public_identity=sip:hamlet@sip.example.com \
    --data-urlencode 'capabilities={"appVersion": "30.0.271+271", "platform": "linux", "supportsPushWake": false, "supportsVideo": true}' \
    --data-urlencode 'push_tokens={"apns": {"token": "redacted"}}' \
    --data-urlencode contact_address=sip:hamlet@sip.example.com \
    --data-urlencode 'metadata={"scope": "desktop"}' \
    --data-urlencode 'push_routes=[{"route_id": "apns", "token": "abcd1234"}, {"route_id": "fcm", "token": "efgh5678"}]' \
    --data-urlencode app_brand_id=com.example.zulip \
    --data-urlencode app_package_id=com.zulip.flutter \
    --data-urlencode server_id=zulip-prod-1 \
    --data-urlencode realm_id=42 \
    --data-urlencode app_version=30.0.271+271 \
    --data-urlencode build_channel=release \
    --data-urlencode signing_certificate_id=ABCDE12345 \
    --data-urlencode platform=ios \
    --data-urlencode os_major=26 \
    --data-urlencode manufacturer=Apple \
    --data-urlencode device_model=iPhone \
    --data-urlencode 'device_alias=Personal phone' \
    --data-urlencode realm_url=https://chat.example.com \
    --data-urlencode account_user_id=42 \
    --data-urlencode environment=production

Parameters

user_id string required

Example: "42"

Authenticated Zulip user ID for the active account.


device_instance_id string required

Example: "device-1"

Stable client-generated or bootstrap-projected device instance identifier.


public_identity string required

Example: "sip:hamlet@sip.example.com"

Public SIP identity the client expects the server to confirm for the authenticated user.


capabilities object required

Example: {"platform": "linux", "appVersion": "30.0.271+271", "supportsVideo": true, "supportsPushWake": false}

Device capabilities that inform reachability provisioning and future push-platform expansion.


push_tokens object | null optional

Example: {"apns": {"token": "redacted"}}

Optional RFC 8599 push-token bundle. Desktop clients typically omit this field in Phase 120.


contact_address string | null optional

Example: "sip:hamlet@sip.example.com"

Optional preferred SIP contact address hint.


metadata object optional

Example: {"scope": "desktop"}

Optional app-owned registration metadata.


push_routes (object)[] optional

Example: [{"route_id": "apns", "token": "abcd1234"}, {"route_id": "fcm", "token": "efgh5678"}]

Optional list of push route objects the client supports, used by the push route registry (feature level 499). Each item is a dict describing a push route with arbitrary string/boolean/integer/number-valued properties.


app_brand_id string | null optional

Example: "com.example.zulip"

Optional application brand identifier for multi-brand push routing (feature level 499).


app_package_id string | null optional

Example: "com.zulip.flutter"

Optional application package identifier for push route registry (feature level 499).


server_id string | null optional

Example: "zulip-prod-1"

Optional logical server identifier for push route registry (feature level 499).


realm_id string | null optional

Example: "42"

Optional realm identifier for push route registry (feature level 499).


app_version string | null optional

Example: "30.0.271+271"

Client application version used for route diagnostics.


build_channel string | null optional

Example: "release"

Client release channel used for route diagnostics.


signing_certificate_id string | null optional

Example: "ABCDE12345"

Public build identity used to bind push routes to the configured application brand. Android sends the uppercase SHA-256 signing-certificate fingerprint; Apple platforms send the Team ID.


platform string | null optional

Example: "ios"

Client platform used for application-brand validation.


os_major string | null optional

Example: "26"

Operating-system major version for user-facing diagnostics.


manufacturer string | null optional

Example: "Apple"

Device manufacturer for user-facing diagnostics.


device_model string | null optional

Example: "iPhone"

Public device model for user-facing diagnostics.


device_alias string | null optional

Example: "Personal phone"

Optional name explicitly assigned by the user.


realm_url string | null optional

Example: "https://chat.example.com"

Canonical URL of the active Zulip organization.


account_user_id string | null optional

Example: "42"

Client-side account user identifier.


environment string | null optional

Example: "production"

Client deployment environment.


Response

Return values

  • availability: string

    Server-authoritative availability value. * fallback_mode: string

    Server-authoritative fallback_mode value. * fallback_reason: string | null

    Server-authoritative fallback_reason value. * ui_error_code: string | null

    Server-authoritative ui_error_code value. * identity: object | null

    Server-authoritative identity details. * sip_identity: string

    Server-authoritative `sip_identity` value.
    
    • person_id: string

      Server-authoritative person_id value. * registration: object | null

    Server-authoritative registration details. * userId: string

    Server-authoritative `userId` value.
    
    • deviceInstanceId: string

      Server-authoritative deviceInstanceId value. * bindingId: string

      Server-authoritative bindingId value. * contactUriParams: object

      Server-authoritative contactUriParams details. * Server-authoritative mapping value. * registerExtraHeaders: (string)[]

      Server-authoritative registerExtraHeaders list. * webSocketHeaders: object

      Server-authoritative webSocketHeaders details. * Server-authoritative mapping value. * iceServers: (object)[]

      Server-authoritative iceServers list. * defaultInviteHeaders: (string)[]

      Server-authoritative defaultInviteHeaders list. * registrationExpiresSeconds: integer

      Server-authoritative registrationExpiresSeconds value. * refreshAfterSeconds: integer

      Server-authoritative refreshAfterSeconds value. * forceReregister: boolean

      Whether the server-authoritative forceReregister condition is true. * metadata: object

      Server-authoritative metadata details. * Server-authoritative mapping value. * routes: (object)[]

      Broker-reported push route statuses for this registration, if returned by the call-control broker.

  • pushRoutePolicyVersion: integer | null

    Push route policy version returned when the push route registry is enabled (feature level 499).

  • routes: (object)[]

    Active push route statuses for this device, returned when the push route registry is enabled or when the call-control broker reports accepted call routes (feature level 499). Raw provider tokens are never echoed in this response.

Example response(s)

Changes: As of Zulip 7.0 (feature level 167), if any parameters sent in the request are not supported by this endpoint, a successful JSON response will include an ignored_parameters_unsupported array.

A typical successful JSON response may look like:

{
    "availability": "available",
    "fallback_mode": "provider_link",
    "identity": {
        "person_id": "person-hamlet",
        "sip_identity": "sip:hamlet@sip.example.com"
    },
    "msg": "",
    "registration": {
        "bindingId": "binding-1",
        "defaultInviteHeaders": [
            "X-App-Device-Id: device-1"
        ],
        "deviceInstanceId": "device-1",
        "metadata": {
            "publicIdentity": "sip:hamlet@sip.example.com"
        },
        "refreshAfterSeconds": 480,
        "registerExtraHeaders": [
            "Authorization: Bearer pbx-register"
        ],
        "registrationExpiresSeconds": 600,
        "userId": "42"
    },
    "result": "success"
}