Back

Blog details

AIOZ Pin API Keys: Auth, Scopes, and Secure Storage

AIOZ Network
5 min readAugust 14, 2026
aioz-pindevelopersecurity
Holographic hexagon tiles representing AIOZ Pin's IPFS storage network

AIOZ Pin API keys aren't one flat secret with full access by default, they're generated with a specific set of scopes attached, and the actual authentication mechanics differ slightly depending on which endpoint you're calling. This covers the parts that don't show up in a quick glance at the docs: which endpoints expect a Bearer token versus raw key/secret headers, exactly what a scoped key can and can't do, and how to store credentials safely once you have them.

TL;DR:
  • Account and key-management endpoints (Users, ApiKeys) authenticate with Authorization: Bearer <access_token>
  • Resource endpoints like testAuthentication and the Nft API instead use raw pinning_api_key/pinning_secret_key headers
  • Keys carry granular scopes (admin, data, pinning, pin_nft) rather than defaulting to full access

Two Different Auth Header Formats, Not One

Generating, listing, and deleting API keys, along with account endpoints like /users/me, all authenticate with the standard pattern: Authorization: Bearer your_access_token_here. But testAuthentication and the Nft API work differently, they expect pinning_api_key and pinning_secret_key as separate headers, the raw key and secret rather than a bearer token. That's not an inconsistency to route around, it lines up with what those endpoints actually do: testAuthentication exists specifically to verify a key/secret pair is valid, and the Nft API is built to be called directly with a scoped key rather than through an intermediate token exchange.

In practice, this distinction matters most when you're debugging: if a call to /users/me or /apiKeys/list fails with an auth error, check your Bearer token. If a call to testAuthentication or the Nft API fails, check the raw key and secret values themselves, those endpoints aren't reading a token at all.

What a Scoped Key Can Actually Do

Generating a key is a POST to /apiKeys with a scopes object:

{
  "admin": false,
  "data": { "pin_list": true, "nft_list": false },
  "pinning": { "unpin": false, "pin_by_hash": true, "pin_file_to_ipfs": true },
  "pin_nft": { "unpin_nft": false, "pin_nft_to_ipfs": false }
}

AIOZ Pin's docs specify that non-admin keys need every property included explicitly, there's no partial-scope shorthand. Admin keys are the one exception: set "admin": true and the sub-properties can be omitted entirely, since an admin key already has full access regardless of what the other fields say. This means a key handed to a build pipeline that only pins new files can be scoped to pinning.pin_file_to_ipfs alone, with no ability to unpin existing content, touch NFT operations, or read billing data, a meaningfully smaller blast radius than one shared admin key used everywhere.

Storing Credentials Safely Across Each Tool

Every AIOZ Pin surface, the REST API, the Node.js SDK, and the CLI, ultimately needs the same key and secret, just supplied differently. The SDK takes them directly in its constructor (new AiozPinClient(apiKey, secretKey)), the CLI accepts them as --key/--secret flags or reads them from a ~/.pinning/credentials JSON file so you don't retype them every invocation, and the raw REST API expects them wrapped into the appropriate header for whichever endpoint you're calling. Whichever layer you're using, avoid hardcoding the raw values into source code that ends up committed anywhere, environment variables or the CLI's credentials file keep the secret out of your codebase's history.

What Scoping Actually Limits If a Key Leaks

The practical reason scoping is worth setting up correctly, not just leaving every key at admin by default, shows up the moment credentials leak, and they eventually do: committed to a public repo by accident, exposed in a client-side bundle, pasted into the wrong Slack channel. An admin key leaked this way hands whoever finds it full account access: read billing, unpin anything, mint NFT records, everything. A key scoped to pinning.pin_file_to_ipfs alone, the kind a build pipeline actually needs, leaked the same way, only lets an attacker pin new files under your account, real damage in the sense of unwanted storage costs, but not the ability to delete existing pins, touch NFT operations, or read anything, because those permissions were never granted to that key in the first place. Scoping doesn't prevent a leak, nothing about key management does. It bounds what a leak actually costs, which is the entire point of generating separate keys per integration instead of one credential reused everywhere.

