API
Diode Console APIs Overview
Diode Console provides APIs for automating fleet creation, membership changes, and retirement using organization-scoped keys.
The public integration surface is JSON-RPC 2.0 over HTTPS. It is not Moonbeam RPC: on-chain work is queued by the console and completed asynchronously through the Diode chain layer.
Available APIs
| API | Description | Availability |
|---|---|---|
|
Console JSON-RPC API
POST /api/v1/rpc |
Manage fleet lifecycle and members from scripts, MDM tooling, or internal systems. | All organizations |
|
Organization API keys
dck_... |
Create, update, and revoke secrets in Settings. Each key is scoped to one organization with a label, fleet access mode (all fleets vs restricted grants), and action scopes. | Owners and admins |
|
Fleet operations
fleet.* |
Create, rename, list members, look up a device, add/remove members, and start fleet retirement. | Authenticated keys |
|
API key management
api_key.* |
List, create, update, and revoke organization API keys. Requires the
admin
scope on the bearer key.
|
Keys with admin
|
Authentication
Create API keys under Settings
(owners and admins only). Set an optional label,
choose fleet access (all fleets in the org or an explicit grant list), and select
action scopes
(read, member changes,
rename, destroy, fleet creation, or the admin
scope for API key management RPCs). The admin
scope implies all fleet actions. Org-wide admin
keys (all_fleets) can only be created in Settings, not via api_key.create. Keys with only
create_fleet
may start with an empty grant list; each successful
fleet.create
adds the new fleet to grants when access is restricted. You can edit keys later; the secret stays read-once.
Copy the secret when it is created; only the hash is stored on the server.
Send it as a Bearer token. Lowercase bearer
is accepted.
Action scopes
Each JSON-RPC method requires a scope on the bearer key (or admin, which implies all fleet scopes).
| Scope | Methods |
|---|---|
| fleet_read | fleet.info, fleet.member.list, fleet.member.get |
| fleet_add_device | fleet.member.add, fleet.member.add_batch |
| fleet_remove_device | fleet.member.remove, fleet.member.remove_batch |
| fleet_update | fleet.rename |
| fleet_destroy | fleet.destroy |
| create_fleet | fleet.create |
| admin | api_key.list, api_key.create, api_key.update, api_key.revoke |
Header
Authorization: Bearer YOUR_API_KEY
Request Format
Every call is a JSON object with jsonrpc, method,
params
(object), and id
(string or number).
Successful responses include result;
failures include error.
Batch Requests
POST a JSON array of request objects to run multiple calls in one HTTP request. Empty arrays are rejected with HTTP 400 and a JSON-RPC error object. For device imports, prefer the member batch methods over JSON-RPC request arrays: they create one database batch and split on-chain work into safe transaction chunks.
Batch example (curl)
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '[{"jsonrpc":"2.0","method":"fleet.create","params":{"name":"Alpha"},"id":1},{"jsonrpc":"2.0","method":"fleet.create","params":{"name":"Beta"},"id":2}]'
fleet.create
Create a new fleet for the organization. Returns
fleet_id
and initial state
while deployment continues asynchronously.
Parameters
-
name(string, required): display name.
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.create","params":{"name":"Production"},"id":1}'
Example response
{"jsonrpc":"2.0","id":1,"result":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","state":"deploying"}}
fleet.rename
Update the fleet name in the console. Imported read-only fleets can use this metadata-only operation.
Parameters
-
fleet_id(UUID or contract address, required). name(string, required).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.rename","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","name":"Staging"},"id":2}'
Example response
{"jsonrpc":"2.0","id":2,"result":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","name":"Staging","state":"live"}}
fleet.info
Read-only snapshot: device count (fleet member rows), authoritative bandwidth usage in bytes for the
current epoch (used_bytes — larger of chain snapshot and live relay total,
same rule as the fleet page bandwidth meter and epoch-close billing), registry stake as a wei string
(or null if the balance cannot be read), chain id, operator and accountant addresses,
the fleet smart contract address, and a
billing
object with plan context (mode, plan_id, monthly_traffic_gb, allowance_bytes, free_bytes_remaining). Hex fields use lowercase
0x
prefixes. Imported fleets are supported.
Parameters
-
fleet_id(UUID or contract address, required).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.info","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000"},"id":21}'
Example response
{"jsonrpc":"2.0","id":21,"result":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","device_count":2,"used_bytes":150000000,"stake_wei":"1000000000000000000","chain_id":1284,"operator":"0x2222222222222222222222222222222222222222","accountant":"0x3333333333333333333333333333333333333333","contract_address":"0x742d35cc6634c0532925a3b844bc454e4438f44e","billing":{"mode":"prepaid","plan_id":"default_50","monthly_traffic_gb":50,"allowance_bytes":50000000000,"free_bytes_remaining":49850000000}}}
fleet.member.add
Add a member address to a fleet. Imported read-only fleets reject this method.
Parameters
-
fleet_id(UUID or contract address, required). -
address(string, required): member wallet address. label(string, optional).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.member.add","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","address":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e","label":"Device A"},"id":3}'
Example response
{"jsonrpc":"2.0","id":3,"result":{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","state":"pending_add"}}
fleet.member.add_batch
Add many member addresses to a fleet. The console validates the full request before
inserting members, then queues one
AddDeviceBatch
on-chain transaction per safe chunk.
Parameters
-
fleet_id(UUID or contract address, required). -
Exactly one of:
members(array of objects withaddressand optionallabel) oraddresses(array of address strings when labels are not needed).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.member.add_batch","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","members":[{"address":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e","label":"Device A"},{"address":"0x1111111111111111111111111111111111111111","label":"Device B"}]},"id":4}'
Example response
{"jsonrpc":"2.0","id":4,"result":{"count":2,"members":[{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","state":"pending_add"},{"member_id":"6ba7b811-9dad-11d1-80b4-00c04fd430c8","state":"pending_add"}]}}
fleet.member.list
Paginated list of devices (fleet members) for a fleet. Includes removed rows still stored in the console. Imported read-only fleets are supported.
Parameters
-
fleet_id(UUID or contract address, required). -
limit(integer, optional): page size, default 50, maximum 100. -
offset(integer, optional): rows to skip, default 0.
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.member.list","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","limit":50,"offset":0},"id":41}'
Example response
{"jsonrpc":"2.0","id":41,"result":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","members":[{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","address":"0x742d35cc6634c0532925a3b844bc454e4438f44e","label":"Device A","state":"active"}],"total":1,"limit":50,"offset":0,"has_more":false}}
fleet.member.get
Fetch one member by console id or device address. Pass exactly one of
member_id
or address. Imported read-only fleets are supported.
Parameters
-
fleet_id(UUID or contract address, required). -
member_id(UUID): console member row id. -
address(string): device address (0xhex).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.member.get","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","address":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e"},"id":42}'
Example response
{"jsonrpc":"2.0","id":42,"result":{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","address":"0x742d35cc6634c0532925a3b844bc454e4438f44e","label":"Device A","state":"active"}}
fleet.member.remove
Remove a member by its console id. Imported read-only fleets reject this method.
Members already allowlisted on chain return
state: "pending_remove"
while the removal transaction confirms; members whose add transaction never
reached the chain are deleted immediately and return state: "removed".
Parameters
member_id(UUID string, required).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.member.remove","params":{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8"},"id":5}'
Example response
{"jsonrpc":"2.0","id":5,"result":{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","state":"pending_remove"}}
fleet.member.remove_batch
Remove many members. Pass member_ids
directly, or pass fleet_id
with addresses
to remove by device address. The console queues
RemoveDeviceBatch
transactions in safe chunks. Same
pending_remove
/ removed
state semantics as fleet.member.remove.
Parameters
-
member_ids(array): console member UUIDs. -
fleet_idplusaddresses(array): remove by fleet and member address.
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.member.remove_batch","params":{"member_ids":["6ba7b810-9dad-11d1-80b4-00c04fd430c8","6ba7b811-9dad-11d1-80b4-00c04fd430c8"]},"id":6}'
Example response
{"jsonrpc":"2.0","id":6,"result":{"count":2,"members":[{"member_id":"6ba7b810-9dad-11d1-80b4-00c04fd430c8","state":"pending_remove"},{"member_id":"6ba7b811-9dad-11d1-80b4-00c04fd430c8","state":"pending_remove"}]}}
fleet.destroy
Retire a fleet: archives immediately when there is no registry stake (or the fleet was
never deployed); otherwise enqueues full unstake and returns unstaking. Imported read-only fleets archive
locally only. Destroyed fleets stay in the database as
archived
and disappear from the dashboard.
Parameters
-
fleet_id(UUID or contract address, required).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"fleet.destroy","params":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000"},"id":7}'
Example response
{"jsonrpc":"2.0","id":7,"result":{"fleet_id":"550e8400-e29b-41d4-a716-446655440000","state":"unstaking","note":"unstake_enqueued"}}
api_key.list
List non-revoked API keys for the organization. Requires the
admin
scope. Returns metadata only; secrets are never included.
Parameters
- None (empty object).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"api_key.list","params":{},"id":81}'
Example response
{"jsonrpc":"2.0","id":81,"result":{"api_keys":[{"api_key_id":"a0a0a0a0-a0a0-a0a0-a0a0-a0a0a0a0a0a0","label":"CI automation","prefix":"dck_1a2b3c4d","fleet_access_mode":"all_fleets","scopes":["fleet_read","fleet_add_device"],"fleet_ids":[],"created_at":"2026-05-28T12:00:00.000000Z","last_used_at":"2026-05-28T14:30:00.000000Z"}]}}
api_key.create
Create a new API key. Requires admin.
Returns the full secret
once in the result; later calls and
api_key.list
show only the prefix. Org-wide admin
keys (all_fleets) cannot be created via RPC — use Settings.
Restricted admin callers may only create non-admin keys with the same
fleet_ids
grant set.
Parameters
label(string, optional).-
fleet_access_mode(string, required):all_fleetsorrestricted. -
scopes(array of strings, required): fleet scope strings such asfleet_read; do not includeadminwhen creating via RPC. -
fleet_ids(array of UUID or contract address strings): required whenfleet_access_modeisrestricted(unless the only scope iscreate_fleet).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"api_key.create","params":{"label":"Delegated read","fleet_access_mode":"restricted","scopes":["fleet_read"],"fleet_ids":["550e8400-e29b-41d4-a716-446655440000"]},"id":82}'
Example response
{"jsonrpc":"2.0","id":82,"result":{"api_key":{"api_key_id":"b1b1b1b1-b1b1-b1b1-b1b1-b1b1b1b1b1b1","label":"Delegated read","prefix":"dck_9f8e7d6c","fleet_access_mode":"restricted","scopes":["fleet_read"],"fleet_ids":["550e8400-e29b-41d4-a716-446655440000"],"created_at":"2026-05-28T15:00:00.000000Z","last_used_at":null},"secret":"dck_9f8e7d6c5b4a3928171615141312111009f8e7d6c5b4a392"}}
api_key.update
Update label, fleet access mode, scopes, and (when restricted) fleet grants for an
existing key. Requires admin.
The same delegation rules as api_key.create
apply. Omitted fields keep their current values when updating a single attribute.
Parameters
-
api_key_id(UUID string, required). label(string, optional).-
fleet_access_mode(string, optional):all_fleetsorrestricted. -
scopes(array of strings, optional). -
fleet_ids(array of UUID or contract address strings, optional): replaces grants when access is restricted.
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"api_key.update","params":{"api_key_id":"b1b1b1b1-b1b1-b1b1-b1b1-b1b1b1b1b1b1","label":"Delegated read+update","fleet_access_mode":"restricted","scopes":["fleet_read","fleet_update"],"fleet_ids":["550e8400-e29b-41d4-a716-446655440000"]},"id":83}'
Example response
{"jsonrpc":"2.0","id":83,"result":{"api_key":{"api_key_id":"b1b1b1b1-b1b1-b1b1-b1b1-b1b1b1b1b1b1","label":"Delegated read+update","prefix":"dck_9f8e7d6c","fleet_access_mode":"restricted","scopes":["fleet_read","fleet_update"],"fleet_ids":["550e8400-e29b-41d4-a716-446655440000"],"created_at":"2026-05-28T15:00:00.000000Z","last_used_at":null}}}
api_key.revoke
Revoke an API key by id. Requires admin.
Idempotent when the key is already revoked. Revoked keys no longer authenticate.
Parameters
-
api_key_id(UUID string, required).
Example request
curl https://console.diode.io/api/v1/rpc \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"jsonrpc":"2.0","method":"api_key.revoke","params":{"api_key_id":"b1b1b1b1-b1b1-b1b1-b1b1-b1b1b1b1b1b1"},"id":84}'
Example response
{"jsonrpc":"2.0","id":84,"result":{"api_key_id":"b1b1b1b1-b1b1-b1b1-b1b1-b1b1b1b1b1b1","revoked_at":"2026-05-28T16:00:00.000000Z"}}
Common Error Responses
JSON-RPC errors use negative numeric code
values. HTTP status is usually 200 for application-level errors except where noted.
| Code | Message | Notes |
|---|---|---|
| -32001 | unauthorized | Missing or non-Bearer Authorization (HTTP 401). |
| -32001 | invalid_api_key | Revoked or unknown key (HTTP 401). |
| -32003 | forbidden |
Missing action scope or fleet not in the key grant list. Check error.data.message: insufficient_scope, fleet_not_allowed, cannot_grant_admin_scope, admin_all_fleets_ui_only, or fleet_grants_mismatch.
|
| -32004 | fleet_not_found | No matching fleet in the key organization. |
| -32004 | api_key_not_found | Unknown key id, or update targeting a revoked key. |
| -32005 | imported_readonly | Mutating call on an imported fleet. |
| -32006 | fleet_not_live | Member add when fleet is not live. |
| -32007 | cap_exceeded | Member cap reached. |
| -32008 | member_not_found | No matching member in the key organization. |
| -32010 | invalid_fleet_state | Destroy not valid for current state. |
| -32012 | registry_unavailable |
Registry read failed; data.reason
may be present.
|
| -32601 | method_not_found |
data.method echoes the unknown name.
|
| -32600 | invalid_request | Malformed JSON-RPC object; empty batch uses HTTP 400. |
| -32700 | invalid_request | Unparsed body or wrong top-level shape. |
| -32602 | invalid_params |
Bad UUID, missing fields, or validation;
data
may list field errors. Common messages include invalid_address, empty_batch, mixed_fleets, restricted_needs_fleets,
and invalid_fleet.
|
| -32603 | internal_error | Unexpected server failure (for example during destroy or API key management). |