Threema Message API

As a developer, you will find here all necessary information and source code to successfully integrate Threema Gateway in your environment. Threema does not provide a graphical user interface for Threema Gateway. The Message API is an interface that can be used from within customer-specific software to send and receive messages via Threema Gateway.
We strongly recommend to use our existing SDKs as they are kept up to date, follow best practices, and are thoroughly tested to ensure encryption is done right.

This API can be used to send messages to any Threema user, and to receive incoming messages and delivery receipts. There are two main modes of operation:

  • Basic mode (server-based encryption)
    • The server handles all encryption for you.
    • The server needs to know the private key associated with your Threema API identity.
    • Incoming messages and delivery receipts are not supported.
  • End-to-end encrypted mode
    • The server doesn't know your private key.
    • Incoming messages and delivery receipts are supported.
    • You need to run software on your side to encrypt each message before it can be sent, and to decrypt any incoming messages or delivery receipts.

The mode that you can use depends on the way your account was set up.

Please only create your own client implementation or API library if you have the required knowledge. You may want to check out the source code of the existing SDKs as a guideline.

To make client-side integration as simple as possible, the API is based on plain old HTTPS GET/POST operations. Authentication details (i.e. the API identity and key) are passed as GET/POST parameters as well (no need for HTTP authentication). The HTTP status code reflects the result of the operation (e.g. 200 OK, 401 Unauthorized, 402 Payment Required, 404 Not Found etc.).

Sending Messages

Basic mode

URL: https://msgapi.threema.ch/send_simple

POST parameters (application/x-www-form-urlencoded):

  • from your API identity (8 characters, usually starts with '*')
  • recipient specifier – choose one:
    • to recipient identity (8 characters)
    • phone recipient phone number (E.164), without leading +
    • email recipient email address
  • text message text, max. 3500 bytes, UTF-8 encoded
  • secret API authentication secret

By using the phone or email recipient specifiers, one can avoid having to look up the corresponding ID (see "Lookup ID" below) and instead do everything in one call (may be more suitable for SMS gateway style integration).

Possible HTTP result codes:

  • 200 (on success)
  • 400 (if the recipient identity is invalid or the account is not set up for basic mode)
  • 401 (if API identity or secret are incorrect)
  • 402 (if no credits remain)
  • 404 (if using phone or email as the recipient specifier, and the corresponding recipient could not be found)
  • 413 (if the message is too long)
  • 429 (if rate-limiting was triggered)
  • 500 (if a temporary internal server error occurs)

On success (HTTP 200), the ID of the new message is returned as text/plain.

Example
$ curl -H 'accept: */*' -H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' -X POST \
  https://msgapi.threema.ch/send_simple -d 'to=THREEMA_ID&text=example%20msg&from=*YOUR_GATEWAY_BASIC_ID&secret=SECRET'

End-to-end encrypted mode

For more information on the format of encrypted messages, please visit the dedicated E2E page.

URL: https://msgapi.threema.ch/send_e2e

POST parameters (application/x-www-form-urlencoded):

  • from your API identity (8 characters, usually starts with '*')
  • to recipient identity (8 characters)
  • nonce nonce used for encryption (24 bytes, hex encoded)
  • box encrypted message data (max. 7812 bytes, hex encoded)
  • secret API authentication secret
  • noDeliveryReceipts (optional) if set to 1, the recipient is requested not to send delivery receipts for this message. Older app versions may ignore this flag.
  • noPush (optional) if set to 1, no push will be sent (push flag in message unset). By default, the push flag is set.
  • group (optional) if set to 1, the group flag will be set

The nonce should consist of 24 cryptographically secure random bytes.

Possible HTTP result codes:

  • 200 (on success)
  • 400 (if the recipient identity is invalid or the account is not set up for end-to-end mode)
  • 401 (if API identity or secret are incorrect)
  • 402 (if no credits remain)
  • 413 (if the message is too long)
  • 429 (if rate-limiting was triggered)
  • 500 (if a temporary internal server error occurs)

On success (HTTP 200), the ID of the new message is returned as text/plain.

Bulk end-to-end encrypted mode

This endpoint is rate-limited. You may send a maximum of 1000 messages in a single bulk request and will receive a HTTP status code 413 if exceeded.

URL: https://msgapi.threema.ch/send_e2e_bulk?from=xxxxxxxx&secret=xxxxxxxx

