Management API
Use the Management API to manage your Inodra account from code. It is for AI agents, scripts and CI jobs.
With it you can:
- List, create and disable API keys
- List and create projects
- Read the organization, plan and prepaid balance
- Pay a monthly plan with USDC on Sui
For the dashboard, see API Keys and Sign in with Sui.
Authentication
Send an API key in the x-api-key header. The key must have the manage scope.
curl https://mainnet-api.inodra.com/v1/account \
-H "x-api-key: indr_pat_..."You can use either of these keys:
- The key from
POST /v1/wallet/register. It hasdata,streamsandmanage. - A key that you create in the dashboard with the Manage scope.
Base URLs:
| Network | Base URL |
|---|---|
| Mainnet | https://mainnet-api.inodra.com |
| Testnet | https://testnet-api.inodra.com |
Scopes
| Scope | Grants access to |
|---|---|
data | Chain reads (gRPC, GraphQL, JSON-RPC) |
streams | Connections to Warp streams |
manage | Webhooks, Warp streams, usage, API keys, projects and account data |
See API Key Scopes for the full model.
Important: A
managekey is an admin credential for the whole organization. It can create, rotate and revoke every key in it, including keys it did not create. Keep it on the server and off agent and CI hosts. For a workload, create a separate key with only thedatascope.
API Keys
List Keys
curl https://mainnet-api.inodra.com/v1/keys \
-H "x-api-key: indr_pat_..."Response 200:
{
"data": [
{
"id": "<key id>",
"name": "indexer-worker",
"start": "indr_pat_ab",
"prefix": "indr_pat_",
"projectId": "...",
"scopes": ["data"],
"enabled": true,
"expiresAt": "2026-10-24T12:00:00.000Z",
"createdAt": "2026-09-24T12:00:00.000Z"
}
]
}- The list shows every key in the organization.
- The response never contains the secret.
startshows the first characters only.
Create a Key
curl -X POST https://mainnet-api.inodra.com/v1/keys \
-H "x-api-key: indr_pat_..." \
-H "Content-Type: application/json" \
-d '{ "name": "indexer-worker", "projectId": "<project id>", "scopes": ["data"], "expiresInDays": 30 }'Request body:
| Field | Required | Description |
|---|---|---|
name | Yes | A name for the key |
projectId | Yes | A project in your organization |
scopes | No | Default ["data"]. Only scopes that the calling key has |
expiresInDays | No | 1 to 365. Default 30 |
Response 201:
{
"data": {
"id": "<key id>",
"apiKey": "indr_pat_...",
"name": "indexer-worker",
"projectId": "...",
"scopes": ["data"],
"expiresAt": "2026-10-24T12:00:00.000Z"
}
}Rules:
apiKeyis shown once. Store it at once. You cannot get it again.- A new key can only get scopes that the calling key has. If not, Inodra answers
403withSCOPE_ESCALATION. - The project must belong to your organization. If not, Inodra answers
404withPROJECT_NOT_FOUND.
Disable a Key
curl -X DELETE https://mainnet-api.inodra.com/v1/keys/<key id> \
-H "x-api-key: indr_pat_..."Response 200:
{
"data": { "id": "<key id>", "enabled": false }
}- The key stops working at once.
- You can disable the key that you use for the call. Later calls with that key fail.
Projects
List Projects
curl https://mainnet-api.inodra.com/v1/projects \
-H "x-api-key: indr_pat_..."Response 200:
{
"data": [
{
"id": "...",
"name": "Main",
"slug": "main",
"network": "mainnet",
"createdAt": "2026-09-24T12:00:00.000Z"
}
]
}Create a Project
curl -X POST https://mainnet-api.inodra.com/v1/projects \
-H "x-api-key: indr_pat_..." \
-H "Content-Type: application/json" \
-d '{ "name": "Staging", "network": "testnet" }'networkismainnetortestnet.- On success, Inodra answers
201with the new project. - If a project with the same slug exists, Inodra answers
409withPROJECT_SLUG_TAKEN. - Your plan sets how many projects you can have. At the limit, Inodra answers
403withPROJECT_LIMIT_REACHED. A wallet organization has one mainnet project.
Account
curl https://mainnet-api.inodra.com/v1/account \
-H "x-api-key: indr_pat_..."Response 200:
{
"data": {
"organization": { "id": "...", "name": "...", "walletAddress": "0x..." },
"tier": "wallet",
"subscription": { "plan": "...", "status": "...", "periodEnd": "..." },
"key": {
"id": "<key id>",
"name": "...",
"scopes": ["data", "streams", "manage"],
"projectId": "...",
"expiresAt": "..."
},
"balance": { "credits": "500000", "usd": "5.000000" }
}
}keydescribes the key that made the call.balanceis present only for wallet organizations. It is the prepaid x402 balance. Both fields are strings.- Management calls are not metered. They work at zero balance.
Billing
Pay a monthly plan with USDC on Sui. For the full flow, see Pay for a plan with USDC on Sui.
List Plans
Returns the networks, the spender address, the treasury address, the package ID, the coins and the plan prices.
curl https://mainnet-api.inodra.com/v1/billing/plans \
-H "x-api-key: indr_pat_..."Prepare the Setup Transaction
Returns txBytes (base64). The funder signs and executes it with any Sui SDK or wallet.
curl -X POST https://mainnet-api.inodra.com/v1/billing/onchain/prepare \
-H "x-api-key: indr_pat_..." \
-H "Content-Type: application/json" \
-d '{ "network": "testnet", "tier": "team", "funderAddress": "0x...", "prefundPeriods": 3 }'Activate the Plan
Send the Allowance object ID from the created objects of the executed transaction. allowanceCapId is optional.
curl -X POST https://mainnet-api.inodra.com/v1/billing/onchain/activate \
-H "x-api-key: indr_pat_..." \
-H "Content-Type: application/json" \
-d '{ "network": "testnet", "tier": "team", "allowanceId": "0x..." }'Read the Plan State
Returns the state, the plan, the allowance, the funder, the billing balance, the next charge and the last charges.
curl https://mainnet-api.inodra.com/v1/billing/onchain \
-H "x-api-key: indr_pat_..."Change the Plan
when is next_renewal or now. An upgrade needs a new allowanceId.
curl -X POST https://mainnet-api.inodra.com/v1/billing/onchain/change \
-H "x-api-key: indr_pat_..." \
-H "Content-Type: application/json" \
-d '{ "tier": "growth", "when": "next_renewal" }'Cancel the Plan
Access continues until the end of the period. Then revoke the allowance from your wallet.
curl -X POST https://mainnet-api.inodra.com/v1/billing/onchain/cancel \
-H "x-api-key: indr_pat_..."For billing error codes, see Error Codes.
Error Codes
Errors return a JSON body with a code field.
| Code | Status | Meaning | What to do |
|---|---|---|---|
INSUFFICIENT_SCOPE | 403 | The calling key does not have the manage scope | Use a key with manage |
SCOPE_ESCALATION | 403 | You asked for a scope that the calling key lacks | Ask only for scopes that the calling key has |
PROJECT_NOT_FOUND | 404 | The project is not in your organization | Use a project ID from GET /v1/projects |
PROJECT_SLUG_TAKEN | 409 | A project with this slug exists | Use another name |
PROJECT_LIMIT_REACHED | 403 | Your plan does not allow more projects | Use an existing project, or upgrade |
API_KEY_EXPIRED | 401 | The calling key expired | Use another key, or register again |
INVALID_SCOPES | 400 | An unknown scope name | Use data, streams or manage |
INVALID_PROJECT_NAME | 400 | The name yields an empty slug | Use letters or digits in the name |
KEY_NOT_FOUND | 404 | No such key in your organization | Use an ID from GET /v1/keys |
KEY_LIMIT_REACHED | 403 | The organization has 50 enabled keys | Disable a key with DELETE /v1/keys/{id} |
INVALID_BODY | 400 | The JSON body could not be parsed | Send valid JSON |
AUTH_CONTEXT_MISSING | 401 | The key has no organization | Use a key minted for an organization |
ORGANIZATION_NOT_FOUND | 404 | The organization no longer exists | Register again |
UNSUPPORTED_MEDIA_TYPE | 415 | The body is not application/json | Send Content-Type: application/json |
Typical Agent Flow
Pay with x402.
Call
POST /v1/wallet/registerwhen the balance is at least $5. You get a 30-day key with themanagescope.Use that key to create a key for the workload, with only the
datascope. A key never outlives the key that created it, so keys made from a 30-day wallet key expire with it:bashcurl -X POST https://mainnet-api.inodra.com/v1/keys \ -H "x-api-key: <manage key>" \ -H "Content-Type: application/json" \ -d '{ "name": "workload", "projectId": "<project id>", "scopes": ["data"] }'Use the
datakey for chain reads. Keep themanagekey out of the workload.Rotate keys before they expire. Do one of these:
- Call
POST /v1/wallet/registeragain. Inodra issues a new wallet key and revokes the older wallet keys. Keys you created withPOST /v1/keysare not revoked; they expire with the wallet key that created them. - Create a new key with
POST /v1/keys, move the workload to it, then disable the old key withDELETE /v1/keys/{id}.
- Call
A person can see the same organization in the dashboard. See See an Agent's Account.
Limits
| Item | Value |
|---|---|
| Key lifetime | 1 to 365 days. Default 30 |
| Default key scopes | ["data"] |
| Scopes of a new key | Only scopes that the calling key has |
| Projects | Set by your plan. A wallet organization has one project |
| Secret visibility | Only in the 201 response of POST /v1/keys |