Skip to content

API Reference

Base URL: https://api.nanorix.io EU Base URL: https://api.nanorix.eu

All request and response bodies use JSON. Authentication uses Bearer tokens in the Authorization header.


Authentication

Authenticated endpoints require:

Authorization: Bearer nrx_live_...

The API key is issued at signup and cannot be retrieved later. Nanorix stores only a SHA-256 hash.

Rate Limits by Tier

Tier Requests/min Concurrent Sessions Max TTL
Free 60 3 5 min
Starter 120 20 10 min
Business 300 100 30 min
Enterprise Custom Custom Unlimited

Endpoints

POST /v1/signup

Create a new customer account. Public, rate limited to 10 requests/min per IP.

Request:

{
  "email": "you@company.com",
  "jurisdiction": "US"
}
Field Type Required Description
email string yes Valid email address
jurisdiction string no US (default), EU, UK, CA, AU, IN, OTHER

Response (201):

{
  "customer_id": "cust_8a3f...",
  "api_key": "nrx_live_...",
  "tier": "free",
  "message": "Save your API key — it cannot be retrieved later."
}

Errors: 400 invalid email, 409 email already registered, 429 rate limited.


POST /v1/sessions

Create an ephemeral session. Requires authentication.

Request:

{
  "data_classification": "PHI"
}
Field Type Required Description
data_classification string no general (default), PHI, PII, financial, credentials

Response (201):

{
  "session_id": "sess_a8f3e71c...",
  "status": "active",
  "ttl_seconds": 300,
  "created_at": "2026-03-01T14:00:00Z"
}

Errors: 401 unauthorized, 402 quota exceeded (free tier: 100 CDPs/month), 429 rate limited.


GET /v1/sessions/:id

Get session status. Requires authentication. Must own the session.

Response (200):

{
  "session_id": "sess_a8f3e71c...",
  "status": "active",
  "ttl_seconds": 300,
  "created_at": "2026-03-01T14:00:00Z",
  "data_classification": "PHI"
}

Session statuses: active, executing, destroyed, expired, expired_unclean.


POST /v1/sessions/:id/exec

Execute a command inside the session. Requires authentication.

Request:

{
  "command": "python classify.py",
  "input_data": "{\"record\": \"...\"}",
  "timeout": 30
}
Field Type Required Description
command string yes Command to execute inside the sandbox
input_data string no Data written to {tmpfs}/input/data before execution
timeout integer no Seconds before SIGTERM. Defaults to session TTL

Response (200):

{
  "output": "classification: chronic_condition",
  "stderr": "",
  "exit_code": 0,
  "timed_out": false
}

Use input_data, not command-line arguments

Pass sensitive data via the input_data field, not in the command string. Command-line arguments are visible in /proc/PID/cmdline. The input_data field writes to a file inside the sealed sandbox.


DELETE /v1/sessions/:id

Destroy the session and generate a CDP. Requires authentication.

Response (200):

{
  "session_id": "sess_a8f3e71c...",
  "status": "destroyed",
  "cdp": {
    "cdp_version": "1.0",
    "...": "see CDP Specification"
  },
  "regulatory_context": { "...": "..." },
  "session_context": {
    "jurisdiction": "US",
    "data_classification": "PHI"
  }
}

This is the primary response. The full CDP JSON format is documented in the CDP Specification.


GET /v1/proofs/:session_id

Retrieve a stored CDP for a destroyed session. Requires authentication. Must own the session.

Response (200): The stored CDP JSON, identical to what was returned in the DELETE response.

Errors: 401 unauthorized, 404 session not found or not yet destroyed.


GET /v1/customers/me

Get your account details, usage, and limits. Requires authentication.

Response (200):

{
  "customer_id": "cust_8a3f...",
  "email": "you@company.com",
  "tier": "free",
  "jurisdiction": "US",
  "cdps_this_cycle": 12,
  "cdp_limit": 100,
  "sessions_used": 2,
  "sessions_limit": 3,
  "rate_limit_rpm": 60,
  "billing_cycle_start": "2026-03-01T00:00:00Z",
  "api_key_prefix": "nrx_live_a1b2"
}

POST /v1/verify

Stateless CDP verification. Public, no authentication required. Rate limited to 60 requests/min per IP.

Request: A CDP JSON document as the request body.

Response (200):

{
  "valid": true,
  "checks": {
    "chain_integrity": true,
    "final_hash": true,
    "signature": true,
    "step_count": 8
  }
}

Nothing is stored. The CDP is verified and discarded.


GET /v1/keys/:id

Retrieve an Ed25519 public key. Public, no authentication required. Used for Level 2 provenance verification.

Response (200):

{
  "key_id": "nrx-verify-20260301T143000Z-a8f3e71c",
  "algorithm": "Ed25519",
  "public_key": "base64:MCowBQYDK2Vw...",
  "created_at": "2026-03-01T14:30:00Z"
}

GET /v1/health

Health check. Public.

Response (200):

{
  "status": "healthy",
  "engines": { "eee": true, "dire": true, "rzl": true, "fgx": true, "ave": true },
  "database": true,
  "uptime_seconds": 86400,
  "timestamp": "2026-03-09T12:00:00Z"
}

POST /v1/billing/checkout

Upgrade to a paid tier. Requires authentication. Redirects to Stripe Checkout.

Request:

{
  "tier": "starter"
}

Response (200):

{
  "checkout_url": "https://checkout.stripe.com/..."
}

Error Format

All errors return a consistent JSON format:

{
  "error": "QuotaExceeded",
  "message": "Free tier limit of 100 CDPs/month exceeded. Upgrade to continue.",
  "status": 402
}

Common Error Codes

Status Error Description
400 BadRequest Invalid request body or parameters
401 Unauthorized Missing or invalid API key
402 QuotaExceeded Free tier CDP limit reached
404 NotFound Session or resource not found
409 Conflict Resource already exists (e.g., duplicate email)
429 RateLimited Too many requests — retry after the indicated period
500 InternalError Server error — contact support