ORIS
Home Developers Authentication
lock Authentication

Authentication

Every request to the Oris API requires authentication. Sandbox calls need an API key. Production calls require an API key plus Ed25519 request signing.

API Key Authentication

All requests must include your API key in the Authorization header. Keys follow the format oris_sk_live_ for production and oris_sk_test_ for sandbox.

Authorization: Bearer oris_sk_live_...

Generate keys from API Keys in the developer dashboard. Each key is scoped to a single environment. Production keys cannot access sandbox data, and sandbox keys cannot access production data.

Ed25519 Request Signing

Production requests must include an Ed25519 signature for tamper protection. The server validates the signature before processing the request. Sandbox requests skip signature validation.

Include these headers alongside the Authorization header:

  • X-Request-Signature -- Ed25519 signature (128 hex chars) of the canonical string
  • X-Timestamp -- Unix epoch in seconds. Must be within 30 seconds of server time.
  • X-Nonce -- Unique token per request. The server rejects duplicate nonces within 30 seconds.

Signing Algorithm

Build the canonical string by concatenating these five components with dot separators:

1
Unix timestamp (same value as X-Timestamp)
2
Nonce (same value as X-Nonce)
3
HTTP method in uppercase (e.g. POST)
4
Request path (e.g. /api/v1/oris/agents)
5
SHA-256 hex digest of the request body (empty string hash for GET requests)

Canonical format: {timestamp}.{nonce}.{METHOD}.{path}.{SHA256(body)}

Sign the canonical string with your Ed25519 private key. Send the resulting hex digest as X-Request-Signature.

Code Example

A complete Python example that signs and sends a request:

auth_example.py
# Python SDK handles signing automatically
from oris import OrisClient

client = OrisClient(
    api_key="oris_sk_live_your_key_here",
    api_secret="oris_pk_live_your_private_key",
)

# SDK signs all requests automatically
agents = client.agents.list()

# Manual signing (direct HTTP)
import hashlib, time, uuid, json
from nacl.signing import SigningKey

api_key    = "oris_sk_live_..."
private_key = SigningKey(bytes.fromhex("..."))

method    = "POST"
path      = "/api/v1/oris/agents"
body      = json.dumps({"name": "payment-bot"})
timestamp = str(int(time.time()))
nonce     = str(uuid.uuid4())

body_hash = hashlib.sha256(body.encode()).hexdigest()
canonical = f"{timestamp}.{nonce}.{method}.{path}.{body_hash}"
signature = private_key.sign(canonical.encode()).signature.hex()

The Python and TypeScript SDKs handle signing automatically. Manual signing is only required for direct HTTP calls.

Rate Limits

Rate limits apply per API key. The server returns a 429 status code when the limit is exceeded. The Retry-After header indicates how many seconds to wait before retrying.

Plan Limit Window
Sandbox1,000 callsPer day
Growth1,000 callsPer minute
EnterpriseCustomCustom

Error Codes

Authentication failures return one of these HTTP status codes with a JSON error body:

Code Meaning Action
401Invalid or missing API keyCheck the Authorization header value
403Signature mismatchVerify the canonical string construction and private key
429Rate limit exceededWait for the duration in the Retry-After header