Authentication
Every Oris API request requires HMAC-SHA256 signing. The SDKs handle this automatically. This page documents the underlying protocol for developers who make direct HTTP calls or build custom clients.
Required Headers
Every request must include these five headers. Missing or invalid headers produce a 401 Authentication failed response with no diagnostic detail.
| Header | Format | Description |
|---|---|---|
Authorization | oris_sk_live_... | Your API key. Identifies your developer account. |
X-Request-Signature | 64-char hex string | HMAC-SHA256 of the canonical request string. |
X-Timestamp | Unix epoch seconds | Current time. Must be within 30 seconds of server time. |
X-Nonce | 16-128 character string | Unique per request. Prevents replay attacks. |
X-Agent-ID | UUID | Required for agent-scoped endpoints. Optional for developer-only endpoints. |
POST and PATCH requests also include an Idempotency-Key header (UUID). The SDKs generate this automatically. For direct calls, generate a UUID v4 for each mutation request.
Canonical Request Format
The signature is computed over a canonical string that binds the timestamp, HTTP method, request path, and request body together. This prevents tampering with any component of the request.
| Component | Value | Example |
|---|---|---|
timestamp | Same value sent in X-Timestamp | 1711234567 |
METHOD | Uppercase HTTP method | POST |
path | Full path including /api/v1 prefix | /api/v1/oris/payments/send |
SHA-256(body) | Hex-encoded SHA-256 of the request body. For GET requests with no body, hash the empty string. | e3b0c44298fc... |
Key Derivation
When you register as a developer, you receive an api_key and api_secret. The signing key is derived from the secret using SHA-256. The server stores the same hash and computes the HMAC with it. The raw api_secret is never stored on the server and cannot be recovered.
Signature Computation
Timestamp Tolerance
The server accepts requests with timestamps within a 30-second window of the current server time. Requests outside this window are rejected with 401. This prevents replay attacks while allowing for reasonable clock drift.
Nonce Handling
Every request must include a unique nonce in the X-Nonce header. The server stores each nonce in Redis with a 30-second TTL using SETNX. If the same nonce appears within that window, the request is rejected. This provides replay protection for the duration of the timestamp tolerance window.
| Constraint | Value |
|---|---|
| Minimum length | 16 characters |
| Maximum length | 128 characters |
| TTL | 30 seconds |
| Storage | Redis SETNX (fail-closed) |
Verification Order
The server validates each request in strict sequential order. If any step fails, the request is immediately rejected with an opaque 401 error. No diagnostic information is returned to prevent information leakage.
| Step | Check | Failure |
|---|---|---|
| 1 | Authorization header format (oris_sk_live_ prefix) | 401 |
| 2 | Timestamp within 30-second tolerance | 401 |
| 3 | Nonce uniqueness (Redis SETNX) | 401 |
| 4 | Developer lookup by API key prefix | 401 |
| 5 | HMAC-SHA256 signature verification (timing-safe) | 401 |
| 6 | Rate limit check (Lua token bucket) | 429 |
Fail-Closed Design
If Redis is unavailable for nonce validation or rate limiting, the request is rejected. The system never falls back to an unauthenticated or unprotected state. Financial transactions require all security checks to pass.
"Authentication failed." for all 401 responses. It never discloses which specific check failed. This is intentional. If your requests are being rejected, verify each component (timestamp, nonce, signature) independently using the code examples on this page.
API Key Format
| Credential | Prefix | Length | Stored On Server |
|---|---|---|---|
| API Key | oris_sk_live_ | 12 + 43 chars (32 random bytes, URL-safe base64) | SHA-256 hash + 12-char prefix |
| API Secret | oris_ss_live_ | 12 + 64 chars (48 random bytes, URL-safe base64) | SHA-256 hash only |
Both credentials are shown exactly once during developer registration. The API secret cannot be recovered. If you lose it, you must rotate your key pair using the Developers API.
Key Rotation
Call POST /oris/developers/rotate-key to generate a new key pair. The old key is invalidated immediately. All active sessions using the old key will fail on their next request.