Revoking and Rotating Keys

DELETE /api/apiKeys/:id removes a key immediately, using the id returned when you generated it or from a GET /api/apiKeys/list call. Because keys are scoped individually, rotating credentials for one integration doesn't require touching any other key you've issued, generate a new scoped key for the specific use case, update that one integration, then delete the old key once you've confirmed the new one works.

Listing Keys to Audit What Exists

Before deciding what to rotate or tighten, it helps to actually see what's currently issued: GET /api/apiKeys/list returns every key on the account, its id, a truncated or masked view of the key itself, its scopes, and when it was created. For an account that's accumulated keys over time, one per integration as this article recommends, this is the practical starting point for a periodic security review: confirm every listed key still corresponds to something actually in use, and that none of them are scoped more broadly than the integration behind them actually needs. A key issued months ago for a project that's since been decommissioned, still valid, still capable of pinning or reading data, is exactly the kind of unnecessary exposure a five-minute audit against this endpoint catches before it becomes a real problem.

Frequently Asked Questions

Does every AIOZ Pin API endpoint use the same authentication header? No. Account and key-management endpoints use Authorization: Bearer <access_token>, while testAuthentication and the Nft API use raw pinning_api_key and pinning_secret_key headers instead.

Can an AIOZ Pin API key be limited to only pinning, with no delete access? Yes. Scopes are granular down to individual permissions like pin_file_to_ipfs or unpin, so a key can be issued with only the specific permissions an integration actually needs.

Do I need to specify every scope property when generating a key? For non-admin keys, yes, AIOZ Pin's docs specify all properties must be included. Admin keys are the exception: setting admin: true alone is sufficient, sub-properties can be omitted.

How do I revoke an AIOZ Pin API key? DELETE /api/apiKeys/:id, using the key's ID from when it was generated or from a GET /api/apiKeys/list call.

Where should I store my AIOZ Pin API key and secret? Not in source code. Use environment variables for the SDK or REST API, or the CLI's ~/.pinning/credentials file, so the raw secret doesn't end up committed to a repository.

References

We only send updates when meaningful changes ship, and you can unsubscribe anytime

Related Content

blog thumbnail

How AIOZ Pin's Wallet Billing Actually Works

AIOZ Pin has no credit card option. You fund an account with AIOZ tokens instead. Here is exactly how the wallet, deposits, and conversion actually work.

5 min readSeptember 13, 2026
blog thumbnail

Content Moderation on IPFS: What Actually Happens

Pinning services can remove their own copy of a file. They cannot remove it from IPFS. Here is exactly what a takedown does and does not accomplish.

5 min readSeptember 12, 2026
blog thumbnail

IPFS Transports: TCP vs. QUIC Explained

libp2p connections can run over more than one transport. Here is exactly what changes with QUIC instead of TCP, and why IPFS dials both at once.

5 min readSeptember 11, 2026
blog thumbnail

GossipSub: How IPFS's PubSub Layer Actually Works

The DHT answers who has a CID. GossipSub answers a different question: how do peers push real-time updates to everyone listening, without a lookup at all.

5 min readSeptember 10, 2026
blog thumbnail

Helia: IPFS's Modern JavaScript Implementation

js-ipfs is deprecated. Helia is what replaced it: a modular, TypeScript-first IPFS implementation built for the browser and Node.js. Here is how it fits.

5 min readSeptember 09, 2026
blog thumbnail

IPLD Selectors: Fetching Part of a DAG, Not All of It

Not every retrieval needs the whole DAG. IPLD Selectors describe exactly which nodes to traverse and match, so a client can fetch a slice, not everything.

5 min readSeptember 08, 2026