Authentication
The Banking API uses EdDSA Proof-of-Possession (PoP) authentication. This cryptographic method ensures that requests are signed by the legitimate owner of the service account’s private key and prevents replay attacks.Overview
Unlike traditional API key or OAuth authentication, PoP authentication requires you to cryptographically sign each request. This provides:- Non-repudiation - Requests can be proven to originate from your service account
- Replay protection - Timestamps prevent reuse of captured requests
- IP binding - Requests are validated against your configured IP allowlist
Prerequisites
Before making API requests, you need:- Service Account - Created in your Conta Digital dashboard
- Ed25519 Key Pair - Generate a public/private key pair
- Registered Public Key - Upload your public key to your service account
- IP Allowlist - Configure allowed IP addresses for your service account
Required Headers
Every authenticated request must include these 5 headers:| Header | Description | Example |
|---|---|---|
x-access-id | Your service account UUID | 550e8400-e29b-41d4-a716-446655440000 |
X-PoP-Signature | EdDSA signature (base64) | MEUCIQDx... |
X-PoP-Challenge | Unix timestamp in milliseconds | 1705423200000 |
X-PoP-Format | Authentication type identifier | service-account |
true-client-ip | Your client’s IP address | 203.0.113.50 |
Signature Process
The signature is created by signing a specific message format with your Ed25519 private key.Step 1: Construct the Message
Concatenate the following values separated by colons (:):
| Component | Description |
|---|---|
uri | Full request path including query string (e.g., /v1/account?include=balance) |
method | HTTP method in uppercase (e.g., GET, POST) |
body | Request body as string, or empty string for GET requests |
timestamp | Same value as X-PoP-Challenge header |
Step 2: Sign the Message
Sign the message using your Ed25519 private key and encode the signature in base64.Step 3: Set Headers
Include the signature and all required headers in your request.Code Examples
Node.js
Python
cURL (with pre-computed signature)
Timestamp Validation
TheX-PoP-Challenge timestamp must be within 5 minutes of the server’s current time. This prevents replay attacks while allowing for reasonable clock drift.
IP Allowlist
Thetrue-client-ip header value must match one of the IP addresses configured in your service account’s allowlist. This provides an additional layer of security.
To configure your IP allowlist:
- Go to your Conta Digital dashboard
- Navigate to Settings > Service Accounts
- Edit your service account
- Add allowed IP addresses (IPv4 or IPv6)
Troubleshooting
Common Errors
401 - Invalid signature
401 - Invalid signature
Cause: The signature doesn’t match the expected value.Solutions:
- Verify you’re signing the exact message format:
{uri}:{method}:{body}:{timestamp} - Ensure the URI includes the full path and query string
- Check that the body string matches exactly what you’re sending
- Verify your private key corresponds to the public key registered with your service account
401 - Timestamp expired
401 - Timestamp expired
Cause: The
X-PoP-Challenge timestamp is more than 5 minutes from server time.Solutions:- Sync your system clock using NTP
- Generate the timestamp immediately before making the request
- Ensure you’re using milliseconds, not seconds
403 - IP not allowed
403 - IP not allowed
Cause: The
true-client-ip doesn’t match your service account’s IP allowlist.Solutions:- Verify your current public IP address
- Update your service account’s IP allowlist in the dashboard
- If behind a proxy/NAT, use the external IP address
401 - Invalid access ID
401 - Invalid access ID
Cause: The
x-access-id doesn’t match any active service account.Solutions:- Verify the service account UUID is correct
- Ensure the service account is active and not disabled
- Check for typos or extra whitespace
Debugging Tips
- Log the message before signing - Print the exact string being signed to verify format
- Test with a known good signature - Use test vectors to verify your signing implementation
- Check response headers - Error responses may include additional debug information
- Verify key format - Ed25519 private keys should be 32 bytes (64 hex characters)
Security Best Practices
Protect Your Private Key
Never expose your private key in client-side code, logs, or version control. Use environment variables or secure secret management.
Rotate Keys Regularly
Generate new key pairs periodically and update your service account. Revoke old keys after rotation.
Minimize IP Allowlist
Only allow IPs that genuinely need API access. Use specific IPs rather than wide CIDR ranges.
Monitor API Usage
Regularly review your API access logs for unexpected patterns or unauthorized attempts.
