Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

gRPC API

The gRPC API links and unlinks platform accounts and syncs ephemeral key pools. The RelaySMS app calls it while online.

Protocol buffer file

curl -O -L https://raw.githubusercontent.com/smswithoutborders/RelaySMS-Publisher/main/protos/v3/publisher.proto

Package publisher.v3, service Publisher.

Generate a client

Generate stubs with protoc for your language. For Python:

pip install grpcio-tools
python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. publisher.proto

Request headers

Every RPC needs these headers. Headers ending in -bin carry raw binary.

HeaderTypeRequiredDescription
x-payload-binbytesYesEncrypted request payload ciphertext
x-public-key-binbytesYesClient ephemeral public key ($eC_{pk}$, 32 bytes)
x-key-idstringYesID of the server identity key used to encrypt the payload
x-nonce-binbytesYesRequest nonce (16 bytes)
x-timestampstringYesUnix timestamp in seconds, within NONCE_TTL_SECONDS of the server’s clock

The examples use -plaintext against a local server; drop it for a server behind TLS on port 443.

Methods

Get OAuth2 authorization URL

Returns the URL that starts the OAuth2 flow.

Request: GetOAuth2AuthorizationUrlRequest

FieldTypeRequiredDescription
platformstringYesPlatform identifier, such as gmail
statestringNoOAuth2 state, returned unchanged
code_verifierstringNoPKCE code verifier
autogenerate_code_verifierboolNoGenerate a code verifier when none is sent
redirect_urlstringNoRedirect URL for OAuth2 application
request_identifierstringNoRequest identifier for tracking

Response: GetOAuth2AuthorizationUrlResponse

FieldTypeDescription
authorization_urlstringGenerated authorization URL
statestringThe state sent
code_verifierstringPKCE code verifier used
messagestringHuman-readable result
scopestringAuthorization request scope
client_idstringOAuth2 application client ID
redirect_urlstringOAuth2 application redirect URL

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d '{
    "platform": "gmail",
    "autogenerate_code_verifier": true
  }' \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/GetOAuth2AuthorizationUrl

Exchange OAuth2 code and store token

Exchanges an OAuth2 authorization code for tokens and stores them. Returns encrypted token data and a set of server ephemeral keys.

Request: ExchangeOAuth2CodeAndStoreRequest

FieldTypeRequiredDescription
platformstringYesPlatform identifier
authorization_codestringYesOAuth2 authorization code
code_verifierstringNoCode verifier for PKCE
redirect_urlstringNoRedirect URL for OAuth2 application
request_identifierstringNoRequest identifier for tracking
client_ephemeral_public_keyslist[PublicKey]YesExactly 256 ephemeral public keys generated by the client, with key_id 0-255 each used once

PublicKey message:

FieldTypeDescription
key_iduint32Key index (0-255)
public_keybytes32-byte public key

Response: ExchangeOAuth2CodeAndStoreResponse

FieldTypeDescription
successbooltrue if the call succeeded
messagestringHuman-readable result
account_identifierstringAccount identifier, such as mail@example.com
token_ciphertextbytesEncrypted token ciphertext
token_iduint32Unique identifier for the stored token
server_ephemeral_public_keyslist[PublicKey]Exactly 256 ephemeral public keys generated by the server

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d @ \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/ExchangeOAuth2CodeAndStore <<EOF
{
  "platform": "gmail",
  "authorization_code": "auth_code",
  "client_ephemeral_public_keys": [
    {"key_id": 0, "public_key": "..."},
    ... 254 more keys ...
    {"key_id": 255, "public_key": "..."}
  ]
}
EOF

Revoke and delete OAuth2 token

Revokes and deletes a stored OAuth2 token, identified by its token ID and the key ID that encrypted it.

Request: RevokeOAuth2TokenRequest

FieldTypeRequiredDescription
token_iduint32YesUnique identifier for the stored token
key_iduint32YesKey index used for encrypting the token

Response: RevokeOAuth2TokenResponse

FieldTypeDescription
successbooltrue if the call succeeded
messagestringHuman-readable result

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d '{
    "token_id": 2941967295,
    "key_id": 123
  }' \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/RevokeOAuth2Token

