Authentication
All API requests require authentication using an API key. The key must be included in the Authorization header of every request using the Bearer token scheme. Unauthenticated requests return a 401 Unauthorized error.
Authentication Method
Martis uses Bearer token authentication. Include the API key in the Authorization header:
Authenticated request
curl https://api-staging.martis.id/api/v1/payments/charges \
--header 'Authorization: Bearer {API_KEY}' \
--header 'Content-Type: application/json'
Header Format
Authorization: Bearer <API_KEY>
Replace <API_KEY> with the secret key obtained from the dashboard. See API Keys for key generation instructions.
Environment-Specific Authentication
API keys are scoped to specific environments. Requests must use the correct API key for the target environment.
| Environment | Base URL | Key Required |
|---|---|---|
| Sandbox | https://api-staging.martis.id | Sandbox API key |
| Production | https://api.martis.id | Production API key |
Using a sandbox key with the production API (or vice versa) results in a 401 Unauthorized response.
Error Responses
Authentication failures return one of the following responses:
401 Unauthorized
Returned when the API key is missing, invalid, or expired.
Response 401
{
"status": "error",
"message": "Invalid or missing API key"
}
Common causes:
- Missing
Authorizationheader - Incorrect API key
- Revoked API key
- Environment mismatch (sandbox key used with production API)
403 Forbidden
Returned when the API key is valid but lacks permission for the requested action.
Response 403
{
"status": "error",
"message": "Insufficient permissions for this action"
}
Common causes:
- API key lacks required feature access
- Account not activated for the requested operation
- IP address not in the allowlist (when IP restrictions are enabled)
Security Best Practices
Key Protection
- Server-side only — Never include API keys in client-side code, mobile apps, or browser JavaScript
- Environment variables — Store keys in environment variables, not in source code
- Secrets management — Use a dedicated secrets manager for production environments
- Version control — Never commit API keys to repositories; use
.gitignoreto exclude environment files
Access Control
- Minimal permissions — Request only the access levels required for each integration
- Separate keys — Use different API keys for different services or environments
- Regular rotation — Rotate keys periodically (recommended: every 90 days)
- Prompt revocation — Revoke keys immediately upon suspected compromise
Network Security
- HTTPS only — All API requests must use HTTPS; HTTP requests are rejected
- IP restrictions — Configure IP allowlists for production API keys
- Request logging — Monitor API usage for unusual patterns
Request Example
A complete authenticated request includes the Authorization header and appropriate content headers:
Required Headers
- Name
Authorization- Type
- string
- Description
Bearer token containing the API key
- Name
Content-Type- Type
- string
- Description
application/jsonfor requests with a body
Complete request example
curl https://api-staging.martis.id/api/v1/payments/charges \
--request POST \
--header 'Authorization: Bearer sk_test_abc123xyz...' \
--header 'Content-Type: application/json' \
--data '{
"payment_method": "qris",
"channel": "gudang_voucher",
"amount": 50000,
"currency": "idr",
"customer_details": {
"email": "customer@example.com"
}
}'
SDK Authentication
When using official SDKs, configure the API key during client initialization:
SDK initialization
const martis = require('martis')({
apiKey: process.env.MARTIS_API_KEY,
environment: 'sandbox' // or 'production'
});
Troubleshooting
| Issue | Solution |
|---|---|
401 Unauthorized on every request | Verify the API key is correct and not revoked |
401 in production but works in sandbox | Ensure a production API key is being used |
403 Forbidden after successful auth | Check account permissions and feature activation |
Intermittent 401 errors | Verify the Authorization header is included in all requests |
401 from specific IPs only | Check IP restriction settings on the API key |