The endpoint accepts a JSON array in the POST body, and returns a JSON array in the response. Each response array element corresponds with the request array element at the same position.

POST query parameters (urlencoded):

  • from your API identity (8 characters, usually starts with '*')
  • secret API authentication secret
  • sameMessageId (optional) if set to 1, the same message ID will be used for all messages in the bulk operation

POST body (application/json):

  • to recipient identity (8 characters)
  • nonce nonce used for encryption (24 bytes, base64 encoded)
  • box encrypted message data (max. 7812 bytes, base64 encoded)
  • noDeliveryReceipts (optional) if set to 1, the recipient is requested not to send delivery receipts for this message. Older app versions may ignore this flag.
  • noPush (optional) if set to 1, no push will be sent (push flag in message unset). By default, the push flag is set.
  • group (optional) if set to 1, the group flag will be set
[
	{
		"to": "ECHOECHO",
		"box": "jB/IVfeQH0nLkBRm6tNrNE/fsJlUV5J7XcB/FQcZGVpN2S0V...",
		"nonce": "HF1YtfcqiccIRz9IN1w1aDt2slSYIoXY",
		"noDeliveryReceipts": true,     // optional
		"noPush": false,                // optional
		"group": true                   // optional
	},
	{
		"box": "...",
		...
	},
	...
]

The nonce should consist of 24 cryptographically secure random bytes.

Possible HTTP result codes:

  • 200 (on success – but individual messages may still have an error code, see JSON response)
  • 400 (if the sender identity is invalid, not set up for end-to-end mode or a to/nonce/box parameter is invalid)
  • 401 (if API identity or secret are incorrect)
  • 402 (if no credits remain)
  • 413 (if the message is too long)
  • 429 (if rate-limiting was triggered)
  • 500 (if a temporary internal server error occurs)

On success (HTTP 200), a JSON array is returned. Each object contains either a messageId key or an errorCode (which corresponds with HTTP error codes). Example:

[
	{
		"messageId": "1239828a197d82da"
	},
	{
		"errorCode": 402
	},
	...
]

Group messages

Please note that support of group messages is provisional, and the documentation, therefore, is not complete.

Group messages are currently supported by the following SDKs:

  • PHP
  • .NET (starting from 2.0.0)
  • Java (starting from 2.0.0)

To send a group message, both the group ID and the Threema IDs of all recipients must be passed on to the sendGroupXXXMessage(...) function.

When creating a group, a random 8-byte ID must be chosen. Together with the ID of the group creator, it serves as a unique identifier for the group.

In the rare case where a Gateway integration with an existing group is required, an inbound URL can be specified to obtain the respective group ID by simply deserializing any group (control) message sent to all group members.

Interaction with groups is non-trivial and requires substantial implementation effort to handle control messages and chat state. Currently, our SDKs do not provide the means to take advantage of group messages without considerable work.

When the creator of a group is a Gateway ID, the group’s name must start with a “☁️” for incoming messages to be received. (Otherwise, only group exits and group sync requests will be forwarded to the specified HTTP endpoint.) With this behavior, users are aware that the group’s creator is a Gateway ID and that their messages are also sent to that ID.

ID Lookups

Find ID by phone number

URL: https://msgapi.threema.ch/lookup/phone/41791234567?from=xxxxxxxx&secret=xxxxxxxx

The phone number must be passed in E.164 format, without the leading +. The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).

The Threema ID corresponding to the phone number will be returned as a text/plain response.

Possible HTTP result codes:

  • 200 (on success)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no matching ID could be found)
  • 500 (if a temporary internal server error occurs)

Find ID by phone number hash

URL: https://msgapi.threema.ch/lookup/phone_hash/0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef?from=xxxxxxxx&secret=xxxxxxxx

The phone number must be passed as an HMAC-SHA256 hash of the E.164 number without the leading +. The HMAC key is 85adf8226953f3d96cfd5d09bf29555eb955fcd8aa5ec4f9fcd869e258370723 (in hexadecimal).

Example: the phone number 41791234567 hashes to ad398f4d7ebe63c6550a486cc6e07f9baa09bd9d8b3d8cb9d9be106d35a7fdbc.

The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).

The Threema ID corresponding to the phone number will be returned as a text/plain response.

Possible HTTP result codes:

  • 200 (on success)
  • 400 (if the hash length is wrong)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no matching ID could be found)
  • 500 (if a temporary internal server error occurs)

Find ID by email address

