deep.navy

Platform API

Separate your customers' agent access and usage within your deep.navy account. Management credentials stay on your backend.

Serve your customers
  1. In API keys, create a Platform management key. Only the signed-in account owner can bootstrap management credentials.
  2. Create a tenant with your own stable customer reference, then create a tool key for that tenant. Keep the one-time returned secret securely; it cannot be retrieved later.
  3. Give the tenant tool key to that customer's agent. Use the normal https://mcp.deep.navy/mcp endpoint. Never distribute the management key.
  4. Read attributed usage from your backend and reconcile it before charging your customers.

Management keys administer tenant keys and usage; they cannot call tools, create other management keys or create account-wide tool keys. Tenant tool keys cannot administer the parent account. A tenant's monitors and budget survive key rotation.

Technical access does not grant blanket resale or content republication rights. Agree commercial terms separately and preserve each source's attribution and restrictions.

Keys and tenant limits

POST JSON to the generated Connect service routes with Authorization: Bearer followed by your management key.

Set DEEPNAVY_MANAGEMENT_KEY in your backend environment to the management secret created in the dashboard. This complete HTTP example creates the tenant; use the same headers and service origin for the requests below.

curl --fail-with-body --request POST \
  'https://api.deep.navy/deepnavy.account.v1.AccountService/CreateTenant' \
  --header "Authorization: Bearer $DEEPNAVY_MANAGEMENT_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Connect-Protocol-Version: 1' \
  --data '{"externalRef":"your-customer-42","name":"Customer 42","rateLimitPerMinute":"60","monthlySpendLimitUsdMicros":"10000000"}'

CreateTenant returns tenant.id. Pass it as tenantId to CreateApiKey; that response contains key.id, key metadata and the one-time secret. Give only the tenant tool secret to the agent. A duplicate externalRef is rejected; use ListTenants to recover your existing tenant instead of creating another.

https://api.deep.navy/deepnavy.account.v1.AccountService/CreateTenant

{
  "externalRef": "your-customer-42",
  "name": "Customer 42",
  "rateLimitPerMinute": "60",
  "monthlySpendLimitUsdMicros": "10000000"
}

https://api.deep.navy/deepnavy.account.v1.AccountService/CreateApiKey

{
  "name": "Customer 42 agent",
  "tenantId": "TENANT_ID_FROM_CREATE",
  "management": false,
  "rateLimitPerMinute": "30"
}

Use Content-Type: application/json and replace the tenant ID placeholder with the returned UUID. Protobuf JSON represents int64 amounts as decimal strings. One US dollar is 1,000,000 USD micros, so the example tenant cap is $10.

externalRef is unique within your account and immutable. ListTenants and ListApiKeys support pageSize and pageToken; keys can be filtered by tenantId. Rotate by creating a new key for the same tenant, switching the client and revoking the old key with RevokeApiKey.

UpdateTenant and UpdateApiKey replace editable settings: omitting a cap removes it, and zero blocks all tool calls. Setting a tenant's disabled field stops access by all its keys without deleting resources or usage history.

Per-key and tenant admission limits apply together. Rate limits use fixed UTC minutes; monthly spend budgets use UTC calendar months. Budgets reserve the conservative maximum configured tool-call price before execution, without subtracting free allowances. Failed completed calls release the spend reservation; admitted attempts still consume their minute limit. Unresolved calls remain reserved until reconciled.

These budgets cover synchronous tool calls, not recurring fees, taxes or background monitor deliveries. Keys or tenants with spend caps cannot create, resume or trigger monitors. Rate-only caps apply to synchronous calls and do not limit background monitor execution. A budgeted amount is an enforcement value, not a final invoice total.

Manage tenants and keys

These are independent request examples, not a script to run in sequence. Replace the ID placeholders with returned UUIDs. List requests accept pageSize up to 200; keep tenantId unchanged while paging keys. Update operations replace all editable settings, so send every cap you want to retain. There is no separate rotation method: create, switch and revoke.

AccountService/ListTenants

