17.12. Donau RESTful API#
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.
17.12.1. API Overview#
This is intended to provide a quick overview of the whole REST API. For a more detailed view of the protocol, see the protocol specification.
The chapters group the families of requests frequently encountered when using the Donau API:
Status information: get the public signing keys of the Donau, the donation unit key, the Donaus config or some entropy
Issue receipts: For use by charities: Issue receipts with blinded unique donor ids from a donor.
- Donation statement: Summarizes the donation receipts to the donation statement signature which is made over the total yearly donation amount,
the year and the hash of taxid+salt. Provides an API to get the donation statement signature.
Charity administration and status information:
For use by administrators to add/modify a charity
For use by charities to get their remaining donation volume
17.12.2. Version History#
The current protocol version is v0.
The merchant is currently targeting protocol version v0.
The donau validator app is currently targeting protocol version v0.
Version history:
v0: This is the first implementation.
Upcoming versions:
none anticipated
Ideas for future version:
vXXX: marker for features not yet targeted for release
17.12.3. 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).
17.12.4. Donau public keys and status information#
This API is used by donors and charities to obtain global information about the Donau, such as online signing keys and available donation units. This is typically the first call any Donau client makes, as it returns information required to process all of the other interactions with the Donau. The returned information is secured by signature(s) from the Donau, especially the long-term offline signing key of the Donau, which clients should cache.
- GET /keys#
Get a list of all donation units keys offered by the Donau, as well as the Donau’s current online signing key (used for donation statements).
Request:
Response:
- 200 OK:
The Donau responds with a DonauKeysResponse object. This request should virtually always be successful. It only fails if the Donau is misconfigured.
- 502 Bad Gateway:
The Donau is unable to reach one of its cryptographic helper processes. Returned with error code
TALER_EC_DONAU_DONATION_UNIT_HELPER_UNAVAILABLEorTALER_EC_DONAU_SIGNKEY_HELPER_UNAVAILABLE.- 503 Service Unavailable:
The Donau has no valid keys at this time, likely due to a configuration problem. Returned with error code
TALER_EC_DONAU_GENERIC_KEYS_MISSING.
Details:
interface DonauKeysResponse { // libtool-style representation of the Donau protocol version, see // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning // The format is "current:revision:age". version: string; // Legal/financial domain this Donau operates for. Shown to the // user by the wallet when selecting a Donau. Should match the // name of the financial authority that the user would recognize. legal_domain: string; // The Donau's base URL. base_url: string; // The Donau's currency. currency: string; // Donation units offered by this Donau. Each entry enumerates a // specific key together with its value and status. donation_units: DonationUnit[]; // The Donau's signing keys. signkeys: SignKey[]; }
interface DonationUnit extends DonationUnitKeyCommon { // How much a receipt signed with this key is worth. value: Amount; // Public key material of the donation unit. donation_unit_pub: DonationUnitKey; }
interface DonationUnitKeyCommon { // For which year is this donation unit key valid. year: Integer; // Set to 'true' if the Donau somehow "lost" the private key. The donation unit was not // revoked, but still cannot be used to withdraw receipts at this time (theoretically, // the private key could be recovered in the future; receipts signed with the private key // remain valid). lost?: boolean; }
type DonationUnitKey = | RsaDonationUnitKey | CSDonationUnitKey;
interface RsaDonationUnitKey { cipher: "RSA"; // RSA public key rsa_public_key: RsaPublicKey; // Hash of the RSA public key, as used in other API calls. pub_key_hash: HashCode; }
interface CSDonationUnitKey { cipher: "CS"; // Public key of the donation unit. cs_public_key: Cs25519Point; // Hash of the CS public key, as used in other API calls. pub_key_hash: HashCode; }
A signing key in the
signkeyslist is a JSON object with the following fields:interface SignKey { // The actual Donau's EdDSA signing public key. key: EddsaPublicKey; // Initial validity date for the signing key. year: Integer; }
Note
Both the individual donation units and the donation units list is signed, allowing customers to prove that they received an inconsistent list.
- GET /seed#
Return an entropy seed. The Donau will return a high-entropy value that will differ for every call. The response is NOT in JSON, but simply high-entropy binary data in the HTTP body. This API should be used by wallets to guard themselves against running on low-entropy (bad PRNG) hardware. Naturally, the entropy returned MUST be mixed with locally generated entropy.
- GET /config#
Return the protocol version, financial domain and currency supported by this Donau backend.
Response:
- 200 OK:
The body is a DonauVersionResponse.
interface DonauVersionResponse { // libtool-style representation of the Donau 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: "donau"; // Currency supported by this Donau. currency: string; // Financial domain by this Donau. domain: string; }
17.12.5. Issue receipts#
Inspired by the Taler exchange Withdrawal.
This API is used to obtain valid, attested donation receipts from the Donau. Use the charity GET route to see the remaining donation volume for the current year.
17.12.5.1. CSR Issue#
- POST /csr-issue#
Obtain donau-side input values in preparation for a issue receipt step for certain donation unit cipher types, specifically at this point for Clause-Schnorr blind signatures. This API is used by the donor.
Request: The request body must be a IssuePrepareRequest object.
Response:
- 201 Created:
The request was successful, and the response is a IssuePrepareResponse. Note that repeating exactly the same request will again yield the same response (assuming none of the donation unit is expired).
- 400 Bad Request:
The request body is malformed or required fields are missing, or the specified denomination key does not support this operation. Returned with error codes
TALER_EC_GENERIC_JSON_INVALIDorTALER_EC_DONAU_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION.- 404 Not Found:
One of the referenced donation unit keys could not be found. Returned with error code
TALER_EC_DONAU_GENERIC_DONATION_UNIT_UNKNOWN.
- 500 Internal Server Error:
The donation unit key is not known to the Donau, has the wrong cipher type, or the signing helper encountered an error. Returned with error code
TALER_EC_DONAU_GENERIC_KEYS_MISSINGorTALER_EC_DONAU_SIGNKEY_HELPER_BUG.- 503 Service unavailable:
The donau is lacking the keys to create the response. Returned with error code
TALER_EC_DONAU_GENERIC_KEYS_MISSING.
Details:
type IssuePrepareResponse = | DonauIssueValue;
type DonauIssueValue = | DonauRsaIssueValue | DonauCsIssueValue;
interface DonauRsaIssueValue { cipher: "RSA"; }
17.12.5.2. Batch Issue#
This is the effectiv issue receipts request. Depending on the amount of the donation a certain amount of blinded unique donation identifiers, or for short BUDIs, are required. Every BUDI will be signed by the corresponding requested donation unit, which is associated with a value. This API is used by the charity but the array of BlindedDonationReceiptKeyPair are coming from the donor.
To make the request idempotent, the hash of the hole request is recorded under the corresponding charity_id by the Donau.
- POST /batch-issue/$CHARITY_ID#
Send in a IssueReceiptsRequest and ask the Donau to sign all it’s contained BUDIs.
Request: IssueReceiptsRequest
Response:
- 200 OK:
The request was successful, and the response is a BlindedDonationReceiptSignaturesResponse. Also returned for idempotent re-requests of an already-processed batch.
- 400 Bad Request:
The request was malformed. This can occur when the
$CHARITY_IDcannot be parsed, thebudikeypairsarray is empty or contains malformed entries, or the total donation amount exceeds the charity’s per-year limit. Returned with error codeTALER_EC_GENERIC_PARAMETER_MALFORMED,TALER_EC_GENERIC_JSON_INVALID, orTALER_EC_DONAU_EXCEEDING_DONATION_LIMIT.- 403 Forbidden:
The charity signature is invalid. Returned with error code
TALER_EC_DONAU_CHARITY_SIGNATURE_INVALID.- 404 Not Found:
The charity is unknown to the Donau, or at least one of the referenced donation unit keys could not be found. Returned with error code
TALER_EC_DONAU_CHARITY_NOT_FOUNDorTALER_EC_DONAU_GENERIC_DONATION_UNIT_UNKNOWN.- 500 Internal Server Error:
The Donau encountered an internal error, such as a database failure or a signing helper problem. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILEDorTALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE- 503 Service unavailable:
The donau is lacking the keys to create the donation statement. Returned with error code
TALER_EC_DONAU_GENERIC_KEYS_MISSING.
Details:
interface IssueReceiptsRequest { // Signature by the charity approving that the // Donau should sign the donation receipts below. charity_sig: EddsaSignature; // Year for which the donation receipts are expected. // Also determines which keys are used to sign the // blinded donation receipts. year: Integer; // Array of blinded donation receipts to sign. // Must NOT be empty (if no donation receipts // are desired, just leave the entire donau // argument blank). budikeypairs: BlindedDonationReceiptKeyPair[]; }
interface BlindedDonationReceiptKeyPair { // Hash of the public key that should be used to sign // the donation receipt. h_donation_unit_pub: HashCode; // Blinded value to give to the Donau to sign over. blinded_udi: BlindedUniqueDonationIdentifier; }
interface RSABUDI { cipher: "RSA"; rsa_blinded_identifier: string; // Crockford Base32 encoded }
// For donation unit signatures based on Blind Clause-Schnorr, the BUDI // consists of the public nonce and two Curve25519 scalars which are two // blinded challenges in the Blinded Clause-Schnorr signature scheme. // See https://taler.net/papers/cs-thesis.pdf for details. interface CSBUDI { cipher: "CS"; cs_nonce: string; // Crockford Base32 encoded cs_blinded_c0: string; // Crockford Base32 encoded cs_blinded_c1: string; // Crockford Base32 encoded }
// Secret for blinding/unblinding. // An RSA blinding secret, which is basically // a 256-bit nonce, converted to Crockford Base32. type BUDIBlindingKeyP = string;
interface BlindedDonationReceiptSignaturesResponse { // Total amount over which all the blind signatures are signing. issued_amount: Amount; // Array of the blind signatures. blind_signatures: BlindedDonationReceiptSignature[]; }
type BlindedDonationReceiptSignature = | RSABlindedDonationReceiptSignature | CSBlindedDonationReceiptSignature;
interface RSABlindedDonationReceiptSignature { cipher: "RSA"; // (blinded) RSA signature blinded_rsa_signature: BlindedRsaSignature; }
interface CSBlindedDonationReceiptSignature { cipher: "CS"; // Signer chosen bit value, 0 or 1, used // in Clause Blind Schnorr to make the // ROS problem harder. b: Integer; // Blinded scalar calculated from c_b. s: Cs25519Scalar; }
interface DonationUnitUnknownError{ unknown_hash_pub_donation_unit: HashCode[]; donau_pub: EddsaPublicKey; donau_sig: EddsaSignature; }
interface DonationUnitExpiredMessage{ h_donation_unit_pub: HashCode; donau_pub: EddsaPublicKey; donau_sig: EddsaSignature; }
17.12.6. Donation statement#
Inspired by the Taler exchange Deposit.
Donation statement operations are requested by a donor.
- POST /batch-submit#
Send in donation receipts for the current or one of the past fiscal years. The donor will reveive the signed total back, which is called the donation statement.
Request: SubmitDonationReceiptsRequest
Response:
- 201 Created:
The request was successful, and a donation statement is now available. The response will be empty.
- 400 Bad Request:
The request body is malformed, required fields are missing, or the
donation_receiptsarray is empty or contains malformed entries. Returned with error codeTALER_EC_GENERIC_JSON_INVALIDorTALER_EC_GENERIC_PARAMETER_MALFORMED.- 403 Forbidden:
One of the donation receipt signatures is invalid. Returned with error code
TALER_EC_DONAU_DONATION_RECEIPT_SIGNATURE_INVALID.- 404 Not Found:
At least one of the donation unit keys is not known to the Donau. Returned with error code
TALER_EC_DONAU_GENERIC_DONATION_UNIT_UNKNOWN.- 409 Conflict:
A duplicate donor identifier nonce was detected within the submitted receipts. Returned with error code
TALER_EC_DONAU_DONOR_IDENTIFIER_NONCE_REUSE.- 500 Internal Server Error:
The Donau encountered an internal database error. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILED.
Details:
interface SubmitDonationReceiptsRequest{ // hashed taxpayer ID plus salt h_donor_tax_id: HashCode; // All donation receipts must be for this year. donation_year: Integer; // Receipts should be sorted by amount. donation_receipts: DonationReceipt[]; }
interface DonationReceipt { h_donation_unit_pub: HashCode; nonce: string; donation_unit_sig: DonationReceiptSignature; }
type DonationReceiptSignature = RSADonationReceiptSignature | CSDonationReceiptSignature ;
interface RSADonationReceiptSignature { cipher: "RSA"; // RSA signature rsa_signature: RsaSignature; }
interface CSDonationReceiptSignature { cipher: "CS"; // R value component of the signature. cs_signature_r: Cs25519Point; // s value component of the signature. cs_signature_s: Cs25519Scalar; }
- GET /donation-statement/$YEAR/$HASH_DONOR_ID#
Get the donation statement for a specific year and donor.
Request:
Response:
- 200 OK:
The request was successful, and the response is a DonationStatementResponse.
- 204 No Content:
No donation statement exists for the given year and donor.
- 400 Bad Request:
The
$YEARor$HASH_DONOR_IDin the URL is malformed. Returned with error codeTALER_EC_GENERIC_PARAMETER_MALFORMED.- 500 Internal Server Error:
The Donau encountered an internal error, such as a database failure or signing key unavailability. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILED,TALER_EC_DONAU_GENERIC_KEYS_MISSING, orTALER_EC_DONAU_SIGNKEY_HELPER_BUG.- 503 Service unavailable:
The donau is lacking the keys to create the donation statement. Returned with error code
TALER_EC_DONAU_GENERIC_KEYS_MISSING.
Details:
interface DonationStatementResponse { total: Amount; // signature over h_donor_tax_id, total, donation_year donation_statement_sig: EddsaSignature; // the corresponding public key to the signature donau_pub: EddsaPublicKey; }
17.12.7. Charity administration and status information#
The administration requests require an authorized bearer token to be set in the HTTP “Authorization” Header. This token can be set by a proxy validating authentication/authorization (using e.g. LDAP). The GET status requests require an authorized bearer token as well.
- GET /charities#
GET all charities. Only allowed if the request comes with the administration bearer token.
return all charities
Request:
Response:
- 200 OK:
The request was successful, and the response is a Charities.
- 204 No Content:
No charities are registered at this time.
- 403 Forbidden:
The request did not contain an accepted administrator bearer token in its header. Returned with error code
TALER_EC_GENERIC_TOKEN_PERMISSION_INSUFFICIENT.- 500 Internal Server Error:
The Donau encountered an internal database error. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILED.
Details:
interface Charities{ charities: CharitySummary[]; }
interface CharitySummary { // Unique ID of the charity within the Donau. charity_id: Integer; // Public key of the charity, used by the charity to // authorize issuing donation receipts. charity_pub: EddsaPublicKey; // Human-readable name of the charity. charity_name: string; // Maximum amount of donation receipts this charity is // allowed to issue per year. max_per_year: Amount; // Year for which receipts_to_date is given. current_year: Integer; // Total amount of donation receipts the donau has // issued for this charity so far this year. receipts_to_date: Amount; }
- GET /charity/$CHARITY_ID#
Request information about a specific charity. Only allowed if the request comes with a signature by the respective charity.
Request:
Charity-Signature:
The client must provide Base-32 encoded EdDSA signature with
$CHARITY_PRIV, affirming the desire to obtain the charity status. Note that this is merely a simple authentication mechanism, the details of the request are not protected by the signature. The$CHARITY_PRIVis usually the merchant instance private key.Response:
- 200 OK:
The Donau responds with a Charity object.
- 400 Bad Request:
The
$CHARITY_IDis malformed or the requiredCharity-Signatureheader is missing or cannot be parsed. Returned with error codeTALER_EC_GENERIC_PARAMETER_MALFORMEDorTALER_EC_GENERIC_PARAMETER_MISSING.- 403 Forbidden:
The charity signature provided in the
Charity-Signatureheader is invalid. Returned with error codeTALER_EC_GENERIC_FORBIDDEN.- 404 Not Found:
The charity ID does not belong to a charity known to the Donau. Returned with error code
TALER_EC_DONAU_CHARITY_NOT_FOUND.- 500 Internal Server Error:
The Donau encountered an internal database error. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILED.
interface Charity { charity_pub: EddsaPublicKey; name: string; url: string; max_per_year: Amount; receipts_to_date: Amount; current_year: Integer; }
- POST /charities#
Register a new charity with the Donau. Only allowed if the request comes with the administrator bearer token. The request body defines the charity’s signing key, contact information, and the initial accounting values for the current business year. On success the Donau assigns a numeric identifier to the charity record.
Request: CharityRequest
Response:
Details:
- 201 Created:
The request was successful, and the response is a CharityResponse.
- 400 Bad Request:
The request body is malformed or required fields are missing. Returned with error code
TALER_EC_GENERIC_JSON_INVALID.- 403 Forbidden:
The request did not contain an accepted administrator bearer token in its header. Returned with error code
TALER_EC_GENERIC_TOKEN_PERMISSION_INSUFFICIENT.- 409 Conflict:
A charity with the same public key already exists. Returned with error code
TALER_EC_DONAU_CHARITY_PUB_EXISTS.- 500 Internal Server Error:
The Donau encountered a database error while storing the charity. Returned with error code
TALER_EC_GENERIC_DB_STORE_FAILED.
interface CharityRequest { // Long-term EdDSA public key that identifies the charity. charity_pub: EddsaPublicKey; // Canonical URL that should be presented to donors. charity_url: string; // Human-readable display name of the charity. charity_name: string; // Allowed donation volume for the charity per calendar year. max_per_year: Amount; }
interface CharityResponse { // Unique ID assigned to the charity in the backend. charity_id: Integer; }
- PATCH /charities/{charity_id}#
Modify a charity. Only allowed if the request comes with the administrator bearer token.
Request:
CharityRequestResponse:
- 200 OK:
The update succeeded. The response body is empty.
- 400 Bad Request:
The request was malformed. For example, the
charity_idin the URL could not be parsed, required JSON fields are missing, ormax_per_yearis smaller than the currentreceipts_to_dateof the charity. Returned with error codeTALER_EC_GENERIC_PARAMETER_MALFORMEDorTALER_EC_GENERIC_JSON_INVALID.- 403 Forbidden:
The request did not contain an accepted administrator bearer token in its header. Returned with error code
TALER_EC_GENERIC_TOKEN_PERMISSION_INSUFFICIENT.- 404 Not Found:
The charity ID is unknown to the Donau. Returned with error code
TALER_EC_DONAU_CHARITY_NOT_FOUND.- 500 Internal Server Error:
The Donau encountered an internal database error. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILED,TALER_EC_GENERIC_DB_STORE_FAILED, orTALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE.
Details:
The request body has the same shape as CharityRequest used by
POST /charities. All fields are required and will replace the stored values of the charity.
- DELETE /charities/{charity_id}#
Delete (or deactivate) a charity. Only allowed if the request comes with the administrator bearer token.
Request:
Response:
- 204 No Content:
The request was successful and the charity has been deleted.
- 400 Bad Request:
The
charity_idin the URL could not be parsed. Returned with error codeTALER_EC_GENERIC_PARAMETER_MALFORMED.- 403 Forbidden:
The request did not contain an accepted administrator bearer token in its header. Returned with error code
TALER_EC_GENERIC_TOKEN_PERMISSION_INSUFFICIENT.- 500 Internal Server Error:
The Donau encountered an internal database error. Returned with error code
TALER_EC_GENERIC_DB_FETCH_FAILED.