URL: https://msgapi.threema.ch/lookup/email/john@doe.com?from=xxxxxxxx&secret=xxxxxxxx

The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).

The Threema ID corresponding to the email address will be returned as a text/plain response.

Possible HTTP result codes:

  • 200 (on success)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no matching ID could be found)
  • 500 (if a temporary internal server error occurs)

Find ID by email address hash

URL: https://msgapi.threema.ch/lookup/email_hash/0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef?from=xxxxxxxx&secret=xxxxxxxx

The lowercased and whitespace-trimmed email address must be hashed with HMAC-SHA256. The HMAC key is 30a5500fed9701fa6defdb610841900febb8e430881f7ad816826264ec09bad7 (in hexadecimal).

Example: the email address test@threema.ch hashes to 1ea093239cc5f0e1b6ec81b866265b921f26dc4033025410063309f4d1a8ee2c.

The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).

The Threema ID corresponding to the email address will be returned as a text/plain response.

Possible HTTP result codes:

  • 200 (on success)
  • 400 (if the hash length is wrong)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no matching ID could be found)
  • 500 (if a temporary internal server error occurs)

Bulk lookup

The use of this endpoint is restricted and requires manual approval. Please contact our support team directly if you would like to use this feature.

URL: https://msgapi.threema.ch/lookup/bulk?from=xxxxxxxx&secret=xxxxxxxx

This URL can be used to lookup up to 1000 phone number hashes or email address hashes per request. See above for details on the hashing.

The API identity and secret must be passed in the URL query string for authentication (use URL encoding).

The POST request body must be a JSON document with the following format:

{
	"phoneHashes": ["27b0e25b6091a0d527e0265e2b4669691f253fd7e4fdca4e82ad37cb1e2bcc32",
		"ebe6cf4cb497b626622ed7eca80dff38a766153cb820441c03cd2677976b3b6a"],
	"emailHashes": ["eca1f01b9fa1ae14ba9d2fe236cde235c0f7877e73173d13501635a63010ded5",
		"8bb29bd2b5e7b9ca317eb345fd1f7f9a1f7a0524369872b0dac2d903fdfe36e3"],
}

The response will also be returned as a JSON document:

{
	"phoneHash": "27b0e25b6091a0d527e0265e2b4669691f253fd7e4fdca4e82ad37cb1e2bcc32",
	"identity": "QRSTUVWX",
	"publicKey": "e58771baf2db70989d0724ef77ba6bf867d46aaa24fc2c3f8f0f144d89a6264b"
},{
	"emailHash": "8bb29bd2b5e7b9ca317eb345fd1f7f9a1f7a0524369872b0dac2d903fdfe36e3",
	"identity": "JIKLMNOP",
	"publicKey": "6a2bd9a0912d4ce0e5c6fc6c9b8ac14a8fdb6282a34c7e0f5fe57d57c54fb69f"
}

In this example, matches were found for one phone number hash and one email address hash, while no matches were found for the other hashes. Note: if both a phone number hash and an email address hash are provided that resolve to the same identity, only one entry will be returned in the response array, but it will have both a phoneHash and an emailHash key. At most 1000 hashes may be specified per request (i.e. the number of phone number hashes plus the number of email hashes may not be more than 1000).

Possible HTTP result codes:

  • 200 (on success)
  • 400 (if the JSON is invalid or a hash length is wrong)
  • 401 (if API identity or secret are incorrect)
  • 413 (if too many hashes have been specified in the request)
  • 429 (if rate-limiting was triggered)
  • 500 (if a temporary internal server error occurs)

Check file reception capability of an ID

Before you send a file to a Threema ID using the blob upload (+ file message), you may want to check whether the recipient uses a Threema version that supports receiving files. The receiver may be using an old version, or a platform where file reception is not supported.

URL: https://msgapi.threema.ch/capabilities/XXXXXXXX?from=xxxxxxxx&secret=xxxxxxxx

The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).
The result is a text/plain response of supported capabilities, separated by commas. Currently defined capabilities:

  • text
  • image
  • video
  • audio
  • group
  • ballot
  • file
  • call
  • videocall
  • pfs
  • groupcall

More capabilities may be added in the future (separated with commas), so you should match on substrings when checking for file. The order in which the capabilities are returned is not defined.

Example result: text,image,video,audio,file

Possible HTTP result codes:

  • 200 (on success)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no matching ID could be found)
  • 500 (if a temporary internal server error occurs)

Key Lookups

