This document is the detailed endpoint reference for the machine API.
If your goal is to use R4 as a password manager for an agent runtime, start with:
Every machine request must satisfy both:
AGENT, USER, TENANT, ORG)Grouped grants are expanded when the key is created, so runtime authorization checks stay atomic and auditable.
| Grant | Covers |
|---|---|
machine.all | All machine endpoints allowed for the key scope |
machine.vault.all | Vault metadata reads, secret reads, sync reads, and allowed vault writes |
machine.agent.all | Agent lifecycle reads/writes, vault-item linking, and tenant-role assignment endpoints |
machine.feedback.all | AGENT feedback submission for unsupported product capabilities |
machine.search.all | Machine metadata-search endpoints |
machine.project.all | Project reads and writes |
machine.permissions.all | Project, vault, vault-item, license-instance, and encryption-key permission reads and writes |
machine.domain.all | Domain registration, verification, and DNS reads/writes |
machine.billing.all | Billing reads and writes |
machine.monitoring.all | Scoped metric, request, audit, and vault-activity feeds plus the global-admin-only infrastructure health endpoints |
machine.webhook.all | Machine webhook endpoint management plus delivery history and test sends |
machine.wrapped_key.all | Wrapped-key reads/writes, pending grants, and rekey flows |
machine.user_key_pair.all | User-key-pair directory, vault, backup, and revoke flows |
machine.integration.all | Integration catalog, instances, authorization URLs, and requests |
machine.intelligence_provider.all | Intelligence-provider metadata, token-provider runtime bundles, and managed usage endpoints |
machine.user_manager.all | Tenant-user, invitation, and membership management |
machine.tenant_admin.all | Tenant API key, tenant settings, and security-group management |
machine.org_admin.all | Org-tenant, org-user, and org API key management |
machine.license.all | License list/detail/activity/assets and write flows |
machine.contract.all | Contract list/detail/assets and write flows |
machine.order.all | Machine-owned cart/checkout flows plus order review and approval |
machine.product.all | Catalog search/quote/order-data plus product-instance list/detail/archive flows |
| Atomic permission | Endpoint families |
|---|---|
machine.vault.read | GET /vault, GET /vault/vaults-data, GET /vault/shared-items, GET /vault/:vaultId, GET /vault/:vaultId/items, plus vault-item activity and change-log reads |
machine.vault.secret.read | GET /vault/:vaultId/fields/:fieldId, GET /vault/:vaultId/items/:itemId, GET /vault/:vaultId/wrapped-key, GET /vault/:vaultId/public-keys, GET /attachments/:vaultId/assets/:assetId/signed-url, GET /attachments/:vaultId/assets/:assetId/download-ticket, plus GET /vault-item/:id/field-instance/:fieldInstanceId/secret |
machine.vault.sync.read | GET /vault/sync |
machine.vault.write | POST /vault, PATCH /vault/:id/update, DELETE /vault/:vaultId, POST /vault/:vaultId/items, PATCH /vault-item/:id/update, PATCH /vault-item/:id/move, DELETE /vault/:vaultId/items/:itemId, the attachments/:vaultId/* upload/archive routes, plus vault-group/* and vault-import/* routes |
machine.me.read | GET /me |
machine.agent.read / machine.agent.write | GET /agent, POST /agent, GET /agent/:id, PATCH /agent/:id, PATCH /agent/:id/archive, POST /agent/:id/regenerate-api-key, PATCH /agent/:id/vault-item, GET/PATCH /agent/:id/tenant-roles |
machine.agent.public_key.write | POST /vault/public-key |
machine.feedback.write | POST /feedback |
machine.search.read | POST /search |
machine.project.read / machine.project.write | GET /project, GET /project/:id, POST /project, PATCH /project/update, POST /project/archive, POST /project/restore, project association/member/agent routes |
machine.permissions.read / machine.permissions.write | GET /permissions/:id/access, helper selectors, GET /permissions/:assetType/:id/permissions, GET /permissions/:assetType/:id/resolved-access, POST /permissions/:assetType/:id/set-permissions |
machine.domain.read / machine.domain.write | GET /domain/list, POST /domain/add, POST /domain/:id/verify |
machine.dns.read / machine.dns.write | GET /domain-manager/dns-records, POST /domain-manager/dns-records, plus DNS edit/delete, domain-tenant, email, and SSL routes |
machine.billing.read / machine.billing.write | GET/POST /budget, plus billing balance, readiness, billing-data, credit-transactions, payment methods, setup-intent, attach, add-credit, and crypto-funding intents |
machine.monitoring.read | GET /monitoring/metric-stats, GET /monitoring/entity-counts, GET /monitoring/request-events, GET /monitoring/audit-events, GET /monitoring/vault-activity-events, and the global-admin-only GET /monitoring/system-stats / GET /monitoring/session-stats |
machine.webhook.read / machine.webhook.write | GET /webhook, detail, create, update, rotate-secret, test, deliveries, and archive |
machine.wrapped_key.read / machine.wrapped_key.write | GET /wrapped-key/pending, GET /wrapped-key/vault/:vaultId/*, POST /wrapped-key/vault/:vaultId, delete, and rekey routes |
machine.user_key_pair.read / machine.user_key_pair.write | GET /user-key-pair/me, /directory, /vault/:vaultId, /backup, plus register, backup, and revoke routes |
machine.integration.read / machine.integration.write | /integration/integrations, instance detail/auth/config routes, create/archive/test/request flows |
machine.intelligence_provider.read / machine.intelligence_provider.write | /intelligence-provider/list, /metadata, create, get-by-id, archive, /:id/runtime, /:id/authorize-usage, and /:id/report-usage |
machine.user_manager.read / machine.user_manager.write | /user-manager/tenant-users, invitations, membership, and tenant-role update routes |
machine.tenant_admin.read / machine.tenant_admin.write | /tenant-admin/api-keys, tenant/security-group CRUD and membership routes |
machine.org_admin.read / machine.org_admin.write | /org-admin/org-tenants, org users, org settings, and org API key routes |
machine.license.read / machine.license.write | /license-manager/licenses, detail/activity/assets, attach/archive, and manual/managed update routes |
machine.contract.read / machine.contract.write | /contract-manager/contracts, detail/assets/licenses, create/update/archive flows |
machine.order.read / machine.order.write | /marketplace/create-cart, add-to-cart, :id/cart, my-carts, past-carts, archive-cart, remove-from-cart, checkout, plus /order-manager/orders, approval queue, approve, reject |
machine.product.read / machine.product.write | /marketplace/catalog/*, /marketplace/quote, /marketplace/:id/order-data, plus /product/tenant-product-instances, detail, archive |
The machine API now proxies most of the platform external API surface rather than re-implementing separate business logic. That includes:
metric-stats, entity-counts, request-events, audit-events, and vault-activity-events stay scoped to the authenticated machine session, while system-stats and session-stats are reserved for global-admin-backed keysPOST /search plus persist-style full or delta vault sync through GET /vault/sync/attachments/:vaultId/*/marketplace/*/webhook/*For the audited controller-by-controller route list, see Machine Endpoint Inventory.
POST /project also accepts an optional domainTenantId. Pass it explicitly for ORG-scoped keys or when a tenant has multiple domain-tenant bindings and you need a specific target.
Machine callers can now top up org credit from any wallet that holds USDC on Base. The agent does not need a Stripe account.
Routes:
POST /api/v1/machine/billing/crypto-funding-intentsGET /api/v1/machine/billing/crypto-funding-intentsGET /api/v1/machine/billing/crypto-funding-intents/:idPermissions:
machine.billing.writemachine.billing.readFlow:
tokenCurrency, network, depositAddress, expiresAt, and status fields.USDC Base wallet to that deposit address.CreditTransaction ledger.GET /billing/balance, or GET /billing/readiness until the credit is available.This is a prepaid top-up flow. It is intentionally separate from future x402 pay-per-request flows.
The machine API now exposes a managed token-provider path for SDK/runtime wrappers that want budget-aware vendor calls without proxying the vendor request through R4.
Routes:
GET /api/v1/machine/intelligence-provider/:id/runtimePOST /api/v1/machine/intelligence-provider/:id/authorize-usagePOST /api/v1/machine/intelligence-provider/:id/report-usageWhat this does:
What this does not do:
Use /me when an agent or headless integration needs to confirm the current
scope, tenant binding, or write-path constraints before taking action.
Requirements:
machine.me.readcurl https://r4.dev/api/v1/machine/me -H "X-API-Key: YOUR_MACHINE_KEY"Key response areas:
apiKey.scope and apiKey.summary tell you what policy was enforcedorg, tenant, and agent describe the current principal contextsession returns the current tenant, security-group, and project statecapabilities.vaultWriteConstraint explains whether vault metadata writes are blocked by policy, a missing AGENT runtime key, or a synthetic non-agent sessionwarnings highlights important conditions such as legacy full-access keys or missing agent public-key registrationSee Agent Orchestration for the dedicated lifecycle guide.
Agent-orchestration endpoints add a second authorization layer on top of machine permissions:
machine.agent.read / machine.agent.writeTENANT_AGENT_MANAGER (or an admin bypass)Use this when you need a valid domainTenantId for a new subordinate agent.
curl https://r4.dev/api/v1/machine/agent -H "X-API-Key: YOUR_AGENT_KEY"The list response includes each agent's domainTenantId, which you can reuse when creating another agent in the same tenant.
curl -X POST https://r4.dev/api/v1/machine/agent -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"name":"Steward Agent","domainTenantId":"DOMAIN_TENANT_ID","securityGroupIds":[],"permissions":["machine.agent.all","machine.permissions.all","machine.project.read"]}'The response returns the new agent id, plus a one-time accessKey and accessSecret. Combine those as accessKey.accessSecret to authenticate as the new agent.
curl -X PATCH https://r4.dev/api/v1/machine/agent/AGENT_ID/tenant-roles -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"roles":["TENANT_AGENT_MANAGER"]}'curl https://r4.dev/api/v1/machine/agent/AGENT_ID/tenant-roles -H "X-API-Key: YOUR_AGENT_KEY"curl -X PATCH https://r4.dev/api/v1/machine/agent/AGENT_ID/archive -H "X-API-Key: YOUR_AGENT_KEY"curl -X PATCH https://r4.dev/api/v1/machine/agent/AGENT_ID -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"name":"Steward Agent v2","securityGroupIds":["SECURITY_GROUP_ID"]}'curl -X PATCH https://r4.dev/api/v1/machine/agent/AGENT_ID/vault-item -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"vaultItemId":"VAULT_ITEM_ID"}'curl -X POST https://r4.dev/api/v1/machine/agent/AGENT_ID/regenerate-api-key -H "X-API-Key: YOUR_AGENT_KEY"Use the feedback endpoint when an AGENT runtime is blocked by a missing CLI, SDK, MCP, or raw machine-API capability.
Requirements:
machine.feedback.write or machine.feedback.allcurl -X POST https://r4.dev/api/v1/machine/feedback -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"surface":"CLI","summary":"Need project-aware secret lookup","details":"The CLI can read secrets, but it cannot first resolve the right project and then narrow the vault lookup.","desiredOutcome":"Add a CLI command or SDK helper that resolves project context before secret retrieval."}'R4 stores the feedback first, then sends a best-effort internal notification email. Do not include secret values, plaintext credentials, tokens, or private user data in this payload.
For the field-level contract, see Submit Feedback.
See Permission Management for the dedicated guide covering helper selectors, project permissions, vault permissions, and vault-item permissions.
Permission-management endpoints require both:
machine.permissions.read / machine.permissions.writeADMIN access to the target assetFor delegated orchestration, start with project permissions. Project writes do not require the extra checkpoint material that vault permission writes may need.
set-permissions replaces the full permission list, so include every entry you want to keep, including the acting agent's own ADMIN row.
Supported assetType values include PROJECT, VAULT, VAULT_ITEM, LICENSE_INSTANCE, and ENCRYPTION_KEY.
curl -X POST https://r4.dev/api/v1/machine/permissions/PROJECT/PROJECT_ID/set-permissions -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"permissions":[{"id":"MASTER_AGENT_ID","name":"Master Agent","type":"agent","avatar":null,"isDefault":null,"access":"ADMIN"},{"id":"CHILD_AGENT_ID","name":"Child Agent","type":"agent","avatar":null,"isDefault":null,"access":"READ"}]}'curl https://r4.dev/api/v1/machine/permissions/PROJECT/PROJECT_ID/permissions -H "X-API-Key: YOUR_AGENT_KEY"Vault permission writes require a signed permissionCheckpoint that exactly matches the submitted direct permission list.
curl -X POST https://r4.dev/api/v1/machine/permissions/VAULT/VAULT_ID/set-permissions -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"permissions":[{"id":"MASTER_AGENT_ID","name":"Master Agent","type":"agent","avatar":null,"isDefault":null,"access":"ADMIN"},{"id":"CHILD_AGENT_ID","name":"Child Agent","type":"agent","avatar":null,"isDefault":null,"access":"READ"}],"permissionCheckpoint":{"checkpoint":{"assetId":"VAULT_ID","assetType":"VAULT","version":4,"permissions":[{"entityId":"MASTER_AGENT_ID","entityType":"agent","access":"ADMIN"},{"entityId":"CHILD_AGENT_ID","entityType":"agent","access":"READ"}]},"signerUserKeyPairId":"USER_KEY_PAIR_ID","signature":"base64-signature"}}'Vault-item permission writes use the same checkpoint-backed request shape as vault writes, but parent-vault access still applies irrespective of direct item settings.
curl -X POST https://r4.dev/api/v1/machine/permissions/VAULT_ITEM/VAULT_ITEM_ID/set-permissions -H "X-API-Key: YOUR_AGENT_KEY" -H "Content-Type: application/json" -d '{"permissions":[{"id":"CHILD_AGENT_ID","name":"Child Agent","type":"agent","avatar":null,"isDefault":null,"access":"READ"}],"permissionCheckpoint":{"checkpoint":{"assetId":"VAULT_ITEM_ID","assetType":"VAULT_ITEM","version":7,"permissions":[{"entityId":"CHILD_AGENT_ID","entityType":"agent","access":"READ"}]},"signerUserKeyPairId":"USER_KEY_PAIR_ID","signature":"base64-signature"}}'The Domain Manager API provides programmatic access to DNS management for domains in your organization.
Retrieves all DNS records configured for a domain managed by your organization.
GET /api/v1/machine/domain-manager/dns-records| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | The domain name to retrieve DNS records for (e.g., "example.com") |
| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your API key |
Success (200 OK)
{
"domain": "example.com",
"records": [
{
"type": "A",
"name": "@",
"value": "192.168.1.1",
"ttl": 300
},
{
"type": "CNAME",
"name": "www",
"value": "example.com.",
"ttl": 300
},
{
"type": "MX",
"name": "@",
"value": "mail.example.com.",
"ttl": 300,
"mxPref": 10
},
{
"type": "TXT",
"name": "@",
"value": "v=spf1 include:_spf.google.com ~all",
"ttl": 300
}
]
}| Field | Type | Description |
|---|---|---|
domain | string | The domain name |
records | array | Array of DNS records |
records[].type | string | Record type (A, AAAA, CNAME, MX, TXT, NS, SRV, CAA) |
records[].name | string | Host name ("@" for root, or subdomain like "www") |
records[].value | string | Record value (IP, hostname, or text) |
records[].ttl | number | Time to live in seconds |
records[].mxPref | number | MX priority (only for MX records) |
401 Unauthorized - Invalid or missing API key
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key. Please provide your API key in the X-API-Key header."
}
}403 Forbidden - Domain not managed through R4
{
"error": {
"code": "domain_not_managed",
"message": "The domain \"example.com\" is not managed through R4. DNS records can only be retrieved for domains purchased through the R4 platform."
}
}404 Not Found - Domain not found in your organization
{
"error": {
"code": "domain_not_found",
"message": "The domain \"example.com\" was not found in your organization or you do not have access to it."
}
}curl -X GET "https://r4.dev/api/v1/machine/domain-manager/dns-records?domain=example.com" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"internalPurchase: true) can have their DNS records retrievedAdds a new DNS record to a domain managed by your organization.
POST /api/v1/machine/domain-manager/dns-records| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your API key |
Content-Type | string | Yes | Must be application/json |
| Field | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | The domain name to add the record to (e.g., "example.com") |
record | object | Yes | The DNS record to add |
record.type | string | Yes | Record type (A, AAAA, CNAME, MX, TXT, NS, SRV, CAA) |
record.name | string | Yes | Host name ("@" for root, or subdomain like "www") |
record.value | string | Yes | Record value (IP address, hostname, or text) |
record.ttl | number | No | Time to live in seconds (default: 300) |
record.mxPref | number | No | MX priority (only for MX records, lower = higher priority) |
{
"domain": "example.com",
"record": {
"type": "A",
"name": "www",
"value": "192.168.1.1",
"ttl": 300
}
}Success (200 OK)
Returns all DNS records for the domain, including the newly added record.
{
"domain": "example.com",
"records": [
{
"type": "A",
"name": "@",
"value": "192.168.1.1",
"ttl": 300
},
{
"type": "A",
"name": "www",
"value": "192.168.1.1",
"ttl": 300
},
{
"type": "CNAME",
"name": "mail",
"value": "example.com.",
"ttl": 300
}
]
}401 Unauthorized - Invalid or missing API key
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key. Please provide your API key in the X-API-Key header."
}
}403 Forbidden - Domain not managed through R4
{
"error": {
"code": "domain_not_managed",
"message": "The domain \"example.com\" is not managed through R4. DNS records can only be modified for domains purchased through the R4 platform."
}
}404 Not Found - Domain not found in your organization
{
"error": {
"code": "domain_not_found",
"message": "The domain \"example.com\" was not found in your organization or you do not have access to it."
}
}curl -X POST "https://r4.dev/api/v1/machine/domain-manager/dns-records" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef" \
-H "Content-Type: application/json" \
-d '{
"domain": "example.com",
"record": {
"type": "A",
"name": "www",
"value": "192.168.1.1",
"ttl": 300
}
}'internalPurchase: true) can have their DNS records modifiedThe Project Manager API provides programmatic access to project creation, listing, and detailed resource information. Projects are organizational units that contain vaults, licenses, and license groups.
Retrieves a list of all non-archived projects accessible to the authenticated API key.
GET /api/v1/machine/project| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your API key |
Success (200 OK)
{
"projects": [
{
"id": "507f1f77bcf86cd799439014",
"name": "Production Infrastructure",
"externalId": "PROJ-001",
"description": "Contains all production environment resources",
"vaultsCount": 5,
"licensesCount": 12,
"licenseGroupsCount": 3,
"archivedAt": null
},
{
"id": "507f1f77bcf86cd799439015",
"name": "Development Environment",
"externalId": "PROJ-002",
"description": "Development and testing resources",
"vaultsCount": 2,
"licensesCount": 4,
"licenseGroupsCount": 1,
"archivedAt": null
}
]
}| Field | Type | Description |
|---|---|---|
projects | array | Array of project summary objects |
| Field | Type | Description |
|---|---|---|
id | string | The unique identifier of the project |
name | string | The name of the project |
externalId | string | null | Optional external identifier for integration with external systems |
description | string | null | A description of the project |
vaultsCount | number | The number of vaults associated with this project |
licensesCount | number | The number of licenses (both internal and manual) associated |
licenseGroupsCount | number | The number of license groups associated |
archivedAt | string | null | ISO 8601 timestamp when archived (null if active) |
401 Unauthorized - Invalid or missing API key
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key. Please provide your API key in the X-API-Key header."
}
}curl -X GET "https://r4.dev/api/v1/machine/project" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"Creates a new project in the organization.
POST /api/v1/machine/project| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your API key |
Content-Type | string | Yes | application/json |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The name of the project (max 255 characters) |
externalId | string | No | Optional external identifier for integration (max 255 characters) |
description | string | No | A description of the project (max 1000 characters) |
Success (201 Created)
{
"id": "507f1f77bcf86cd799439014"
}| Field | Type | Description |
|---|---|---|
id | string | The unique identifier of the newly created project |
400 Bad Request - Invalid request body
{
"error": {
"code": "project_creation_failed",
"message": "Failed to create the project. Please verify your input and try again."
}
}401 Unauthorized - Invalid or missing API key
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key. Please provide your API key in the X-API-Key header."
}
}curl -X POST "https://r4.dev/api/v1/machine/project" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Infrastructure",
"externalId": "PROJ-001",
"description": "Contains all production environment resources"
}'Retrieves detailed information about a project including all associated vaults, licenses, and license groups.
GET /api/v1/machine/project/:id| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The unique identifier of the project |
| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your API key |
Success (200 OK)
{
"id": "507f1f77bcf86cd799439014",
"name": "Production Infrastructure",
"externalId": "PROJ-001",
"description": "Contains all production environment resources",
"domainTenantId": "507f1f77bcf86cd799439016",
"vaultsCount": 5,
"licensesCount": 12,
"licenseGroupsCount": 3,
"createdAt": "2026-01-15T10:30:00.000Z",
"createdBy": "507f1f77bcf86cd799439017",
"archivedAt": null,
"vaults": [
{
"id": "507f1f77bcf86cd799439011",
"name": "Production Secrets",
"isEncrypted": true
}
],
"licenses": [
{
"id": "507f1f77bcf86cd799439012",
"name": "Enterprise License",
"type": "internal"
},
{
"id": "507f1f77bcf86cd799439018",
"name": "Manual License Entry",
"type": "manual"
}
],
"licenseGroups": [
{
"id": "507f1f77bcf86cd799439013",
"name": "Development Team Licenses"
}
]
}| Field | Type | Description |
|---|---|---|
id | string | The unique identifier of the project |
name | string | The name of the project |
externalId | string | null | Optional external identifier for integration with external systems |
description | string | null | A description of the project |
domainTenantId | string | null | The domain tenant ID this project is associated with |
vaultsCount | number | The number of vaults associated with this project |
licensesCount | number | The number of licenses (both internal and manual) associated |
licenseGroupsCount | number | The number of license groups associated |
createdAt | string | ISO 8601 timestamp when the project was created |
createdBy | string | ID of the user who created the project |
archivedAt | string | null | ISO 8601 timestamp when archived (null if active) |
vaults | array | Array of vault objects associated with the project |
licenses | array | Array of license objects (both internal and manual) |
licenseGroups | array | Array of license group objects |
| Field | Type | Description |
|---|---|---|
id | string | The unique identifier of the vault |
name | string | The name of the vault |
isEncrypted | boolean | null | Whether the vault uses client-side encryption |
| Field | Type | Description |
|---|---|---|
id | string | The unique identifier of the license |
name | string | null | The name of the license |
type | string | License type: "internal" or "manual" |
| Field | Type | Description |
|---|---|---|
id | string | The unique identifier of the license group |
name | string | The name of the license group |
401 Unauthorized - Invalid or missing API key
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key. Please provide your API key in the X-API-Key header."
}
}404 Not Found - Project not found in your organization
{
"error": {
"code": "project_not_found",
"message": "The project with ID \"507f1f77bcf86cd799439014\" was not found in your organization or you do not have access to it."
}
}curl -X GET "https://r4.dev/api/v1/machine/project/507f1f77bcf86cd799439014" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"The Vault Manager API provides full programmatic access to vault management — creating vaults, managing vault items, and retrieving secrets.
Creates a new encrypted vault with a client-signed empty summary checkpoint.
POST /api/v1/machine/vault| Header | Type | Required | Description |
|---|---|---|---|
X-API-Key | string | Yes | Your API key |
Content-Type | string | Yes | Must be application/json |
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Stable vault ID chosen client-side |
summaryCheckpoint | object | Yes | Signed empty summary checkpoint for the new vault |
name | string | Yes | The name of the vault (max 255 chars) |
projectId | string | No | Project ID to grant WRITE access to the vault |
dataClassification | string | No | Data classification level: PUBLIC, INTERNAL, CONFIDENTIAL, or CUI |
Success (201 Created)
{
"id": "507f1f77bcf86cd799439016"
}signerEncryptionKeyId matches the agent's active registered encryption keysummaryCheckpoint.items and summaryCheckpoint.groups must both be empty on createprojectId is provided, the project is additionally granted WRITE accesscurl -X POST "https://r4.dev/api/v1/machine/vault" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef" \
-H "Content-Type: application/json" \
-d '{
"id": "507f1f77bcf86cd799439016",
"summaryCheckpoint": {
"checkpoint": {
"vaultId": "507f1f77bcf86cd799439016",
"version": 1,
"name": "Production Secrets",
"dataClassification": "CONFIDENTIAL",
"currentDekVersion": 1,
"items": [],
"groups": []
},
"signerUserKeyPairId": "507f1f77bcf86cd799439099",
"signature": "base64-signature"
},
"name": "Production Secrets",
"projectId": "507f1f77bcf86cd799439014",
"dataClassification": "CONFIDENTIAL"
}'Returns all accessible vaults, optionally filtered by project.
GET /api/v1/machine/vault| Parameter | Type | Required | Description |
|---|---|---|---|
projectId | string | No | Filter vaults by project ID |
Success (200 OK)
{
"vaults": [
{
"id": "507f1f77bcf86cd799439011",
"name": "Production Secrets",
"isEncrypted": true,
"encryptionKeyId": "507f1f77bcf86cd799439015",
"dataClassification": "CONFIDENTIAL",
"itemCount": 12,
"createdAt": "2026-01-15T10:30:00.000Z"
}
]
}curl -X GET "https://r4.dev/api/v1/machine/vault?projectId=507f1f77bcf86cd799439014" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef"Returns detailed information about a specific vault.
GET /api/v1/machine/vault/:vaultId| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault |
Success (200 OK)
{
"id": "507f1f77bcf86cd799439011",
"name": "Production Secrets",
"isEncrypted": true,
"encryptionKeyId": "507f1f77bcf86cd799439015",
"dataClassification": "CONFIDENTIAL",
"createdAt": "2026-01-15T10:30:00.000Z",
"createdBy": "507f1f77bcf86cd799439017",
"itemCount": 12
}Vault metadata note: vault names, item names, field labels, and websites are not end-to-end encrypted. That metadata is only protected by encryption in transit and at rest, then authenticated with signed checkpoints. Only field values are end-to-end encrypted v3 vault envelopes.
Updates vault metadata such as the vault name or data classification.
PATCH /api/v1/machine/vault/:id/update| Field | Type | Required | Description |
|---|---|---|---|
directoryCheckpoint | object | Yes | Signed replacement directory checkpoint for list-level metadata |
summaryCheckpoint | object | Yes | Signed replacement summary checkpoint for vault metadata |
name | string | Yes | The new vault name |
dataClassification | string | No | Optional classification override |
name in this request and its checkpoints is metadata, so it is not end-to-end encrypted.Archives (soft-deletes) a vault with a client-signed replacement summary checkpoint. The vault and its items are retained for audit purposes.
DELETE /api/v1/machine/vault/:vaultId| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault to archive |
| Field | Type | Required | Description |
|---|---|---|---|
summaryCheckpoint | object | Yes | Signed replacement summary checkpoint after archive |
Success (204 No Content)
No response body.
signerEncryptionKeyId matches the agent's active registered encryption keysummaryCheckpoint should usually preserve the current vault item/group snapshot and only advance the signed metadata version during the archive transitionNo response body.
Creates a new vault item with client-encrypted field values plus signed vault/item checkpoints.
POST /api/v1/machine/vault/:vaultId/items| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault |
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Stable vault-item ID chosen client-side |
summaryCheckpoint | object | Yes | Signed replacement summary checkpoint for the parent vault |
detailCheckpoint | object | Yes | Signed detail checkpoint for the new item |
name | string | Yes | The name of the vault item (max 255 chars) |
type | string | Yes | Vault item type (for example LOGIN) |
websites | array | No | Associated website URLs (max 100) |
fields | array | Yes | Array of field objects to create on the item |
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Stable field ID chosen client-side |
fieldInstanceId | string | Yes | Stable field-instance ID chosen client-side |
name | string | Yes | Field label (for example Username) |
type | string | Yes | Field type (TEXT, PASSWORD, SECRET, URL, etc.) |
encryptedValue | string | No | Client-encrypted v3 vault envelope |
Success (201 Created)
{
"id": "507f1f77bcf86cd799439018"
}signerEncryptionKeyId matches the agent's active registered encryption keyname, item name, field name, and websites metadata in this request are not end-to-end encrypted.encryptedValue as-is and does not decrypt itcurl -X POST "https://r4.dev/api/v1/machine/vault/507f1f77bcf86cd799439011/items" \
-H "X-API-Key: rk_abc123def456.ghijklmnopqrstuvwxyz1234567890abcdef" \
-H "Content-Type: application/json" \
-d '{
"id": "507f1f77bcf86cd799439018",
"summaryCheckpoint": {
"checkpoint": {
"vaultId": "507f1f77bcf86cd799439011",
"version": 9,
"name": "Production Secrets",
"dataClassification": "CONFIDENTIAL",
"currentDekVersion": 3,
"items": [
{
"id": "507f1f77bcf86cd799439018",
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"groupId": null
}
],
"groups": []
},
"signerUserKeyPairId": "507f1f77bcf86cd799439099",
"signature": "base64-signature"
},
"detailCheckpoint": {
"checkpoint": {
"vaultItemId": "507f1f77bcf86cd799439018",
"vaultId": "507f1f77bcf86cd799439011",
"version": 1,
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"groupId": null,
"fields": [
{
"id": "507f1f77bcf86cd799439019",
"name": "Username",
"type": "TEXT",
"order": 0,
"fieldInstanceIds": ["507f1f77bcf86cd799439051"],
"assetIds": []
}
]
},
"signerUserKeyPairId": "507f1f77bcf86cd799439099",
"signature": "base64-signature"
},
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"fields": [
{
"id": "507f1f77bcf86cd799439019",
"fieldInstanceId": "507f1f77bcf86cd799439051",
"name": "Username",
"type": "TEXT",
"encryptedValue": "{\"v\":3,\"iv\":\"...\",\"t\":\"...\",\"d\":\"...\"}"
},
{
"id": "507f1f77bcf86cd799439020",
"fieldInstanceId": "507f1f77bcf86cd799439052",
"name": "Password",
"type": "PASSWORD",
"encryptedValue": "{\"v\":3,\"iv\":\"...\",\"t\":\"...\",\"d\":\"...\"}"
}
]
}'Returns all non-archived items in a vault with the signed summary-checkpoint metadata a zero-trust runtime needs before trusting item names, websites, or group structure.
GET /api/v1/machine/vault/:vaultId/items| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault |
Success (200 OK)
{
"vaultId": "507f1f77bcf86cd799439011",
"vaultName": "Production Secrets",
"dataClassification": "CONFIDENTIAL",
"currentDekVersion": 3,
"summaryCheckpoint": {
"checkpoint": {
"vaultId": "507f1f77bcf86cd799439011",
"version": 9,
"name": "Production Secrets",
"dataClassification": "CONFIDENTIAL",
"currentDekVersion": 3,
"items": [
{
"id": "507f1f77bcf86cd799439018",
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"groupId": null
}
],
"groups": []
},
"signerUserKeyPairId": "507f1f77bcf86cd799439099",
"signature": "base64-signature"
},
"items": [
{
"id": "507f1f77bcf86cd799439018",
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"groupId": null,
"createdAt": "2026-01-15T10:30:00.000Z",
"fieldCount": 2
}
],
"vaultItemGroups": [],
"count": 1
}vaultName, item name, and websites are metadata, so they are not end-to-end encryptedsummaryCheckpoint against GET /vault/:vaultId/public-keyscurrentDekVersion binds the item listing to the current wrapped-DEK generationvaultItemGroups provides the group structure covered by the signed checkpointReturns the latest stored payload for one field, plus the parent signed detail checkpoint so a runtime can authenticate the field metadata locally without fetching sibling field values.
GET /api/v1/machine/vault/:vaultId/fields/:fieldId| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault |
fieldId | string | Yes | The unique identifier of the vault field |
Success (200 OK)
{
"id": "507f1f77bcf86cd799439020",
"name": "Password",
"type": "PASSWORD",
"order": 1,
"fieldInstanceId": "507f1f77bcf86cd799439052",
"fieldInstanceIds": ["507f1f77bcf86cd799439052"],
"assetId": null,
"assetIds": [],
"value": "{\"v\":3,\"iv\":\"...\",\"t\":\"...\",\"d\":\"...\"}",
"vaultId": "507f1f77bcf86cd799439011",
"vaultItemId": "507f1f77bcf86cd799439018",
"vaultItemName": "Production Database",
"detailCheckpoint": {
"checkpoint": {
"vaultItemId": "507f1f77bcf86cd799439018",
"vaultId": "507f1f77bcf86cd799439011",
"version": 12,
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"groupId": null,
"fields": [
{
"id": "507f1f77bcf86cd799439019",
"name": "Username",
"type": "TEXT",
"order": 0,
"fieldInstanceIds": ["507f1f77bcf86cd799439051"],
"assetIds": []
},
{
"id": "507f1f77bcf86cd799439020",
"name": "Password",
"type": "PASSWORD",
"order": 1,
"fieldInstanceIds": ["507f1f77bcf86cd799439052"],
"assetIds": []
}
]
},
"signerUserKeyPairId": "507f1f77bcf86cd799439099",
"signature": "base64-signature"
}
}fieldId and want the narrowest possible readname, vaultItemName, and checkpoint websites metadata are not end-to-end encryptedfieldInstanceId is the latest active instance used for value; fieldInstanceIds contains the full active instance setdetailCheckpoint.checkpoint.fields matches the returned id, type, order, fieldInstanceIds, and assetIdsPOST /vault/public-key, GET /vault/:vaultId/wrapped-key, and GET /vault/:vaultId/public-keys to unwrap the vault DEK and verify the signer locally before decrypting valueReturns full vault item detail including all fields, ciphertext values, and the signed detail checkpoint needed to authenticate the metadata locally.
GET /api/v1/machine/vault/:vaultId/items/:itemId| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault |
itemId | string | Yes | The unique identifier of the vault item |
Success (200 OK)
{
"id": "507f1f77bcf86cd799439018",
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"vaultId": "507f1f77bcf86cd799439011",
"groupId": null,
"fields": [
{
"id": "507f1f77bcf86cd799439019",
"name": "Username",
"type": "TEXT",
"order": 0,
"fieldInstanceIds": ["507f1f77bcf86cd799439051"],
"assetIds": [],
"value": "{\"v\":3,\"iv\":\"...\",\"t\":\"...\",\"d\":\"...\"}"
},
{
"id": "507f1f77bcf86cd799439020",
"name": "Password",
"type": "PASSWORD",
"order": 1,
"fieldInstanceIds": ["507f1f77bcf86cd799439052"],
"assetIds": [],
"value": "{\"v\":3,\"iv\":\"...\",\"t\":\"...\",\"d\":\"...\"}"
}
],
"detailCheckpoint": {
"checkpoint": {
"vaultItemId": "507f1f77bcf86cd799439018",
"vaultId": "507f1f77bcf86cd799439011",
"version": 12,
"name": "Production Database",
"type": "LOGIN",
"websites": ["https://db.example.com"],
"groupId": null,
"fields": [
{
"id": "507f1f77bcf86cd799439019",
"name": "Username",
"type": "TEXT",
"order": 0,
"fieldInstanceIds": ["507f1f77bcf86cd799439051"],
"assetIds": []
}
]
},
"signerUserKeyPairId": "507f1f77bcf86cd799439099",
"signature": "base64-signature"
}
}name, field name, and websites metadata are not end-to-end encryptedPOST /vault/public-key, GET /vault/:vaultId/wrapped-key, and GET /vault/:vaultId/public-keys as part of your client-side key-unwrapping flowdetailCheckpoint before trusting the item name, websites, or field layoutUpdates vault-item metadata and applies batched field mutations through the updates array.
PATCH /api/v1/machine/vault-item/:id/update| Field | Type | Required | Description |
|---|---|---|---|
detailCheckpoint | object | Yes | Signed replacement detail checkpoint for the item |
summaryCheckpoint | object | No | Required when name, type, or websites change |
name | string | No | Optional new item name |
type | string | No | Optional new item type |
websites | array | No | Optional replacement website list |
updates | array | Yes | Batched field operations with add, update, or delete actions |
name, field name, and websites metadata in this request are not end-to-end encrypted.add creates a new field, update creates a new active field instance, and delete archives the field.Moves a vault item into another vault.
PATCH /api/v1/machine/vault-item/:id/move| Field | Type | Required | Description |
|---|---|---|---|
detailCheckpoint | object | Yes | Signed replacement detail checkpoint for the moved item |
sourceVaultSummaryCheckpoint | object | Yes | Signed replacement source-vault summary after removal |
targetVaultSummaryCheckpoint | object | Yes | Signed replacement target-vault summary after insert |
vaultId | string | Yes | Target vault ID |
reEncryptedFieldValues | array | No | Re-encrypted field values for the target vault DEK |
Archives (soft-deletes) a vault item with a client-signed replacement summary checkpoint.
DELETE /api/v1/machine/vault/:vaultId/items/:itemId| Parameter | Type | Required | Description |
|---|---|---|---|
vaultId | string | Yes | The unique identifier of the vault |
itemId | string | Yes | The unique identifier of the vault item to archive |
| Field | Type | Required | Description |
|---|---|---|---|
summaryCheckpoint | object | Yes | Signed replacement summary checkpoint after delete |
Success (204 No Content)
No response body.
signerEncryptionKeyId matches the agent's active registered encryption keyRegisters the AGENT-scoped caller's active RSA public key. The private key stays on the agent runtime and never traverses the server.
POST /api/v1/machine/vault/public-keyX-R4-Agent-Hostname: Best-effort runtime hostname claim sent by the official SDK/CLI. Stored only for operator visibility.{
"publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----",
"previousEncryptionKeyId": "507f1f77bcf86cd799439015",
"rotationSignature": "base64-signature"
}Success (201 Created)
{
"encryptionKeyId": "507f1f77bcf86cd799439015",
"publicKey": "-----BEGIN PUBLIC KEY-----\n...",
"fingerprint": "b5d44d6c7c1c1d4b...",
"previousEncryptionKeyId": "507f1f77bcf86cd799439010",
"rotationSignature": "base64-signature"
}X-R4-Agent-Hostname claim on the agent so operators can see where the active key last registeredrewrappedVaultKeys batchGET /vault/:vaultId/wrapped-key to unwrap vault DEKsThe following DNS record types may be returned by the API:
Maps a domain to an IPv4 address.
{
"type": "A",
"name": "@",
"value": "192.168.1.1",
"ttl": 300
}Maps a domain to an IPv6 address.
{
"type": "AAAA",
"name": "@",
"value": "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
"ttl": 300
}Creates an alias from one domain to another.
{
"type": "CNAME",
"name": "www",
"value": "example.com.",
"ttl": 300
}Specifies mail servers for the domain. Lower mxPref values indicate higher priority.
{
"type": "MX",
"name": "@",
"value": "mail.example.com.",
"ttl": 300,
"mxPref": 10
}Contains arbitrary text data, commonly used for SPF, DKIM, and domain verification.
{
"type": "TXT",
"name": "@",
"value": "v=spf1 include:_spf.google.com ~all",
"ttl": 300
}Specifies authoritative nameservers for the domain.
{
"type": "NS",
"name": "@",
"value": "ns1.example.com.",
"ttl": 86400
}Currently, endpoints return all results in a single response. Future endpoints may support pagination with the following format:
{
"data": [...],
"pagination": {
"page": 1,
"limit": 50,
"total": 150,
"totalPages": 3
}
}Query parameters for paginated endpoints:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number (1-indexed) |
limit | number | 50 | Number of items per page (max 100) |
POST /auth/auth/register-agent now requires a saved Stripe payment method id plus an initial prepaid top-off of at least $20, and the new agent-only org stays pending until that billing step succeedsGET /vault/sync so machine-authenticated runtimes can reuse the full or delta persist sync contractPOST /search for machine-visible vault, field-label, and license metadata discoveryPOST /auth/auth/register-agent bootstrap coverage so a new agent-only org can optionally register its first runtime public key and custom AGENT machine-policy grants in the same flowPATCH /vault/:id/update, PATCH /vault-item/:id/update, and PATCH /vault-item/:id/move write routesGET /vault/:vaultId/fields/:fieldId for narrow single-field reads that still return the parent signed detail checkpointGET /vault/env/:projectId plaintext env endpointGET /vault/:vaultId/items and GET /vault/:vaultId/items/:itemIdPOST /vault/public-key so AGENT-scoped runtimes register or rotate their own public key locallyPOST /vault — Create encrypted vaultGET /vault — List vaults (with optional project filter)GET /vault/:vaultId — Get vault detailDELETE /vault/:vaultId — Archive vault with a signed summary checkpointPOST /vault/:vaultId/items — Create vault itemGET /vault/:vaultId/items — List vault itemsGET /vault/:vaultId/fields/:fieldId — Get a single field valueGET /vault/:vaultId/items/:itemId — Get vault item detailDELETE /vault/:vaultId/items/:itemId — Archive vault item with a signed summary checkpointPOST /domain-manager/dns-records endpoint for adding DNS recordsGET /project/:id endpoint for project detailsGET /domain-manager/dns-records endpoint