All Fipto API requests are signed with the HTTP Signatures protocol using RSA-SHA256 (algorithm hs2019). Generate your RSA key pair, register the public key in the Fipto app, and sign every request with the required headers.
All Fipto API requests are signed with the HTTP Signatures protocol using RSA-SHA256 (algorithm hs2019). This page walks through key generation, the required headers, the signing string and a worked example.
Quick facts
- Protocol: HTTP Signatures
- Algorithm: RSA-SHA256 (
hs2019)- Key size: 2048-bit RSA
- Required headers (all requests):
Host,Date,Signature- Required headers (POST/PUT/PATCH): plus
Content-TypeandDigest- Demo host:
api.demo.fipto.tech- Production host:
api.fipto.app
Before you start
Before you can authenticate, you need:
- A Fipto account in demo or production. See Get started with Fipto.
- An RSA key pair. Generate one in the next section.
- An API integration created in the Fipto web application (
Settings > API integrations) with your public key. Its Key ID is thekeyIdin every signature. Create one per environment, with a separate key pair for demo and production.
1. Generate an RSA key pair
Generate a 2048-bit RSA private key and a matching public key. The public key is the one you register in the Fipto web application; the private key never leaves your environment.
# Private key
openssl genrsa -out private-key.rsa 2048
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt \
-in private-key.rsa -out private-key.pem
# Public key
openssl rsa -in private-key.rsa -pubout -out public-key.pemIn the Fipto web application, go to Settings > API integrations, click Create integration and upload the public key file (public-key.pem in the example above) or paste its content. Once the integration is created, its Key ID is the keyId you use in every signed request.
2. Required headers
Every authenticated Fipto API request must include the following headers.
| Header | Required on | Value |
|---|---|---|
Host | All requests | api.demo.fipto.tech (demo) or api.fipto.app (production) |
Date | All requests | RFC 1123 timestamp, no older than one minute and not in the future |
Signature | All requests | Signature block (see step 4) |
Content-Type | POST, PUT, PATCH | MIME type of the body, typically application/json |
Digest | POST, PUT, PATCH | Base64-encoded SHA-256 of the body, prefixed with SHA-256= |
Generate the Digest header from the body. On Unix:
echo -n "$BODY" | openssl dgst -sha256 -binary | openssl enc -base64 -APrepend SHA-256= to that value to produce the final header.
3. Build the signing string
The signing string concatenates the (request-target) pseudo-header and every header you intend to sign, each on its own line, in the order they will appear in the headers field of the signature block.
For a POST request, the signing string looks like:
(request-target): post /companies/c240e5bf-863e-4f44-91aa-cc74a8b3303f/wallets
host: api.demo.fipto.tech
date: Fri, 24 Jan 2025 08:56:30 GMT
content-type: application/json
digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=Sign this string with your RSA private key using SHA-256, then base64-encode the result.
4. The Signature header
Place the base64-encoded signature inside the Signature header along with the other required fields.
Signature: keyId="<your-key-id>",algorithm="hs2019",headers="(request-target) host date content-type digest",signature="<base64-encoded-signature>"Field rules:
keyIdmust be the Key ID of your API integration (shown inSettings > API integrations).
algorithmmust behs2019(its synonymrsa-sha256is also accepted).headersmust list, in order:(request-target), then every header that appears in the signing string. For GET requests, omitcontent-typeanddigest.signatureis the base64-encoded RSA-SHA256 signature of the signing string.
Worked example: GET request
curl https://api.demo.fipto.tech/companies/$COMPANY_ID/wallets \
-H "Host: api.demo.fipto.tech" \
-H "Date: $(date -uR)" \
-H 'Signature: keyId="<your-key-id>",algorithm="hs2019",headers="(request-target) host date",signature="<base64-encoded-signature>"'Worked example: POST request with body
BODY='{"data":{"type":"wallet","attributes":{"name":"Merchant · Acme Corp","asset":"USDC_BASE"}}}'
DIGEST="SHA-256=$(echo -n "$BODY" | openssl dgst -sha256 -binary | openssl enc -base64 -A)"
curl https://api.demo.fipto.tech/companies/$COMPANY_ID/wallets \
-H "Host: api.demo.fipto.tech" \
-H "Date: $(date -uR)" \
-H "Content-Type: application/json" \
-H "Digest: $DIGEST" \
-H 'Signature: keyId="<your-key-id>",algorithm="hs2019",headers="(request-target) host date content-type digest",signature="<base64-encoded-signature>"' \
-d "$BODY"A working Postman collection that signs requests for you is available in the Postman collection guide.
Common errors
| HTTP status | Likely cause | Fix |
|---|---|---|
| 401 Unauthorized | keyId does not match a registered key | Check the Key ID in Settings > API integrations and that the integration uses your current public key |
| 401 Unauthorized | Date header is older than one minute or in the future | Sync your clock; regenerate the request |
| 401 Unauthorized | Signing string mismatch | Reproduce the exact byte order of headers in headers= |
| 400 Bad Request with Digest mismatch | Digest does not match the body | Recompute the base64 SHA-256 of the actual transmitted body |
| 415 Unsupported Media Type | Missing Content-Type on a POST | Always set Content-Type: application/json for JSON bodies |
Frequently asked questions
What algorithm does Fipto use for HTTP Signatures?
RSA-SHA256, declared as hs2019 (also accepted as rsa-sha256).
How do I authenticate Fipto API requests in Python or Node?
Use any library that implements the HTTP Signatures draft. In Python, requests-http-signature works. In Node, http-signature by TJ Fontaine is the reference. The Fipto Postman collection also includes a JavaScript pre-request script you can adapt.
Do I need a new key pair for demo and production?
Yes, we strongly recommend it. Reusing the same key pair is technically possible but bad practice: keep a separate key pair and API integration per environment so a test request can never act on your live company.
How long is a signed request valid?
Up to one minute after the time in its Date header. A Date older than one minute, or set in the future even by a few seconds, is rejected. Keep your clock synchronised (NTP).
What does Fipto support: HMAC or RSA signatures?
RSA only, via HTTP Signatures with the hs2019 algorithm.