For the end-to-end encrypted mode, you need the public key of the recipient in order to encrypt a message. While it's best to obtain this directly from the recipient (extract it from the QR code), this may not be convenient, and therefore you can also look up the key associated with a given ID from the server.

URL: https://msgapi.threema.ch/pubkeys/XXXXXXXX?from=xxxxxxxx&secret=xxxxxxxx

The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).
The public key corresponding to the ID will be returned as a text/plain response (hex encoded).

Possible HTTP result codes:

  • 200 (on success)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no matching ID could be found)
  • 500 (if a temporary internal server error occurs)

It is strongly recommended that you cache the public keys to avoid querying the API for each message.

Incoming Messages and Delivery Receipts

If your account is operating in end-to-end encrypted mode and incoming messages have been enabled on it, you can specify an HTTPS URL callback that will be called whenever an incoming message or delivery receipt arrives for your API identity. You can set or change the callback URL in the Threema Gateway administration panel.

Callback parameters

Your callback URL will be called with the following POST parameters (application/x-www-form-urlencoded):

  • from sender identity (8 characters)
  • to your API identity (8 characters, usually starts with '*')
  • messageId message ID assigned by the sender (8 bytes, hex encoded)
  • date message date set by the sender (UNIX timestamp)
  • nonce nonce used for encryption (24 bytes, hex encoded)
  • box encrypted message data (max. 7812 bytes, hex encoded)
  • mac Message Authentication Code (32 bytes, hex encoded, see below)
  • nickname public nickname of the sender, if set

Note that the message first needs to be decrypted before it can be determined whether it is an incoming text/media message or a delivery receipt.

MAC calculation

For each callback, the server includes a mac parameter than can be used to verify the authenticity of the call and the included information. This parameter is calculated as follows:

mac = HMAC-SHA256(from || to || messageId || date || nonce || box, secret)
|| denotes concatenation. The parameters are concatenated in the same form as they were included in the POST (i.e. including any hex encoding, but not including any URL encoding). The secret that is used for the HMAC operation is the API authentication secret.

It is recommended that receivers verify the mac parameter before attempting to parse the other parameters and decrypt the message.

Callback results and retry

If the connection to your callback URL fails or your callback does not return an HTTP 200 status, the API will retry 3 more times in intervals of 5 minutes. If all attempts fail, the message is discarded.

Certificates and cipher suites

The server that hosts the callback URL must use a valid and trusted SSL/TLS certificate (not self-signed). If in doubt, please contact customer service and specify the issuing CA of your certificate.

File Upload and Download

Upload

URL: https://msgapi.threema.ch/upload_blob

POST parameters (multipart/form-data):

  • blob blob data (binary), max. 50 MB

URL parameters ("GET"):

  • from your API identity (8 characters, usually starts with '*')
  • secret API authentication secret

Please note that the authentication parameters must be passed in the request URL ("/upload_blob?from=...&secret=..."), while the actual blob data needs to be sent as a multipart/form-data parameter.

Possible HTTP result codes:

  • 200 (on success)
  • 400 (if required parameters are missing or the blob is empty)
  • 401 (if API identity or secret are incorrect)
  • 402 (if no credits remain)
  • 413 (if the blob is too big)
  • 429 (if rate-limiting was triggered)
  • 500 (if a temporary internal server error occurs)

The ID of the new blob is returned as text/plain. One credit is deducted for the upload of a blob.

Download

URL: https://msgapi.threema.ch/blobs/blobId

GET parameters:

  • from your API identity (8 characters, usually starts with '*')
  • secret API authentication secret

Possible HTTP result codes:

  • 200 (on success, body is the blob data as application/octet-stream)
  • 401 (if API identity or secret are incorrect)
  • 404 (if no blob with this ID could be found)
  • 500 (if a temporary internal server error occurs)

Please note: after a blob download has first been attempted, the blob may be deleted from the server within an hour.

Querying Account Information

Get remaining credits

URL: https://msgapi.threema.ch/credits?from=xxxxxxxx&secret=xxxxxxxx

The API identity and secret must be passed in the corresponding GET parameters for authentication (use URL encoding).

The number of credits left on the account that the given ID belongs to will be returned as a text/plain response. Note: several IDs may use the same account, and thus share the same credit balance.

Possible HTTP result codes:

  • 200 (on success)
  • 401 (if API identity or secret are incorrect)
  • 500 (if a temporary internal server error occurs)