List tenants. Pass nextPageToken as pageToken to continue.

{
  "pageSize": 50
}

AccountService/ListApiKeys

List one tenant’s keys, including revocation metadata. This never returns the secret.

{
  "tenantId": "TENANT_ID_FROM_CREATE",
  "pageSize": 50
}

AccountService/UpdateTenant

Disable this tenant’s agent access while keeping its name and existing caps. Set disabled to false to re-enable it.

{
  "id": "TENANT_ID_FROM_CREATE",
  "name": "Customer 42",
  "disabled": true,
  "rateLimitPerMinute": "60",
  "monthlySpendLimitUsdMicros": "10000000"
}

AccountService/UpdateApiKey

Replace the key label and caps. This example removes any existing key spend cap by omitting it; the tenant cap still applies.

{
  "id": "KEY_ID_FROM_CREATE",
  "name": "Customer 42 agent",
  "rateLimitPerMinute": "30"
}

AccountService/RevokeApiKey

Revoke the old key after switching the agent to a replacement key for the same tenant. Use key.id, not its prefix or secret.

{
  "id": "OLD_KEY_ID"
}

The account owner can also create tenants, manage agent keys and edit caps in Dashboard → API keys, and filter usage by tenant/key in Dashboard → Usage. Tenant ownership and management privilege cannot be changed with UpdateApiKey. Management keys are for tenant provisioning and usage; an ordinary tool key receives permission_denied here.

Usage and billing

Call deepnavy.account.v1.TenantUsageService/GetUsageSummary at the same API origin with an optional UTC month (YYYY-MM), tenantId and apiKeyId. The response contains month, totals, completionWatermark and observedAt. Totals include successful, failed and pending calls and budgeted USD micros, with an observation timestamp and completion watermark.

Use TenantUsageService/ListUsageEvents with optional tenant/key filters, limit (up to 500) and pageToken for reconciliation. The response contains events, nextPageToken, hasMore and completionWatermark. Deduplicate by the stable event id; each event includes apiKeyId, tenantId when scoped, tool, occurredAt, completedAt, outcome, billableUnits and budgetedUsdMicros. A completed successful call has one billable unit; a completed failure has zero. Events preserve key and tenant attribution through rotation.

Keep and reuse nextPageToken even when hasMore is false: it is an incremental polling checkpoint. Tokens are bound to the original filter scope; start a new request when filters change. Completion ordering handles calls that finish out of order. Store your checkpoint only after processing the returned events successfully.

Tenant metering covers API-key tool calls admitted after this feature was deployed. Historical usage is not backfilled. OAuth sessions continue through account-level metering and do not appear in this tenant/key event ledger.

Account invoices remain the authoritative charge record. Do not use delayed daily summaries or operational logs as a hard spend gate. See limits and errors and retention.

Usage request examples follow. POST to https://api.deep.navy/deepnavy.account.v1.TenantUsageService/ plus the method name, using the same management headers. The month is illustrative; omit it for the current UTC month. Event polling has no month parameter. Start without a page token to consume retained completions, then persist the returned checkpoint.

TenantUsageService/GetUsageSummary

{
  "month": "2026-10",
  "tenantId": "TENANT_ID_FROM_CREATE"
}

TenantUsageService/ListUsageEvents

{
  "tenantId": "TENANT_ID_FROM_CREATE",
  "limit": 100
}

TenantUsageService/ListUsageEvents

{
  "tenantId": "TENANT_ID_FROM_CREATE",
  "limit": 100,
  "pageToken": "NEXT_PAGE_TOKEN_FROM_PREVIOUS_RESPONSE"
}

Parse int64 counters and USD micros as exact decimal integers, not floating-point currency. Poll with the same filters, process and deduplicate the page, then persist its nextPageToken. If hasMore is true, drain the next page; otherwise wait before polling with that same token. A completion watermark describes committed events, not invoice finality.

Requests and responses follow the ProtoJSON format over the Connect protocol. Preserve source and trust information as described in provenance and trust.