1.10. Mailbox RESTful API#

This is the API documentation for the GNU Taler Mailbox service which allows Taler wallets to securely send push and pull payment requests to other wallets without having to interact with the respective messaging service.

Clients (wallets) are expected to generate mailbox keys that uniquely identify a mailbox as well as encryption keys that can be used to encrypt messages for the mailbox (e.g. HPKE. Mailbox signing keys are usable implicity, but encryption keys must be generated and put into the key directory.

The API specified here follows the general conventions for all details not specified in the individual requests. The glossary defines all specific terms used in this section.

1.10.1. Terms of service API#

These APIs allow clients to obtain the terms of service and the privacy policy of a service.

GET /terms#

Get the terms of service of the service. The endpoint will consider the “Accept” and “Accept-Language” and “Accept-Encoding” headers when generating a response. Specifically, it will try to find a response with an acceptable mime-type, then pick the version in the most preferred language of the user, and finally apply compression if that is allowed by the client and deemed beneficial.

The endpoint will set an “Etag”, and subsequent requests of the same client should provide the tag in an “If-None-Match” header to detect if the terms of service have changed. If not, a “304 Not Modified” response will be returned. Note that the “304 Not Modified” will also be returned if the client changed the “Accept-Language” or “Accept-Encoding” header. Thus, if the client would like to download the resource in a different language or format, the “If-None-Match” header must be omitted.

If the “Etag” is missing, the client should not cache the response and instead prompt the user again at the next opportunity. This is usually only the case if the terms of service were not configured correctly.

The “Etag” is generated from the first 256 bits of the SHA-512 hash over the terms and encoded in Crockford base-32. However, this behavior is not normative and clients MUST NOT rely on it.

A “Taler-Terms-Version” header is generated to indicate the legal version of the terms. This header will change whenever something legally changed in the terms of service and the user must review and accept the terms of service again. If the “Taler-Terms-Version” is identical to one that the user has already accepted, there is no need for the user to review the terms again.

When returning a full response (not a “304 Not Modified”), the server should also include a “Avail-Languages” header which includes a comma-separated list of the languages in which the terms of service are available in (see availability hints specification). Clients can use this to generate a language switcher for users that may not have expressed a proper language preference.

Response:

200 OK:

The body is the terms of service in the requested encoding and language.

501 Not Implemented:

The exchange lacks a valid terms of service configuration. A human-readable error message is returned. Wallets should not require the human to accept any terms of service (and do not need to show this message).

GET /privacy#

Get the privacy policy of the service. Behaves the same way as The “/terms” endpoint, except that it returns the privacy policy instead of the terms of service.

Response:

200 OK:

The body is the privacy policy in the requested encoding and language.

501 Not Implemented:

The exchange lacks a valid terms of service configuration. A human-readable error message is returned. Wallets should not require the human to accept any terms of service (and do not need to show this message).

1.10.2. Configuration information#

GET /config#

Return the protocol version and currency supported by this service.

Response:

200 OK:

The body is a VersionResponse.

Details:

interface VersionResponse {
  // libtool-style representation of the Merchant protocol version, see
  // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
  // The format is "current:revision:age".
  version: string;

  // Name of the protocol.
  name: "taler-mailbox";

  // Fee per message.
  message_fee: Amount;

  // Fixed size of message body.
  message_body_bytes: Integer;

  // Maximum number of messages in a
  // single response.
  message_response_limit: Integer;

  // How long will the service store a message
  // before giving up on delivery?
  delivery_period: RelativeTime;

}

1.10.3. Sending messages#

POST /$H_MAILBOX#

Puts a message into $H_MAILBOX. $H_MAILBOX is the SHA512 of an EdDSA public key.

Request

The content of the request must be the message with a size of exactly message_body_bytes (see VersionResponse). The header Mailbox-Order-Id may be provided if the client recently paid for this message.

Response

204 No Content

Message was stored and will be delivered.

402 Payment Required

Client needs to make a Taler payment before proceeding. See standard Taler payment procedure.

403 Forbidden

The specified order ID in the Mailbox-Order-Id header does not permit sending of this message. Possible reasons include the order being for a different message, unpaid or malformed. This response comes with a standard ErrorDetail response.

429 Too Many Requests:

The system is currently experiencing a too high request load and is unable to accept the message for delivery. The response format is given by MailboxRateLimitedResponse.

Details:

interface MailboxRateLimitedResponse {

  // Taler error code, TALER_EC_MAILBOX_DELIVERY_RATE_LIMITED.
  code: number;

  // When the client should retry.
  retry_delay: RelativeTime;

  // The human readable error message.
  hint: string;

}

1.10.4. Receiving messages#

GET /$H_MAILBOX#

Endpoint that returns unread messages in $H_MAILBOX. The number of messages returned by the service can be limited. If the request is simply repeated, the same messages will be returned again (or possibly more if additional messages arrived and the total number is below the service’s current internal limit). To receive additional messages, the client generally has to first explicitly delete already downloaded messages from the mailbox. If messages are returned, the ETag header will be set containing the ID of the first message for use in any potential delete requests that require the message ID.

Request:

Query Parameters:
  • timeout_ms=NUMBEROptional. If specified, the Mailbox service will wait up to NUMBER milliseconds for the arrival of new messages before sending the HTTP response. Note that if the mailbox is non-empty, the service will always return immediately with the messages in the mailbox, and not wait for additional messages to arrive.

Response

200 Ok:

Messages are returned in binary format, 256 bytes per message, starting with the ephemeral key and followed by the encrypted body. Messages are not encapsulated in JSON!

204 No Content:

The mailbox is empty.

429 Too Many Requests:

The system is currently experiencing a too high request load and is unable to accept the message for delivery. The response format is given by MailboxRateLimitedResponse.

POST /private/$ADDRESS#

Requests the deletion of already received messages from the mailbox. Here, $ADDRESS must be the EdDSA public key of the mailbox (not the hash!). The ETag header returned by a GET request for messages returns the ID for the first message received. This allows the caller to select a range of messages starting from the first message received in the last GET call to delete.

Request

The body of the request must be a MessageDeletionRequest. The header Match-If must be set to the ID of the first message to delete. For example, a Match-If header value of 2 and a count field of 5 will delete messages from ID 2 to 7 (given a valid signature).

Details:

interface MessageDeletionRequest {

  // Number of messages to delete. (Starting from the beginning
  // of the latest GET response).
  count: Integer;

  // SHA-512 hash over all messages to delete.
  checksum: HashCode;

  // Signature by the mailbox's private key affirming
  // the deletion of the messages, of purpuse
  // TALER_SIGNATURE_WALLET_MAILBOX_DELETE_MESSAGES.
  signature: string;

}

Response

204 No Content:

Deletion complete.

403 Forbidden:

The signature is invalid. This response comes with a standard ErrorDetail response.

404 Not found:

The checksum does not match the messages currently at the head of the mailbox, or count is larger than the number of messages currently in the mailbox. This response comes with a standard ErrorDetail response.

1.10.5. Key directory#

GET /keys/$H_MAILBOX#

Endpoint that returns signing and encryption keys for $H_MAILBOX.

Response

200 Ok:

Keys are returned in a MailboxMessageKeys response,

404 Not Found:

The mailbox has no keys configured.

429 Too Many Requests:

The system is currently experiencing a too high request load and is unable to accept the message for delivery. The response format is given by MailboxRateLimitedResponse.

Details:

interface MailboxMessageKeys {

  // The mailbox signing key.
  // Note that $H_MAILBOX == H(singingKey).
  // Note also how this key cannot be updated
  // as it identifies the mailbox.
  // Base32 crockford-encoded.
  signingKey: string;

  // Type of key.
  // Currently only
  // EdDSA keys are supported.
  signingKeyType: "EdDSA";

  // The mailbox encryption key.
  // This is a HPKE public key
  // Currently, only the X25519 format
  // for use in a X25519-DHKEM (RFC 9180)
  // is supported.
  // Base32 crockford-encoded.
  encryptionKey: string;

  // Type of key.
  // Currently only
  // X25519 keys are supported.
  encryptionKeyType: "X25519";

  // Expiration of this mapping.
  // Unix epoch (seconds)
  expiration: Timestamp;

}
POST /keys#

Requests the update of the encryption key for the mailbox. The mailbox identity is given through the keys field in the MailboxMessageKeys field.

Request

The body of the request must be a KeyUpdateRequest.

Details:

interface KeyUpdateRequest {

  // Keys to add/update for a mailbox.
  keys: MailboxMessageKeys;

  // Signature by the mailbox's signing key affirming
  // the update of keys, of purpose
  // TALER_SIGNATURE_WALLET_MAILBOX_UPDATE_KEYS.
  // The signature is created over the SHA-512 hash
  // of (encryptionKeyType||encryptionKey||expiration)
  // Base32 crockford-encoded.
  // The signature system is defined through the
  // signingKeyType in the keys field.
  signature: string;

}

Response

204 No Content:

Update/creation complete.

403 Forbidden:

The signature is invalid. This response comes with a standard ErrorDetail response.