English
English
Appearance
English
English
Appearance
Pin existing IPFS content to your account. When you pin a CID, our cluster fetches the content from the IPFS network and keeps it permanently available.
POST /pin
Also available at POST /pins (IPFS Pinning Services API spec-compatible path — identical request and response):
curl -X POST https://api.ipfs.ninja/pins \
-H "X-Api-Key: bws_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"}'| Parameter | Type | Required | Description |
|---|---|---|---|
cid | string | Yes | IPFS content identifier. Any form accepted: CIDv0 (Qm…), CIDv1 base32 (bafk…, bafy…, and other codecs). |
description | string | No | Short description for your reference. Alias: name (matches the IPFS Pinning Services API field of the same name). |
metadata | object | No | Custom key-value pairs to attach to the pin. Max 10 keys. Keys must be alphanumeric or underscore, 1-64 characters. Values must be strings, max 256 characters each. Total metadata size must not exceed 4 KB. Alias: meta (Pinning Services API). |
multiaddresses | string[] | No | Optional swarm-connect hints. Up to 5 libp2p multiaddresses of peers that host the CID. Our cluster runs swarm connect against each one in parallel before the pin, so content on private / non-DHT peers is reachable without waiting for DHT discovery. Best-effort — a failed connect does not fail the pin. See Pinning from a private node. Alias: origins (Pinning Services API). |
folderId | string | No | Destination folder for the pinned row. Get folder IDs via GET /folders. Omit to land the pin at the root of your file list. |
metadata.fileType (or meta.fileType) is a reserved metadata key: when set to one of the values listed under Automatic type detection, it overrides auto-detection once the pin resolves to pinned, instead of the byte-sniffed type. Auto-detection for pins works the same way as uploads — the actual content bytes are sniffed via a bounded range fetch rather than trusted from a gateway Content-Type header, which used to default to a generic binary label more often than it should have.
Pinning Services API field-name aliases
POST /pin accepts and returns name, meta, origins, created; GET /pin/:cid / GET /pins/:cid return only the name and created aliases on status lookups. These are the IPFS Pinning Services API spec's field names, so tooling built against that spec's naming works here too. POST /pin, GET /pin/:cid, and DELETE /pin/:cid are also reachable at POST /pins, GET /pins/:cid, and DELETE /pins/:cid — same integration, just the path the spec expects. We don't implement the full Pinning Services API surface (no queued status, no delegates, and the by-id lookup is keyed on cid rather than the spec's requestid) — just this path and field-name alignment.
curl -X POST https://api.ipfs.ninja/pin \
-H "X-Api-Key: bws_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"description": "NFT metadata",
"metadata": {
"collection": "my-nfts",
"token_id": "42"
}
}'202 Accepted {
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"status": "pinning",
"description": "NFT metadata",
"name": "NFT metadata",
"meta": {
"collection": "my-nfts",
"token_id": "42"
},
"created": "2026-07-17T14:32:07.000Z",
"uris": {
"ipfs": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"url": "https://ipfs.ninja/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"
}
}For large DAGs (>500 blocks or >50 MB), the response includes an async: true flag:
{
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"status": "pinning",
"async": true,
"note": "Large DAG detected — pin running in background. Check status via GET /pin/bafybei…",
"uris": { ... }
}If the CID you want to pin lives on a peer that isn't participating in the public DHT — a private staging node, a self-hosted machine on a VPN, or a workstation behind NAT — the default pin flow won't find it. Passing one or more multiaddresses tells our cluster exactly where to look.
We run ipfs swarm connect <multiaddr> for each hint in parallel before the pin runs. If the connect succeeds, the pin's DAG fetch can talk to your peer directly instead of hunting through the DHT. If it fails, the pin still proceeds against the public network (best-effort semantics).
curl -X POST https://api.ipfs.ninja/pin \
-H "X-Api-Key: bws_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"description": "internal staging build",
"multiaddresses": [
"/ip4/203.0.113.42/tcp/4001/p2p/12D3KooWH3uVF6wv47WnArKHk5p6cvgCJEb74UTmxztmQDc298L3",
"/dns4/node.internal.example/tcp/443/wss/p2p/12D3KooWH3uVF6wv47WnArKHk5p6cvgCJEb74UTmxztmQDc298L3"
]
}'{
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"status": "pinning",
"origins": [
"/ip4/203.0.113.42/tcp/4001/p2p/12D3KooWH3uVF6wv47WnArKHk5p6cvgCJEb74UTmxztmQDc298L3",
"/dns4/node.internal.example/tcp/443/wss/p2p/12D3KooWH3uVF6wv47WnArKHk5p6cvgCJEb74UTmxztmQDc298L3"
],
"swarmConnected": [
{ "multiaddr": "/ip4/203.0.113.42/tcp/4001/p2p/12D3KooW…", "ok": true, "strings": ["connect 12D3KooW… success"] },
{ "multiaddr": "/dns4/node.internal.example/tcp/443/…", "ok": false, "error": "dial to peer: no route" }
],
"info": {
"swarmConnected": [
{ "multiaddr": "/ip4/203.0.113.42/tcp/4001/p2p/12D3KooW…", "ok": true, "strings": ["connect 12D3KooW… success"] },
{ "multiaddr": "/dns4/node.internal.example/tcp/443/…", "ok": false, "error": "dial to peer: no route" }
]
},
"uris": { … }
}Common shapes are supported: /ip4, /ip6, /dns4, /dns6, /dns, /dnsaddr transports; /tcp or /udp protocols; optional /quic-v1, /quic, /ws, /wss, /http, /https, /webtransport, /webrtc-direct upgrades. The multiaddress must end with /p2p/<peerId>. Cap: up to 5 hints per pin.
Getting your node's multiaddress
On the peer you want to pin from, run ipfs id and copy any of the Addresses entries that ends in /p2p/<PeerID>. Prefer public routable addresses (/ip4/YOUR_PUBLIC_IP/…) or DNS-based ones (/dnsaddr/your.domain/…) so our cluster can reach the peer from AWS.
Pinning very large directories
POST /pin is for content that already lives on the IPFS network — the cluster fetches the DAG block-by-block from peers, which can take several minutes for directories with 1,000+ files. During that fetch window, some child files may not yet be locally available and gateway requests to them may time out. Once the parent's status flips to pinned, every child is locally available and accessible via your gateway.
If you have the files locally (instead of just a CID), prefer CAR import for large NFT collections or datasets — it uploads the entire DAG to IPFS Ninja in one atomic request, so there's no fetch window and no partial-pin state. Create a CAR with:
npx ipfs-car pack ./my-collection -o collection.carThen import it via POST /upload/new with car: true.
TIP
Pinning is asynchronous. The response returns immediately with status pinning. Poll the status endpoint to check when pinning completes.
GET /pin/:cid
Also available at GET /pins/:cid (same response).
| Parameter | Type | Required | Description |
|---|---|---|---|
cid | string | Yes | The CID you're checking. |
200 OK {
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"status": "pinned",
"sizeMB": 0.042,
"fileName": "NFT metadata",
"pinnedAt": 1711036800000,
"name": "NFT metadata",
"created": "2024-03-21T16:00:00.000Z",
"info": {
"sizeMB": 0.042,
"fileName": "NFT metadata"
},
"uris": {
"ipfs": "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"url": "https://ipfs.ninja/ipfs/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"
}
}| Status | Meaning |
|---|---|
pinning | Content is being fetched from the IPFS network. Poll again in a few seconds. |
pinned | Content is pinned and available through your account and gateway. |
failed | Content could not be found on the IPFS network. The CID may be invalid or the content is no longer available. |
DELETE /pin/:cid
Also available at DELETE /pins/:cid (same request and response).
Removes the file record for the CID from your account and decrements your storage usage. If the CID is a directory pin or a CAR upload, its child-file accounting rows are cleaned up too. The content is unpinned from the cluster only if no other IPFS Ninja user still holds the same CID — deleting your pin never affects another account's copy.
| Parameter | Type | Required | Description |
|---|---|---|---|
cid | string | Yes | The CID to delete. |
curl -X DELETE https://api.ipfs.ninja/pin/bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi \
-H "X-Api-Key: bws_your_api_key_here"200 OK {
"success": true,
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"sizeMBFreed": 0.042,
"childFilesDeleted": 0,
"clusterUnpin": "ok"
}clusterUnpin reflects what happened on the IPFS cluster: ok (unpinned), not_pinned (already gone from the cluster), failed (the unpin attempt errored, but the file record was still deleted), or skipped_shared (another user still holds this CID, so the underlying content stays pinned).
| Status | Meaning |
|---|---|
404 | No file record for this CID under your account. |
POST /pinWARNING
Pinning time depends on file size and network availability. Small files typically pin in seconds. Large files or rarely-pinned content may take minutes.
Pinned content counts toward your plan's storage limit. The file size is recorded when pinning completes. If you approach your storage limit, you can free space by deleting unused files or upgrade for more capacity.