REST API Reference
All endpoints are served over HTTPS at /api/v1/. Authenticated endpoints require Authorization: Bearer <token>.
Token types: API tokens (arc_ prefix, persistent), JWT tokens (24h, from login), SSO tokens (from OIDC/SAML/LDAP callback).
Quick Example
Store and retrieve a secret (Python)
import urllib.request, json, ssl
ARCAN = "https://localhost:8443"
TOKEN = "arc_your_token_here"
ctx = ssl._create_unverified_context() # self-signed cert
# Store a secret
data = json.dumps({"key": "DATABASE_URL", "value": "postgres://prod:5432/app", "environment": "prod"}).encode()
req = urllib.request.Request(f"{ARCAN}/api/v1/realms/default/secrets", data=data,
headers={"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"})
resp = urllib.request.urlopen(req, context=ctx)
print("Stored:", json.load(resp)["key"])
# Retrieve it
req = urllib.request.Request(f"{ARCAN}/api/v1/realms/default/secrets/DATABASE_URL?env=prod",
headers={"Authorization": f"Bearer {TOKEN}"})
resp = urllib.request.urlopen(req, context=ctx)
secret = json.load(resp)
print("Value:", secret["value"])
Store and retrieve a secret (Go)
package main
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"net/http"
)
func main() {
arcan := "https://localhost:8443"
token := "arc_your_token_here"
client := &http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}
// Store a secret
body, _ := json.Marshal(map[string]string{
"key": "DATABASE_URL", "value": "postgres://prod:5432/app", "environment": "prod",
})
req, _ := http.NewRequest("POST", arcan+"/api/v1/realms/default/secrets", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, _ := client.Do(req)
defer resp.Body.Close()
fmt.Println("Stored, status:", resp.Status)
// Retrieve it
req, _ = http.NewRequest("GET", arcan+"/api/v1/realms/default/secrets/DATABASE_URL?env=prod", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, _ = client.Do(req)
defer resp.Body.Close()
var secret map[string]interface{}
json.NewDecoder(resp.Body).Decode(&secret)
fmt.Println("Value:", secret["value"])
}
Generate dynamic credentials (curl)
# Generate a short-lived PostgreSQL credential
curl -sk -X POST https://localhost:8443/api/v1/realms/myapp/engines/postgres/generate \
-H "Authorization: Bearer arc_your_token" \
-H "Content-Type: application/json" \
-d '{"ttl": "1h", "config": {"host": "db.internal", "port": 5432, "admin_user": "arcan"}}'
Response:
{
"username": "arcan-a7f3b2c1",
"password": "xK9m2pL4qR...",
"ttl": "1h",
"expires_at": "2026-04-06T13:00:00Z"
}
The generated credentials are temporary — they expire automatically after the TTL and are revoked from the database.
Error Format
{
"error": {
"code": "not_found",
"message": "realm not found -- list realms with: arcan realm list",
"status": 404
}
}
Endpoints
Health
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/health | No | Server status, version, component health |
Auth
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/auth/register | No | Create user account (email, password, name) |
| POST | /api/v1/auth/login | No | Login with email/password, returns JWT |
| GET | /api/v1/auth/providers | No | List configured SSO providers |
SSO
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/auth/oidc/{provider}/login | No | Initiate OIDC login (302 redirect) |
| GET | /api/v1/auth/oidc/{provider}/callback | No | OIDC callback, returns JWT |
| GET | /api/v1/auth/saml/{provider}/login | No | Initiate SAML login (302 redirect) |
| POST | /api/v1/auth/saml/{provider}/acs | No | SAML assertion consumer service |
| GET | /api/v1/auth/saml/{provider}/metadata | No | SAML SP metadata XML |
| POST | /api/v1/auth/ldap/{provider}/login | No | LDAP login (username/password) |
Tokens
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/auth/tokens | Yes | Create API token (name, scopes) |
| GET | /api/v1/auth/tokens | Yes | List API tokens |
| DELETE | /api/v1/auth/tokens/{id} | Yes | Revoke a token |
Realms
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/realms | Yes | Create realm (slug, name) |
| GET | /api/v1/realms | Yes | List all realms |
| GET | /api/v1/realms/{slug} | Yes | Get realm details |
| DELETE | /api/v1/realms/{slug} | Yes (admin) | Soft-delete realm |
Secrets
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/realms/{slug}/secrets | Yes | Store a secret (key, value, environment) |
| GET | /api/v1/realms/{slug}/secrets | Yes | List secrets (filter by ?env=) |
| GET | /api/v1/realms/{slug}/secrets/{key} | Yes | Get a secret (filter by ?env=) |
| DELETE | /api/v1/realms/{slug}/secrets/{key} | Yes | Delete a secret (filter by ?env=) |
| POST | /api/v1/encrypt | Yes | Encrypt a plaintext value |
Store a secret
curl -sk -X POST https://localhost:8443/api/v1/realms/myapp/secrets \
-H "Authorization: Bearer arc_your_token" \
-H "Content-Type: application/json" \
-d '{"key": "API_KEY", "value": "sk-abc123", "environment": "prod"}'
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"key": "API_KEY",
"value": "sk-abc123",
"environment": "prod",
"version": 1,
"created_at": "2026-04-06T12:00:00Z"
}
Get a secret
curl -sk https://localhost:8443/api/v1/realms/myapp/secrets/API_KEY?env=prod \
-H "Authorization: Bearer arc_your_token"
List all secrets
curl -sk https://localhost:8443/api/v1/realms/myapp/secrets?env=prod \
-H "Authorization: Bearer arc_your_token"
Response:
{
"secrets": [
{"key": "API_KEY", "value": "sk-abc123", "environment": "prod", "version": 1},
{"key": "DATABASE_URL", "value": "postgres://...", "environment": "prod", "version": 3}
]
}
Engines
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/engines | Yes | List registered engine types |
| POST | /api/v1/realms/{slug}/engines/{type}/generate | Yes | Generate dynamic credentials |
| POST | /api/v1/realms/{slug}/engines/{type}/validate | Yes | Validate credentials via engine |
Policy
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/policy/roles | Yes | List roles and capabilities |
| POST | /api/v1/realms/{slug}/policy/bindings | Yes (admin) | Assign role to user |
| GET | /api/v1/realms/{slug}/policy/bindings | Yes | List role bindings |
| DELETE | /api/v1/realms/{slug}/policy/bindings/{userID} | Yes (admin) | Remove role binding |
ESO (External Secrets Operator)
Simplified endpoints for the Kubernetes External Secrets Operator webhook provider. Returns only secret values (not full secret objects) so ESO can extract them with jsonPath: $.value.
Default environment is prod (not dev) since ESO typically targets production clusters.
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/eso/{realm}/{key} | Yes | Get a single secret value |
| GET | /api/v1/eso/{realm} | Yes | Bulk fetch all secrets in realm |
Query parameters: ?env= (default prod)
Get single secret
curl -sk https://localhost:8443/api/v1/eso/myapp/DATABASE_URL?env=prod \
-H "Authorization: Bearer arc_your_token"
Response:
{"value": "postgres://user:pass@db:5432/myapp"}
Bulk fetch
curl -sk https://localhost:8443/api/v1/eso/myapp?env=prod \
-H "Authorization: Bearer arc_your_token"
Response:
{
"data": {
"DATABASE_URL": "postgres://user:pass@db:5432/myapp",
"API_KEY": "sk-abc123",
"REDIS_URL": "redis://cache:6379"
}
}
See External Secrets Operator Integration for Kubernetes setup.
Audit
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/v1/audit/events | Yes | Query audit log |
Query parameters: ?realm=, ?type=, ?actor=, ?limit= (default 50)
curl -sk "https://localhost:8443/api/v1/audit/events?realm=myapp&type=secret.set&limit=10" \
-H "Authorization: Bearer arc_your_token"
Metrics
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /metrics | No | Prometheus metrics |
Available metrics: arcan_http_requests_total, arcan_secrets_total, arcan_auth_attempts_total.