Authentication
Thiqwave uses two authentication mechanisms depending on the caller:
| Caller | Mechanism | Used for |
|---|---|---|
| Partner dashboard / admin | Bearer token (JWT) | 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 dashboard token
Sign in to the Thiqwave Dashboard to manage applications and keys interactively. To script the same steps, exchange your dashboard credentials at the OAuth2 token endpoint for your environment:
TOKEN=$(curl -s -X POST "$THIQWAVE_AUTH_URL/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=partner-console" \
-d "username=you@company.com" \
-d "password=your-password" \
-d "grant_type=password" | jq -r '.access_token')
THIQWAVE_AUTH_URL is issued with your onboarding pack. The resulting bearer token is used only for application and key management — never for payment calls, which use X-API-Key.
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"
}
:::danger Store the secret immediately
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 API gateway:
| Limit | Value |
|---|---|
| Requests per minute | 100 |
| Requests per hour | 5,000 |
Enterprise plans have custom limits. Contact support to adjust.
Error Codes
Authentication failures use the standard error envelope:
| Status | Code | Description |
|---|---|---|
401 | ATH_0001 | Missing or invalid API key |
403 | ATH_0002 | Key is valid but lacks permission for this action |
403 | ATH_0002 | Application is deactivated |
Revoked-key conflicts (409) and rate limiting (429) return the same envelope. See Errors for the full code list and Idempotency & Rate Limits for throttling behaviour.