Skip to content

API Keys & Authentication

Learn how to get your API key and authenticate your requests to Inodra's APIs.

Getting Your API Key

1. Create an Account

Sign up for a free Inodra account at inodra.com.

2. Select or Create a Project

API keys belong to projects, which are tied to specific Sui networks:

  1. Navigate to Projects in your dashboard
  2. Select an existing project or create a new one
  3. Choose the network (Mainnet or Testnet) for your project

Learn more about Projects and how to organize your resources.

3. Generate an API Key

  1. Navigate to API Keys in the sidebar
  2. Ensure the correct project is selected in the header dropdown
  3. Click Generate New API Key
  4. Give your key a descriptive name (e.g., "Production App", "Development")
  5. Copy your API key and store it securely

Note: API keys are project-specific. A key generated for a Mainnet project will only work with Mainnet endpoints.

⚠️ Keep your API key secure! Never commit API keys to version control. If you ship a key in client-side code, restrict it first: give it only the scopes it needs (see API Key Scopes) and limit it to your site's origins (see Allowed Origins). API Key Security covers every control in one place.

4. API Key Format

Your API key will look like this:

indr_pat_qsVOAbCdEf123456789...

All Inodra API keys start with the indr_pat_ prefix. Treat anything with that prefix in a log, a commit, or a screenshot as a live credential.

API Key Scopes

Every API key carries a set of scopes that control which parts of the platform it can access:

ScopeGrants access toTypical use
DataJSON-RPC, GraphQL, gRPC, and REST read endpointsReading chain data, including from frontends
StreamsConnecting to existing Warp streams (SSE and WebSocket)Live event feeds in apps and frontends
ManageCreating/editing/deleting webhooks and Warp streams, usage stats, key infoBackend services and automation

New keys get the Data scope by default. Select additional scopes when creating a key, or change them later from the dashboard (click the Scopes summary on any key). Scope changes take effect within a few seconds.

A request made with a key that lacks the required scope is rejected with 403 and the error code INSUFFICIENT_SCOPE (WebSocket connections close with code 4003; gRPC calls fail with PERMISSION_DENIED).

Frontend keys: scopes exist so you can safely ship a key in a browser app. Give such keys Data (and Streams if you use Warp) but never Manage - a Manage-scoped key can read webhook signing secrets and redirect webhook deliveries, so keep it server-side only.

Allowed Origins

A key can be restricted to a list of web origins. When the list is not empty, the request must carry an Origin header that matches an entry. Set it from the Origins control on any key, or when you create it.

This is the control that makes a key in a public web page survivable: a copy lifted from your site cannot be replayed from another site, because a browser sets Origin itself and page JavaScript cannot forge it.