Get PNBA code

Requests a one-time passcode (OTP) for phone number-based authentication (PNBA).

Request: GetPNBACodeRequest

FieldTypeRequiredDescription
platformstringYesPlatform identifier
phone_numberstringYesPhone number to receive OTP
request_identifierstringNoRequest identifier for tracking
channelstringNoChannel to send the code over, such as signal

Response: GetPNBACodeResponse

FieldTypeDescription
successbooltrue if the call succeeded
messagestringHuman-readable result
expires_atint64Optional. Code expiry, Unix epoch seconds

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d '{
    "platform": "telegram",
    "phone_number": "+237600000000"
  }' \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/GetPNBACode

Exchange PNBA code and store token

Exchanges a one-time passcode (OTP) for a token, stores it, and returns encrypted token data.

Request: ExchangePNBACodeAndStoreRequest

FieldTypeRequiredDescription
platformstringYesPlatform identifier
phone_numberstringYesPhone number that received OTP
authorization_codestringYesPNBA authorization code
passwordstringNoPassword for two-step verification
request_identifierstringNoRequest identifier for tracking
client_ephemeral_public_keyslist[PublicKey]YesExactly 256 ephemeral public keys generated by the client, with key_id 0-255 each used once
channelstringNoChannel the code was sent over, such as signal

Response: ExchangePNBACodeAndStoreResponse

FieldTypeDescription
successbooltrue if the call succeeded
messagestringHuman-readable result
two_step_verification_enabledboolTwo-step verification status
account_identifierstringAccount identifier
token_ciphertextbytesEncrypted token ciphertext
token_iduint32Unique identifier for the stored token
server_ephemeral_public_keyslist[PublicKey]Exactly 256 ephemeral public keys generated by the server
key_iduint32Key ID used for encrypting token

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d @ \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/ExchangePNBACodeAndStore <<EOF
{
  "platform": "telegram",
  "phone_number": "+237600000000",
  "authorization_code": "auth_code",
  "client_ephemeral_public_keys": [
    {"key_id": 0, "public_key": "..."},
    ... 254 more keys ...
    {"key_id": 255, "public_key": "..."}
  ]
}
EOF

Revoke and delete PNBA token

Revokes and deletes a stored PNBA token.

Request: RevokePNBATokenRequest

FieldTypeRequiredDescription
token_iduint32YesUnique identifier for the stored token
key_iduint32YesKey index used for encrypting the token

Response: RevokePNBATokenResponse

FieldTypeDescription
successbooltrue if the call succeeded
messagestringHuman-readable result

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d '{
    "token_id": 2941967295,
    "key_id": 123
  }' \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/RevokePNBAToken

Sync keys

Replaces a token’s key pools: the client sends 256 new ephemeral public keys and the server returns 256 of its own.

Request: SyncKeysRequest

FieldTypeRequiredDescription
token_iduint32YesUnique identifier for the stored token
key_iduint32YesThe current key index used for encrypting the token
client_ephemeral_public_keyslist[PublicKey]YesExactly 256 new ephemeral public keys generated by the client, with key_id 0-255 each used once

Response: SyncKeysResponse

FieldTypeDescription
successbooltrue if the call succeeded
messagestringHuman-readable result
server_ephemeral_public_keyslist[PublicKey]Exactly 256 ephemeral public keys generated by the server

Example:

grpcurl -plaintext \
  -H 'x-payload-bin: <ENCRYPTED_PAYLOAD>' \
  -H 'x-public-key-bin: <CLIENT_PUBLIC_KEY>' \
  -H 'x-key-id: <KEY_ID>' \
  -H 'x-nonce-bin: <NONCE>' \
  -H 'x-timestamp: <TIMESTAMP>' \
  -d @ \
  -proto publisher.proto \
  <HOST>:<PORT> publisher.v3.Publisher/SyncKeys <<EOF
{
  "token_id": 2941967295,
  "key_id": 123,
  "client_ephemeral_public_keys": [
    {"key_id": 0, "public_key": "..."},
    ... 254 more keys ...
    {"key_id": 255, "public_key": "..."}
  ]
}
EOF

Every RPC returns a standard gRPC status code; 0 OK is success.