Authentication
Thiqwave uses two authentication mechanisms depending on the caller:
| Caller | Mechanism | Used for |
|---|---|---|
| Partner dashboard / admin | Keycloak JWT (Bearer token) | Managing applications, generating keys, partner onboarding |
| Server-to-server API calls | API Key (X-API-Key header) | Payment flows, transaction queries, webhooks |
Concepts
Partner
A Partner is the company that has signed up to Thiqwave. It represents your organization.
Application
An Application is a logical grouping of credentials for one product or integration. Each application belongs to a single environment — either TEST (testnet/sandbox) or LIVE (mainnet/production).
A typical partner setup:
Acme Corp (Partner)
├── "Payment Gateway" [TEST] → sandbox credentials
└── "Payment Gateway" [LIVE] → production credentials
See Environments for a full guide on the TEST/LIVE model.
API Key
An API Key (also called a client secret) is the credential used for machine-to-machine requests. It:
- Belongs to one Application and therefore one environment
- Is shown exactly once at creation — store it securely immediately
- Can be rotated at any time without downtime (create new, update app, revoke old)
- Has an optional expiry date
Getting Your API Key
1. Obtain a Keycloak token
Log in to the Thiqwave Dashboard or use the OAuth2 password flow for development:
TOKEN=$(curl -s -X POST \
http://localhost:8080/realms/thiqwave/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=partner-service" \
-d "username=you@company.com" \
-d "password=your-password" \
-d "grant_type=password" | jq -r '.access_token')
2. Register your company (once)
curl -X POST https://api.thiqwave.com/api/v1/auth/register \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"company_name": "Acme Corp",
"email": "dev@acme.com"
}'
3. Create an application
# Create a TEST application
curl -X POST https://api.thiqwave.com/api/v1/applications \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "My Payment App", "environment": "TEST" }'
Note the id in the response — you need it in the next step.
4. Generate an API key
curl -X POST https://api.thiqwave.com/api/v1/applications/<app-id>/keys \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
Response:
{
"api_key_id": "01970000-0000-7000-8000-bbbbbbbbbbbb",
"prefix": "a1b2c3d4",
"type": "TEST",
"expires_at": null,
"created_at": "2026-02-26T12:00:00.000Z",
"client_secret": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
}
The client_secret is returned once and never stored on our servers. Save it to a secrets manager before closing this response.
Making Authenticated Requests
Use the client_secret in the X-API-Key header for all API calls:
cURL
curl https://api.thiqwave.com/api/v1/transactions \
-H "X-API-Key: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
-H "Content-Type: application/json"
JavaScript / Node.js
const response = await fetch('https://api.thiqwave.com/api/v1/transactions', {
headers: {
'X-API-Key': process.env.THIQWAVE_API_SECRET,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
});
const data = await response.json();
Python
import os
import requests
headers = {
'X-API-Key': os.environ['THIQWAVE_API_SECRET'],
'Content-Type': 'application/json',
'Idempotency-Key': str(uuid.uuid4()),
}
response = requests.post(
'https://api.thiqwave.com/api/v1/transactions',
headers=headers,
json=payload,
)
Environment variable naming convention
# .env (never commit this)
THIQWAVE_TEST_SECRET=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
THIQWAVE_LIVE_SECRET=<your-live-secret>
Idempotency
All money-moving endpoints require an Idempotency-Key header. This prevents duplicate charges if a request is retried:
curl -X POST https://api.thiqwave.com/api/v1/transactions \
-H "X-API-Key: <your-secret>" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{ ... }'
Reusing the same Idempotency-Key within 24 hours returns the original response without creating a duplicate transaction.
API Key Security
Best Practices
- Store secrets in environment variables, never in source code
- Keep TEST and LIVE secrets in separate variables — never mix them
- Rotate keys every 90 days in production
- Use key expiry (
expires_at) for CI/CD pipelines and short-lived integrations - Revoke a key immediately if you suspect it has been exposed
- You can have multiple active keys per application, enabling zero-downtime rotation
Key Rotation (zero-downtime)
- Generate a new key for the application
- Update your application to use the new secret (deploy)
- Revoke the old key once traffic has drained
# Step 1: Generate new key
NEW_KEY=$(curl -s -X POST https://api.thiqwave.com/api/v1/applications/<app-id>/keys \
-H "Authorization: Bearer $TOKEN" \
-d '{}' | jq -r '.client_secret')
# Step 2: Deploy with new key, then...
# Step 3: Revoke old key
curl -X DELETE https://api.thiqwave.com/api/v1/applications/<app-id>/keys/<old-key-id> \
-H "Authorization: Bearer $TOKEN"
Rate Limits
API keys are subject to rate limits enforced at the Kong gateway:
| Limit | Value |
|---|---|
| Requests per minute | 100 |
| Requests per hour | 5,000 |
Enterprise plans have custom limits. Contact support to adjust.
Error Codes
| Status | Code | Description |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid API key |
403 | FORBIDDEN | Key is valid but lacks permission for this action |
403 | FORBIDDEN | Application is deactivated |
409 | CONFLICT | API key already revoked |
429 | RATE_LIMITED | Too many requests |