Entries look like [scheme://][*.]host[:port]:

EntryMatches
example.comexample.com on any scheme and any port
*.example.comAny subdomain of example.com. Not the apex domain itself
https://app.example.comExactly that origin
http://localhost:3000Local development

A restricted key fails closed: a request with no Origin is rejected with 403 and code ORIGIN_NOT_ALLOWED (WebSocket close code 4003, gRPC PERMISSION_DENIED). Native gRPC clients send no Origin, so they cannot use a restricted key.

Not an access control for backends: any non-browser caller can send whatever Origin it likes. Origin restriction stops key lifting from browsers. Pair it with a per-IP cap (see Rate Limits), which applies to everyone.

Full details, including matching rules and limits, are in API Key Security.

Rate Limits

Beyond your plan's organization-wide limit, each key can carry two optional caps (set them from the Limits control on any key in the dashboard):

CapWhat it boundsUse it for
Per visitor IPRequests from a single IP address, for this keyKeys embedded in a website - each visitor gets their own budget
Per keyAll traffic through this key combinedA ceiling for one integration

The per-IP cap is what makes a browser-embedded key safe to ship: one abusive visitor - or someone who copies the key out of your page and replays it from their own server - is stopped at their own budget instead of draining your organization's quota. Keep it generous (20/s is a reasonable starting point): offices and mobile networks put many legitimate visitors behind a single IP.

Both caps apply to requests and stream connections - opening a Warp SSE or WebSocket stream counts once, when the connection is established. Events delivered over an already-open stream are not rate limited; their cost is metered in compute units instead.

Note: the per-IP cap depends on identifying the visitor, so treat it as a strong guard against a single abusive visitor rather than an absolute one. The per-key cap always applies, so set that too if you need a hard ceiling.

Requests rejected by either cap return 429 with code RATE_LIMIT_EXCEEDED and a Retry-After header - and do not consume credits, so an attacker cannot run up your bill. (A 429 from your plan's organization-wide limit is billed normally.)

The response deliberately doesn't say which of the two caps was hit, or what you configured it to: your key is readable by anyone using your site, and that detail would tell them how to work around it. You can always see the caps you set on the key in the dashboard.

Authentication

Include your API key in the x-api-key header for all requests:

JSON-RPC Authentication

bash
curl -X POST https://mainnet-api.inodra.com/v1/jsonrpc \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"sui_getLatestCheckpointSequenceNumber","params":[]}'

GraphQL Authentication

bash
curl -X POST https://mainnet-api.inodra.com/v1/graphql \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"query": "{ checkpoints(first: 10) { nodes { sequenceNumber } } }"}'

gRPC Authentication

Primary:

go
ctx := metadata.AppendToOutgoingContext(context.Background(), "x-api-key", "YOUR_API_KEY")
response, err := client.GetLatestCheckpoint(ctx, &GetLatestCheckpointRequest{})

Fallback:

go
ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer YOUR_API_KEY")

HTTP Authentication (GraphQL / JSON-RPC)

bash
curl -X POST https://mainnet-api.inodra.com/v1/graphql \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "{ chainIdentifier }"}'

Managing API Keys

Viewing Keys

In your dashboard, you can:

  • View all your API keys
  • See last used timestamps
  • Monitor usage statistics per key

Rotating Keys

For security best practices:

  1. Generate a new API key
  2. Update your applications to use the new key
  3. Delete the old key once migration is complete

Revoking Keys

If a key is compromised:

  1. Go to your dashboard
  2. Find the compromised key
  3. Click Delete to immediately revoke access

Organizations & Teams

Creating Organizations

Organizations allow you to:

  • Share API keys with team members
  • Manage billing centrally
  • Set usage limits per team

Inviting Team Members

  1. Go to Organizations in your dashboard
  2. Click Invite Members
  3. Enter email addresses
  4. Assign roles (Admin or Member)

Role Permissions

  • Admin: Full access to billing, keys, and team management
  • Member: Can create and manage API keys, view usage statistics

Testing Your Setup

Verify your API key works:

bash
# Test with a simple checkpoint query
curl -X POST https://mainnet-api.inodra.com/v1/jsonrpc \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "sui_getLatestCheckpointSequenceNumber",
    "params": []
  }'

Expected response:

json
{
  "jsonrpc": "2.0",
  "result": "12345678",
  "id": 1
}

Common Issues

Invalid API Key

  • Error: 401 Unauthorized
  • Solution: Check that your API key is correct and active

Missing Header

  • Error: 401 Unauthorized
  • Solution: Ensure you're including the x-api-key header

Insufficient Scope

  • Error: 403 Forbidden with code INSUFFICIENT_SCOPE
  • Solution: The key lacks the scope that endpoint requires (see API Key Scopes). Edit the key's scopes in the dashboard, or use a key that has the right scope.

Origin Not Allowed

  • Error: 403 Forbidden with code ORIGIN_NOT_ALLOWED
  • Solution: The key is restricted to specific web origins and this request's origin is not on its allowlist (see Allowed Origins). Add the origin in the dashboard, or use an unrestricted key. Clients that send no Origin cannot use a restricted key.

Network Mismatch

  • Error: 403 Forbidden with code NETWORK_MISMATCH
  • Solution: The key belongs to a project on the other network. Use the endpoint that matches the key's network, or a key from a project on that network.

Rate Limit Exceeded (per key or per IP)

  • Error: 429 Too Many Requests with code RATE_LIMIT_EXCEEDED
  • Solution: You hit a cap set on this specific key (see Rate Limits). Honor the Retry-After header, or raise/remove the cap in the dashboard. These rejections don't consume credits.

Expired Key

  • Error: 401 Unauthorized with code API_KEY_EXPIRED
  • Solution: The key passed its expiration date. Generate a new key in the dashboard and update your application. Expired keys show an Expired badge in the dashboard's key list.

Rate Limit Exceeded (organization-wide)

  • Error: 429 Too Many Requests, with no code field and a retryAfter value in the body
  • Solution: You hit your plan's requests-per-second limit, shared by every key in the organization. Wait retryAfter seconds, spread the load, or upgrade your plan. The X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on every response show where you stand.

Credit Quota Exceeded

  • Error: 429 Too Many Requests with code CU_QUOTA_EXCEEDED
  • Solution: The organization has spent its monthly compute units. Check X-Inodra-Credit-Remaining and X-Inodra-Credit-Replenish-Date on any response, then upgrade your plan or wait for the reset. Open Warp WebSocket streams close with code 1008 and reason QUOTA_EXCEEDED.

Next Steps

The full-stack Sui data layer.