Register a new organization and its owner.
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| organizationName | string | Yes | 2-120 chars | Name of the organization |
| name | string | Yes | 1-120 chars | Full name of the owner |
| string | Yes | Valid email | Owner's email address | |
| password | string | Yes | 8-200 chars | Secure password |
Response: TokenPairDto
| Field | Type | Description |
|---|---|---|
| accessToken | string | JWT access token |
| refreshToken | string | JWT refresh token |
| expiresIn | number | Access token lifetime in seconds (default: 900) |
| tokenType | string | Token type (optional) |
Authenticate with email and password.
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| string | Yes | Valid email | User's email address | |
| password | string | Yes | Non-empty | User's password |
Response: TokenPairDto
Rotate an access/refresh token pair.
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| refreshToken | string | Yes | Non-empty | Valid refresh token |
Response: TokenPairDto
Revoke the current session.
Authentication: Bearer token required
Response: Success message
Get the current authenticated user.
Authentication: Bearer token required
Response: User profile information
Get the current session principal (alias for /auth/me).
Authentication: Bearer token required
Response: User profile information
Begin WebAuthn passkey registration.
Status: Not implemented - requires @simplewebauthn/server package
Verify a WebAuthn passkey assertion.
Status: Not implemented - requires @simplewebauthn/server package
List wallets for the organization.
Query Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
Authentication: Bearer token required
Response: Paginated list of wallets
Create a wallet (generate a keypair or import an address).
Authentication: Requires roles: OWNER, ADMIN, FINANCE, DEVELOPER
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| label | string | No | Max 120 chars | Wallet label/name |
| walletType | enum | No | AGENT, OPERATIONAL, TREASURY | Type of wallet (default: AGENT) |
| network | enum | No | TESTNET, PUBLIC | Stellar network (default: TESTNET) |
| agentId | string | No | Valid UUID | Owning agent ID |
| stellarAddress | string | No | Non-empty | Import existing address (if provided, no keypair is generated) |
Response: WalletSecretDto (on generation) or wallet object (on import)
| Field | Type | Description |
|---|---|---|
| stellarAddress | string | Public Stellar address (G...) |
| secretKey | string | Generated secret key (S...) - shown ONCE, never stored |
Get a specific wallet.
Authentication: Bearer token required
Response: Wallet details
Fetch live on-chain balances for a wallet.
Authentication: Bearer token required
Response: Balance information for all assets
Update a wallet label or owning agent.
Authentication: Requires roles: OWNER, ADMIN, FINANCE, DEVELOPER
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| label | string | No | Max 120 chars | New wallet label |
| agentId | string | No | Valid UUID or null | Reassign or clear owning agent |
Response: Updated wallet object
Freeze a wallet (block outgoing transactions).
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Response: Updated wallet with FROZEN status
Unfreeze a wallet.
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Response: Updated wallet with ACTIVE status
Archive (soft-delete) a wallet.
Authentication: Requires roles: OWNER, ADMIN
Response: Success message
List transactions for the organization.
Query Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
Authentication: Bearer token required
Response: Paginated list of transactions
Create a transaction (runs the full governance pipeline).
Authentication: Requires roles: OWNER, ADMIN, FINANCE, DEVELOPER
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| walletId | string | Yes | Valid UUID | Sender wallet ID |
| agentId | string | No | Valid UUID | Initiating agent ID |
| budgetId | string | No | Valid UUID | Budget to charge against |
| asset | string | No | 1-24 chars | Asset code (default: XLM) |
| amount | string | Yes | Positive decimal, max 7 decimal places | Transaction amount |
| recipientAddress | string | Yes | Non-empty | Stellar destination address |
| memo | string | No | Max 28 chars | Transaction memo |
| purpose | string | No | Max 280 chars | Transaction purpose |
| metadata | object | No | Arbitrary JSON | Additional metadata |
Response: Transaction object with governance evaluation result
Dry-run the governance pipeline without moving funds.
Authentication: Bearer token required
Request Body: Same as POST /transactions
Response: Simulation result with policy evaluation
Get a specific transaction.
Authentication: Bearer token required
Response: Transaction details
Cancel a draft or pending transaction.
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Response: Updated transaction with CANCELLED status
List policies for the organization.
Query Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
Authentication: Bearer token required
Response: Paginated list of policies
Create a policy.
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| name | string | Yes | 1-120 chars | Policy name |
| description | string | No | Max 500 chars | Policy description |
| type | enum | Yes | SPENDING_LIMIT, ASSET_RESTRICTION, APPROVAL_WORKFLOW, TIME_WINDOW, EMERGENCY_LOCK | Policy type |
| agentId | string | No | Valid UUID | Scope policy to specific agent |
| configuration | object | No | Valid policy configuration | Policy-specific settings (see below) |
| priority | number | No | 0-1000 | Evaluation priority (default: 100) |
| enabled | boolean | No | - | Policy active state (default: true) |
Configuration Schema:
| Field | Type | Description |
|---|---|---|
| maxAmount | number | Maximum single transaction amount |
| minAmount | number | Minimum single transaction amount |
| allowedAssets | string[] | List of allowed asset codes |
| blockedAssets | string[] | List of blocked asset codes |
| allowedRecipients | string[] | List of allowed recipient addresses |
| blockedRecipients | string[] | List of blocked recipient addresses |
| dailyLimit | number | Daily spending limit |
| weeklyLimit | number | Weekly spending limit |
| monthlyLimit | number | Monthly spending limit |
| timeWindow | object | Allowed time window (startHour, endHour, days) |
| requiresApproval | boolean | Whether approval is required |
| approvalThreshold | number | Amount threshold for approval |
| emergencyLock | boolean | Emergency lock flag (blocks all spending) |
Response: Created policy object
Simulate a transaction intent against active policies.
Authentication: Bearer token required
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| agentId | string | No | Valid UUID | Agent ID |
| walletId | string | No | Valid UUID | Wallet ID |
| asset | string | Yes | Non-empty | Asset code |
| amount | number | Yes | Positive | Transaction amount |
| recipientAddress | string | Yes | Non-empty | Destination address |
| spentToday | number | No | Non-negative | Amount spent today |
| spentThisWeek | number | No | Non-negative | Amount spent this week |
| spentThisMonth | number | No | Non-negative | Amount spent this month |
Response: Policy evaluation result
Get a specific policy.
Authentication: Bearer token required
Response: Policy details
Update a policy.
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Request Body: Partial update of POST /policies body
Response: Updated policy object
Delete (soft-delete) a policy.
Authentication: Requires roles: OWNER, ADMIN
Response: Success message
List budgets for the organization.
Query Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number (default: 1) |
| limit | number | No | Items per page (default: 10) |
Authentication: Bearer token required
Response: Paginated list of budgets
Create a budget.
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Request Body:
| Field | Type | Required | Constraints | Description |
|---|---|---|---|---|
| name | string | Yes | 1-120 chars | Budget name |
| period | enum | Yes | DAILY, WEEKLY, MONTHLY | Budget period |
| limit | number | Yes | Positive | Budget limit amount |
| asset | string | Yes | 1-24 chars | Asset code |
| walletId | string | No | Valid UUID | Associated wallet |
| agentId | string | No | Valid UUID | Associated agent |
| resetDate | date | No | Valid date | Custom reset date |
Response: Created budget object
Get a specific budget.
Authentication: Bearer token required
Response: Budget details with current usage
Update a budget.
Authentication: Requires roles: OWNER, ADMIN, FINANCE
Request Body: Partial update of POST /budgets body
Response: Updated budget object
Delete a budget.
Authentication: Requires roles: OWNER, ADMIN
Response: Success message
The liveness and readiness probes are served outside the API prefix, so orchestrator and load-balancer probe paths do not change with the API version. Both are public, exempt from rate limiting, excluded from the audit trail, and return raw JSON (no success envelope).
Liveness probe. Returns 200 whenever the process is running. It performs no
dependency checks, so a database or cache outage never causes an otherwise
healthy process to be restarted.
Authentication: Public
Response (200):
{ "status": "up", "timestamp": "2026-09-28T10:00:00.000Z", "uptimeSeconds": 42 }Readiness probe. Probes the database (SELECT 1) and cache (Redis PING) in
parallel, each bounded by a 2 second timeout. Returns 200 when every
dependency is up and 503 when any is down.
Authentication: Public
Response (503 example):
{
"status": "down",
"timestamp": "2026-09-28T10:00:00.000Z",
"services": {
"database": {
"status": "down",
"latencyMs": 2001,
"timestamp": "2026-09-28T10:00:00.000Z",
"error": "Database health check timed out after 2000ms"
},
"cache": { "status": "up", "latencyMs": 1, "timestamp": "2026-09-28T10:00:00.000Z" }
}
}Richer diagnostics (including Stellar and migration status) remain available
under the API prefix at GET /{API_PREFIX}/health/readiness,
GET /{API_PREFIX}/health/liveness and GET /{API_PREFIX}/health/database.
| Field | Type | Default | Description |
|---|---|---|---|
| page | number | 1 | Page number |
| limit | number | 10 | Items per page |
All endpoints return errors as RFC 9457 problem details with Content-Type: application/problem+json:
{
"type": "urn:astroid:problem:validation-error",
"title": "Validation Failed",
"status": 400,
"detail": "Request validation failed",
"instance": "/api/v1/agents",
"code": "VALIDATION_ERROR",
"requestId": "req_018f...",
"details": [{ "path": "limit", "message": "Number must be less than or equal to 200" }]
}| Member | Description |
|---|---|
type |
URI identifying the problem type (urn:astroid:problem:<code>), or about:blank for plain HTTP errors without a dedicated code (e.g. 405) |
title |
Short summary of the problem type; the same for every occurrence |
status |
HTTP status code |
detail |
Explanation specific to this occurrence |
instance |
Request path that produced the error (query string omitted) |
code |
Machine-readable error code; clients should switch on this rather than on title or detail |
requestId |
Correlation id, matching the x-request-id header |
details |
Optional structured context, e.g. field-level validation errors |
Unhandled server errors always return 500 with code: "INTERNAL_ERROR" and a generic detail; internal information is only written to the server logs under the requestId.
Most endpoints require Bearer token authentication in the format:
Authorization: Bearer <access_token>
Tokens are obtained via /auth/login or /auth/register endpoints.
Unauthenticated endpoints (routes marked @Public(), such as /auth/login, /auth/register and /auth/refresh, and every route under /public/) share a per-IP sliding-window budget: 60 requests per 60 seconds by default, configurable with PUBLIC_RATE_LIMIT_MAX_REQUESTS and PUBLIC_RATE_LIMIT_WINDOW_SECONDS. Counters are stored in Redis, so the budget applies across all API instances.
Every rate-limited response includes:
| Header | Description |
|---|---|
X-RateLimit-Limit |
Requests allowed per window |
X-RateLimit-Remaining |
Requests left in the current window |
X-RateLimit-Reset |
Unix time (seconds) at which the next request slot frees up |
When the budget is exhausted the API responds with 429 Too Many Requests, a Retry-After header (seconds) and error code RATE_LIMITED. These limits are in addition to the per-route auth throttling on the /auth endpoints.