{
 "slug": "pinata",
 "name": "Pinata",
 "url": "https://pinata.cloud",
 "domain": "pinata.cloud",
 "category": "file-storage",
 "category_name": "File storage",
 "tested_at": "2026-10-06",
 "run": "20261006T085154Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261001T204253Z",
   "date": "2026-10-01",
   "level": 1,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   },
   "drives": 3
  },
  {
   "run": "20261006T085154Z",
   "date": "2026-10-06",
   "level": 1,
   "engine": {
    "runner": "omp",
    "model": "claude-opus-5-5",
    "driver": 2,
    "signed": true,
    "inbox": [
     "agentdrives.com"
    ],
    "robots": "start"
   }
  }
 ],
 "level": 1,
 "level_name": "Needs a person",
 "level_selfhost": null,
 "entry": "closed",
 "door": {
  "passed": 0,
  "tries": 3,
  "self_start": false
 },
 "badges": [],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "no",
   "text": "Can't get in on its own",
   "at": "signup"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "unreached",
   "text": "Work not measured"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "agent_rail"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "unreached",
   "text": "Leaving not reached",
   "how": "no-account"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "yes",
   "text": "Docs agents can read: llms.txt, an OpenAPI and an MCP server",
   "have": [
    "llms_txt",
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "no",
   "text": "Can't get in on its own",
   "at": "signup",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "unreached",
   "text": "Work not measured",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "unreached",
   "text": "Payment not reached",
   "value": "unreached",
   "route": "agent_rail",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "unreached",
   "text": "Leaving not reached",
   "how": "no-account",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "person",
   "label": "A person sets it up",
   "routes": [],
   "minutes": null,
   "core": null
  }
 ],
 "minutes": null,
 "next": {
  "to": 2,
  "text": "Next: let an agent sign up on its own"
 },
 "stop": "signup",
 "core": "1/7",
 "scores": {
  "coverage": null,
  "reliability": null,
  "resilience": null,
  "setup": 100,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 100,
  "security": null,
  "standards": [
   {
    "standard": "MCP",
    "state": "behind",
    "behind": 1,
    "value": "2025-11-25"
   },
   {
    "standard": "MCP discovery",
    "state": "behind",
    "behind": null,
    "value": "legacy"
   },
   {
    "standard": "OpenAPI",
    "state": "behind",
    "behind": 2,
    "value": "3.0.0"
   },
   {
    "standard": "A2A",
    "state": "behind",
    "behind": 1,
    "value": "0.3"
   }
  ]
 },
 "reliability_method": null,
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": null,
 "after_wall": null,
 "coverage_source": "computed",
 "driver": {
  "version": 2,
  "model": "claude-opus-5-5",
  "profile": "full",
  "assisted": false,
  "handoff": null,
  "prompt_sha": "f3d0adeeb256",
  "kb_version": "2+overlay-9e43028a2c",
  "identity": null
 },
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": "claude-opus-5-5",
  "driver": 2,
  "signed": true,
  "inbox": [
   "agentdrives.com"
  ],
  "robots": "start"
 },
 "same_level_drives": 4,
 "drives": 4,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": {
  "rung": "signup",
  "vendor": "Cloudflare Turnstile (on the Clerk sign-up form)",
  "visible": true,
  "type": "network",
  "human": null,
  "how": "Let verified bots and signed agents past the check on sign-up: in Cloudflare, add a WAF custom rule that skips the bot challenge on your sign-up paths for verified bots and for signed agents (rule field cf.bot_management.signed_agent; since 1 July 2026 signed agents count as verified bots), and render Turnstile only when the request is not from a verified agent.",
  "signed": true
 },
 "agent_pass": null,
 "who_gets_in": {
  "server": {
   "state": "form"
  },
  "signed": {
   "state": "page",
   "kind": "signup",
   "at": "2026-10-12"
  },
  "browser": {
   "state": "through",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "docs.pinata.cloud/llms.txt (243 lines), .md pages and Accept: text/markdown all work headless; API reference per endpoint with scopes."
  },
  "signup": {
   "status": "human",
   "note": "Web form only (Clerk-hosted at app.pinata.cloud/auth/signup). After Continue a visible Cloudflare Turnstile 'Verify you are human' replaces the form."
  },
  "verify": {
   "status": "",
   "note": "Not reached: no account (sign-up stopped at Turnstile).",
   "reached": false
  },
  "credentials": {
   "status": "",
   "note": "API keys (JWT) are created only in the web app (Developers > API Keys); no account, so none. No OAuth/device flow or agent registration found.",
   "via": "",
   "reached": false
  },
  "first_call": {
   "status": "",
   "note": "Authenticated calls return 401 without a JWT. Without an account, an agent can only read public CIDs through the public gateway (and via the MCP fetchFromGateway tool).",
   "reached": false
  },
  "first_action": {
   "status": "",
   "note": "No upload possible: 401 on uploads.pinata.cloud/v3/files. The account-free MPP upload returns a real 402 that we could not pay (no wallet).",
   "reached": false
  },
  "pay": {
   "status": "",
   "grade": "P3",
   "rails": [
    "MPP (Tempo, USDC) on mpp.pinata.cloud",
    "card on web Billing page"
   ],
   "rail_ids": [
    "mpp",
    "card"
   ],
   "first_party": true,
   "rail_scope": "side",
   "trial_path": "free tier",
   "note": "mpp.pinata.cloud answers 402 + WWW-Authenticate: Payment method=\"tempo\" intent=\"charge\" for account-free upload and download (listed first-party on mpp.dev). That buys side endpoints only, not the account plans; plans (Picnic $20/mo, Fiesta $100/mo) are paid by card on the web Billing page. Not paid: no wallet or card.",
   "detected_grade": "P4",
   "exercised": false,
   "reached": false
  },
  "cancel": {
   "status": "",
   "grade": "n/a",
   "note": "No plan was started. Billing docs describe plan changes only on the web Billing page.",
   "reached": false
  },
  "delete": {
   "status": "",
   "note": "No account was created, so nothing to delete; the docs show no account-deletion route.",
   "account": false,
   "reached": false
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-06",
  "source": "drive",
  "options": [
   {
    "id": "mpp",
    "name": "MPP",
    "kind": "agent-rail",
    "first_party": true,
    "lead": false,
    "networks": [],
    "testnet": false
   },
   {
    "id": "card",
    "name": "Card checkout",
    "kind": "checkout",
    "first_party": false,
    "lead": false,
    "networks": [],
    "testnet": false
   }
  ],
  "agentic": [
   "mpp"
  ],
  "paid": null,
  "exercised": false,
  "detected_grade": "P4",
  "trial": {
   "no_card": null,
   "card_required": null,
   "free_plan": true
  },
  "owner_fixes": [
   {
    "title": "List your plans on Stripe Projects",
    "how": "Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev)."
   },
   {
    "title": "Sell the plan or credits over the rail, not only side endpoints",
    "how": "Let the paid call buy what the product sells, so the rail covers the whole product."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": true,
  "mcp": "official",
  "llms_txt": true,
  "sandbox": false
 },
 "surface_notes": {
  "api": "REST v3 (api.pinata.cloud, uploads.pinata.cloud), JWT bearer; errors are JSON but not problem+json",
  "openapi": "only the x402 Payment Instructions API (pinata-x402-api-v3.yaml, openapi 3.0.0); no spec listed for the core files API",
  "mcp": "official stdio pinata-mcp 0.2.0, 35 tools, the older 25 Nov 2025 spec; docs MCP (Mintlify) is modern 28 Jul 2026"
 },
 "can_do": [
  "Read the docs headless (llms.txt, markdown pages, docs MCP)",
  "Fetch public IPFS content by CID through gateway.pinata.cloud or the MCP fetchFromGateway tool, without an account",
  "Get a real MPP 402 challenge for account-free upload and download on mpp.pinata.cloud"
 ],
 "cannot_do": [
  {
   "what": "Create an account",
   "why": "Visible Cloudflare Turnstile on the web sign-up form; no headless sign-up route"
  },
  {
   "what": "Get an API key",
   "why": "Keys are created only in the web app after sign-in"
  },
  {
   "what": "Upload, update, list, delete, pin or group files",
   "why": "Every route needs a JWT we could not get"
  },
  {
   "what": "Upload account-free via MPP",
   "why": "Needs a USDC payment on Tempo; we have no wallet"
  }
 ],
 "blockers": [
  "Visible Cloudflare Turnstile on the sign-up form",
  "API keys only in the web dashboard"
 ],
 "tips_for_owner": [
  "Let verified signed agents skip Turnstile",
  "Add a headless way to get an API key",
  "Upgrade pinata-mcp to MCP (the 28 Jul 2026 spec)",
  "Return errors as RFC 9457 problem+json"
 ],
 "tips_for_agents": [
  "Docs: start from https://docs.pinata.cloud/llms.txt; every page has a .md version, and the docs MCP at docs.pinata.cloud/mcp is 2026-07-28.",
  "Without an account you can still read public CIDs at https://gateway.pinata.cloud/ipfs/<cid>.",
  "With a wallet holding USDC on Tempo, mpp.pinata.cloud lets you upload (POST /v1/pin/public?fileSize=) and download without an account.",
  "Sign-up needs a human (Turnstile); once a human creates an admin JWT, pinata-mcp (35 tools) or the v3 REST API cover files, groups, signatures and pin-by-CID."
 ],
 "selfhost": null,
 "summary": "Pinata's docs are very agent-friendly (llms.txt, markdown, a modern docs MCP), and it runs a first-party MPP endpoint that sells account-free IPFS uploads and downloads. But sign-up is a web form behind a visible Cloudflare Turnstile and API keys come only from the dashboard, so our agent got no account: it could only read public CIDs through the gateway.",
 "wall": "Cloudflare Turnstile on the sign-up form",
 "plan_scope": "",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Pinata is a file-storage service built on IPFS (a decentralized file system). An agent could read its documentation and fetch existing public files without any account, and even found a real pay-per-use option, but it could not create an account itself because a visible human-verification check blocked the sign-up form to step in.",
  "can_do": [
   "Read all the product documentation automatically",
   "Download a publicly shared file without needing an account",
   "Discover a real pay-as-you-go option for uploading/downloading without an account (though paying it needs a cryptocurrency wallet the agent didn't have)"
  ],
  "cannot_do": [
   {
    "what": "Create an account",
    "why": "A visible human-verification puzzle appears on the sign-up form"
   },
   {
    "what": "Upload, list, update, delete, or pin files",
    "why": "All of these need an account key, and no account could be created"
   },
   {
    "what": "Pay for account-free uploads",
    "why": "The pay-per-use option needs a cryptocurrency wallet, which the agent did not have"
   }
  ]
 },
 "plan_gated": [
  {
   "capability": "Private IPFS upload/retrieve",
   "plan": "paid",
   "evidence": "capability map plan=paid; not reachable without an account"
  },
  {
   "capability": "Dedicated gateway with custom domain",
   "plan": "paid",
   "evidence": "capability map plan=paid; not reachable without an account"
  }
 ],
 "reply": null,
 "capabilities": [
  {
   "id": "cap-01",
   "group": "Files",
   "capability": "Upload a file to IPFS",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/files (uploads.pinata.cloud)",
    "mcp": "uploadFile",
    "cli": "pinata upload",
    "ui": "App > Files > Upload"
   },
   "check": "GET /v3/files/{network}/{id} returns the file with its CID and size",
   "source": "https://docs.pinata.cloud/quickstart; https://docs.pinata.cloud/api-reference/endpoint/upload-a-file; https://docs.pinata.cloud/tools/mcp/tools"
  },
  {
   "id": "cap-02",
   "group": "Files",
   "capability": "Retrieve a file by CID through a gateway",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "GET https://{gateway}/ipfs/{cid}",
    "mcp": "fetchFromGateway",
    "cli": "pinata gateways",
    "ui": "App > Files > open file"
   },
   "check": "HTTP GET to the gateway URL for the CID returns 200 with the file bytes",
   "source": "https://docs.pinata.cloud/gateways/retrieving-files; https://docs.pinata.cloud/quickstart; https://docs.pinata.cloud/tools/mcp/tools"
  },
  {
   "id": "cap-03",
   "group": "Files",
   "capability": "Update a file's name and metadata",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "PUT /v3/files/{network}/{id}",
    "mcp": "updateFile",
    "cli": "pinata ipfs",
    "ui": "App > Files > edit"
   },
   "check": "GET /v3/files/{network}/{id} shows the new name/keyvalues",
   "source": "https://docs.pinata.cloud/api-reference/endpoint/update-file; https://docs.pinata.cloud/tools/mcp/tools"
  },
  {
   "id": "cap-04",
   "group": "Files",
   "capability": "Delete a file",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "DELETE /v3/files/{network}/{id}",
    "mcp": "deleteFile",
    "cli": "pinata ipfs",
    "ui": "App > Files > delete"
   },
   "check": "GET /v3/files/{network}/{id} returns 404 / NOT_FOUND after deletion",
   "source": "https://docs.pinata.cloud/api-reference/endpoint/delete-file-by-id; https://docs.pinata.cloud/tools/mcp/tools"
  },
  {
   "id": "cap-05",
   "group": "Files",
   "capability": "List and query uploaded files",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "GET /v3/files/{network}",
    "mcp": "searchFiles",
    "cli": "pinata ipfs",
    "ui": "App > Files"
   },
   "check": "GET /v3/files/{network}?name= returns matching file records",
   "source": "https://docs.pinata.cloud/files/listing-files; https://docs.pinata.cloud/api-reference/endpoint/list-files; https://docs.pinata.cloud/tools/mcp/tools"
  },
  {
   "id": "cap-06",
   "group": "Files",
   "capability": "Pin an existing CID (not just uploaded files)",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/files/public/pin_by_cid",
    "mcp": null,
    "cli": "pinata ipfs",
    "ui": null
   },
   "check": "GET /v3/files/public/pin_by_cid shows the request with status 'pinned'",
   "source": "https://docs.pinata.cloud/api-reference/endpoint/pin-by-cid; https://docs.pinata.cloud/api-reference/endpoint/query-pin-requests"
  },
  {
   "id": "cap-07",
   "group": "Private storage",
   "capability": "Upload and retrieve files on the private IPFS network",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v3/files with network=private; GET /v3/files/private/{id}/download_url",
    "mcp": "uploadFile(network=private), createPrivateDownloadLink",
    "cli": "pinata ipfs",
    "ui": "App > Files > Private"
   },
   "check": "an unsigned gateway request to the private CID is rejected, while a signed download link returned by the API succeeds",
   "source": "https://docs.pinata.cloud/files/private-ipfs; https://pinata.cloud/private-ipfs-storage; https://docs.pinata.cloud/api-reference/endpoint/get-signed-url"
  },
  {
   "id": "cap-10",
   "group": "Groups",
   "capability": "Create a group and add/remove files from it",
   "weight": "core",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/groups/{network}, POST /v3/groups/{network}/{id}/ids/{fileId}",
    "mcp": "createGroup, addFileToGroup, removeFileFromGroup",
    "cli": "pinata ipfs",
    "ui": "App > Files > Groups"
   },
   "check": "GET /v3/groups/{network}/{id} lists the file after adding and no longer lists it after removal",
   "source": "https://pinata.cloud/groups; https://docs.pinata.cloud/files/file-groups; https://docs.pinata.cloud/api-reference/endpoint/add-file-to-group"
  },
  {
   "id": "cap-13",
   "group": "Gateways",
   "capability": "Create a dedicated IPFS gateway with a custom domain",
   "weight": "core",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v3/ipfs/gateways; POST .../custom_domains",
    "mcp": null,
    "cli": "pinata ipfs gateways",
    "ui": "App > Gateways"
   },
   "check": "GET /v3/ipfs/gateways lists the new gateway, and a request to the custom domain resolves content",
   "source": "https://pinata.cloud/dedicated-ipfs-gateways; https://docs.pinata.cloud/gateways/dedicated-ipfs-gateways; https://docs.pinata.cloud/api-reference/endpoint/ipfs/create-gateway"
  },
  {
   "id": "cap-08",
   "group": "Files",
   "capability": "Create a time-limited signed access/download link",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/files/{network}/{id}/download_url (Create Download Link)",
    "mcp": "createLink, createPrivateDownloadLink",
    "cli": null,
    "ui": "App > Files > share"
   },
   "check": "the returned URL serves the file before 'expires' and returns 403/expired after",
   "source": "https://docs.pinata.cloud/api-reference/endpoint/get-signed-url; https://docs.pinata.cloud/files/presigned-urls; https://docs.pinata.cloud/tools/mcp/tools"
  },
  {
   "id": "cap-09",
   "group": "Files",
   "capability": "Create a presigned upload URL for client-side uploads",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/files/sign (Create Signed Upload URL)",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "a POST multipart upload to the returned presigned URL succeeds and the resulting file appears via List Files",
   "source": "https://docs.pinata.cloud/files/presigned-urls; https://docs.pinata.cloud/api-reference/endpoint/create-signed-upload-url"
  },
  {
   "id": "cap-11",
   "group": "Groups",
   "capability": "Rename, make public/private, or delete a group",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "PUT /v3/groups/{network}/{id}; DELETE /v3/groups/{network}/{id}",
    "mcp": "updateGroup, deleteGroup",
    "cli": null,
    "ui": "App > Files > Groups"
   },
   "check": "GET /v3/groups/{network}/{id} reflects the new name/visibility, or returns 404 after delete",
   "source": "https://docs.pinata.cloud/api-reference/endpoint/update-group; https://docs.pinata.cloud/api-reference/endpoint/delete-group"
  },
  {
   "id": "cap-12",
   "group": "Metadata",
   "capability": "Attach custom key-value metadata to a file",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "PUT /v3/files/{network}/{id} with keyvalues",
    "mcp": "uploadFile(keyvalues), updateFile(keyvalues)",
    "cli": null,
    "ui": "App > Files > edit metadata"
   },
   "check": "GET /v3/files/{network}/{id} returns the keyvalues object, and List Files filters by that key/value",
   "source": "https://pinata.cloud/kv-storage; https://docs.pinata.cloud/files/key-values"
  },
  {
   "id": "cap-14",
   "group": "Gateways",
   "capability": "Restrict gateway access by key, IP, or host origin",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v3/ipfs/gateways/{id}/restrictions/{type}",
    "mcp": null,
    "cli": null,
    "ui": "App > Gateways > Access Controls"
   },
   "check": "a request from a disallowed origin/IP to the gateway is rejected after the restriction is created",
   "source": "https://pinata.cloud/access-control; https://docs.pinata.cloud/gateways/gateway-access-controls; https://docs.pinata.cloud/api-reference/endpoint/ipfs/create-gateway-host-origin-restriction"
  },
  {
   "id": "cap-15",
   "group": "Gateways",
   "capability": "Resize/convert images on the fly via gateway URL parameters",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "GET https://{gateway}/ipfs/{cid}?img-width=...&img-format=webp",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "fetching the gateway URL with img-width/img-format params returns an image with the requested dimensions/content-type",
   "source": "https://pinata.cloud/image-optimization; https://docs.pinata.cloud/gateways/image-optimizations"
  },
  {
   "id": "cap-16",
   "group": "Gateways",
   "capability": "Install a gateway plugin (e.g. content-addressable signatures, hot swaps)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v3/ipfs/gateways/{id}/plugins",
    "mcp": null,
    "cli": null,
    "ui": "App > Gateways > Plugins"
   },
   "check": "GET /v3/ipfs/gateways/{id}/plugins lists the installed plugin and gateway responses show its effect (e.g. pinata-signature header)",
   "source": "https://docs.pinata.cloud/gateways/plugins/getting-started; https://docs.pinata.cloud/api-reference/endpoint/ipfs/install-gateway-plugin"
  },
  {
   "id": "cap-18",
   "group": "Trust",
   "capability": "Cryptographically sign a CID and verify the signature",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/signature/{network}/{cid}; GET .../{cid}",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "GET Signature for a CID returns the stored EIP-712 signature, and verifyTypedData confirms it against the signer address",
   "source": "https://docs.pinata.cloud/files/signatures; https://docs.pinata.cloud/api-reference/endpoint/add-signature-to-cid"
  },
  {
   "id": "cap-19",
   "group": "AI/Vectors",
   "capability": "Vectorize a file and run semantic search over it",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v3/vectorize/{network}/{id}; POST /v3/vector_query/{network}/{groupId}",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "after vectorizing, Query File Vectors returns the file among semantically relevant results",
   "source": "https://docs.pinata.cloud/files/vectors; https://docs.pinata.cloud/api-reference/endpoint/vectorize-file; https://docs.pinata.cloud/api-reference/endpoint/query-file-vectors"
  },
  {
   "id": "cap-20",
   "group": "NFT backup",
   "capability": "Back up a wallet's NFT IPFS content",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "App > NFT Backup"
   },
   "check": "after syncing a wallet and backing up, the NFT's CIDs appear in the account's pinned files",
   "source": "https://docs.pinata.cloud/files/nft-backup/overview; https://pinata.cloud/blog/how-to-back-up-your-ipfs-nfts/"
  },
  {
   "id": "cap-21",
   "group": "Analytics",
   "capability": "View request and bandwidth analytics for files/gateways",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": "GET /v3/ipfs/gateway_analytics_top; GET /v3/ipfs/gateway_analytics_time_series",
    "mcp": null,
    "cli": null,
    "ui": "App > Analytics"
   },
   "check": "GET gateway analytics endpoint returns non-zero request/bandwidth counts after traffic has occurred",
   "source": "https://pinata.cloud/analytics; https://docs.pinata.cloud/api-reference/endpoint/ipfs/top-gateway-analytics; https://docs.pinata.cloud/sdk/analytics/requests"
  },
  {
   "id": "cap-22",
   "group": "Automation",
   "capability": "Subscribe to webhooks for account events (upload, delete, etc.)",
   "weight": "secondary",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "App > Webhooks"
   },
   "check": "triggering a subscribed event (e.g. uploading a file) delivers a signed payload to the configured endpoint, visible in the webhook dashboard log",
   "source": "https://docs.pinata.cloud/account-management/webhooks"
  },
  {
   "id": "cap-23",
   "group": "Monetization",
   "capability": "Monetize content via x402 payment instructions",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v1/payment_instructions; POST /v1/payment_instructions/{id}/cids",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "fetching the associated CID without payment returns an x402 payment-required response, and succeeds after payment per the x402 quick start",
   "source": "https://docs.pinata.cloud/files/x402/intro; https://docs.pinata.cloud/api-reference/endpoint/x402/payment-instructions-create; https://docs.pinata.cloud/files/x402/x402-accessing-paid-content"
  },
  {
   "id": "cap-25",
   "group": "Agents",
   "capability": "Deploy and run a hosted AI agent instance from a template",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "Agents HTTP API",
    "mcp": null,
    "cli": "pinata agents (Agents CLI)",
    "ui": "agents.pinata.cloud"
   },
   "check": "GET agent status via the HTTP API or console shows the agent running after deployment from a template",
   "source": "https://pinata.cloud/ (Launch agents); https://docs.pinata.cloud/agents/overview; https://docs.pinata.cloud/agents/templates/overview"
  },
  {
   "id": "cap-26",
   "group": "Agents",
   "capability": "Chat with a deployed agent",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "Agents HTTP API",
    "mcp": null,
    "cli": "pinata agents",
    "ui": "agents.pinata.cloud > Chat"
   },
   "check": "a sent chat message produces a visible agent reply in the chat transcript/logs",
   "source": "https://docs.pinata.cloud/agents/chat"
  },
  {
   "id": "cap-27",
   "group": "Agents",
   "capability": "Assign and track agent work on an issues/kanban board",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "agents.pinata.cloud > Issues & Boards"
   },
   "check": "creating an issue and assigning it moves it across board columns and produces a reviewable diff",
   "source": "https://docs.pinata.cloud/agents/issues"
  },
  {
   "id": "cap-28",
   "group": "Agents",
   "capability": "Schedule recurring agent prompts (Tasks)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "agents.pinata.cloud > Tasks"
   },
   "check": "a scheduled task runs at its configured interval, visible in agent logs with a timestamped execution",
   "source": "https://docs.pinata.cloud/agents/tasks"
  },
  {
   "id": "cap-29",
   "group": "Agents",
   "capability": "Expose an agent service to the internet via a domain/route",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "agents.pinata.cloud > Domains & Routes"
   },
   "check": "an HTTP request to the configured public route reaches the service running inside the agent container",
   "source": "https://docs.pinata.cloud/agents/routes"
  },
  {
   "id": "cap-30",
   "group": "Agents",
   "capability": "Connect an agent to chat channels (Telegram, Slack, Discord)",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "agents.pinata.cloud > Channels"
   },
   "check": "a message sent in the connected channel produces a response from the agent",
   "source": "https://docs.pinata.cloud/agents/channels"
  },
  {
   "id": "cap-31",
   "group": "Agents",
   "capability": "Browse/edit an agent's workspace files and view snapshots",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "agents.pinata.cloud > Files & Snapshots"
   },
   "check": "editing a file in the workspace UI and restoring a prior snapshot changes the file content back",
   "source": "https://docs.pinata.cloud/agents/snapshots"
  },
  {
   "id": "cap-32",
   "group": "Agents",
   "capability": "Run LLM inference through an OpenAI-compatible endpoint",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v1/chat/completions (Pinata Inference)",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "a chat completion request returns a model-generated response, and Credits balance decreases accordingly",
   "source": "https://docs.pinata.cloud/inference/overview; https://docs.pinata.cloud/inference/chat-completions; https://docs.pinata.cloud/inference/credits"
  },
  {
   "id": "cap-33",
   "group": "Team",
   "capability": "Invite teammates to a shared workspace",
   "weight": "secondary",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "App > Workspaces"
   },
   "check": "an invited teammate's email can access the shared workspace's files after accepting the invite",
   "source": "https://docs.pinata.cloud/account-management/workspaces; https://docs.pinata.cloud/quickstart"
  },
  {
   "id": "cap-17",
   "group": "Gateways",
   "capability": "Swap a CID to redirect to a different CID",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": "POST /v3/files/public/swap/{cid}",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "fetching the original CID through the gateway returns the content of the swapped-to CID, and GET swap history shows the change",
   "source": "https://docs.pinata.cloud/api-reference/endpoint/add-swap; https://docs.pinata.cloud/gateways/plugins/hot-swaps"
  },
  {
   "id": "cap-24",
   "group": "Automation",
   "capability": "Upload/retrieve IPFS content without an account via crypto micropayments (MPP server)",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "MPP server endpoints",
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "an MPP quick-start upload returns a CID retrievable via gateway without a Pinata account JWT",
   "source": "https://docs.pinata.cloud/files/mpp/overview; https://docs.pinata.cloud/files/mpp/quickstart"
  },
  {
   "id": "cap-34",
   "group": "Account admin",
   "capability": "Create and revoke scoped API keys",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": "POST /v3/pinata/keys; PUT /v3/pinata/keys/{id}",
    "mcp": null,
    "cli": "pinata keys",
    "ui": "App > API Keys"
   },
   "check": "List API Keys shows the new key, and requests using it fail after it is revoked",
   "source": "https://docs.pinata.cloud/account-management/api-keys; https://docs.pinata.cloud/api-reference/endpoint/v3-create-api-key; https://docs.pinata.cloud/api-reference/endpoint/v3-revoke-api-key"
  },
  {
   "id": "cap-35",
   "group": "Account admin",
   "capability": "Register an AI agent on-chain (ERC-8004)",
   "weight": "peripheral",
   "plan": "paid",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": null
   },
   "check": "following the ERC-8004 quickstart produces an on-chain registration transaction referencing an IPFS-hosted agent service document",
   "source": "https://docs.pinata.cloud/tools/erc-8004/quickstart; https://docs.pinata.cloud/tools/erc-8004/services"
  },
  {
   "id": "cap-36",
   "group": "Account admin",
   "capability": "Upgrade/change billing plan and track usage limits",
   "weight": "peripheral",
   "plan": "free",
   "surfaces": {
    "api": null,
    "mcp": null,
    "cli": null,
    "ui": "App > Billing; pinata.cloud/pricing"
   },
   "check": "selecting a paid plan on the pricing page updates the account's storage/gateway limits shown in Billing",
   "source": "https://pinata.cloud/pricing; https://docs.pinata.cloud/account-management/billing; https://docs.pinata.cloud/account-management/limits"
  }
 ],
 "attempts": [
  {
   "t": "00:31",
   "cap": "docs",
   "capability": "Find docs",
   "task": "Fetch llms.txt and markdown docs",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET https://docs.pinata.cloud/llms.txt 200 text/plain, 243 lines; .md pages (quickstart.md, tools/mcp/overview.md) 200",
   "notes": "Mintlify docs; OpenAPI specs listed only for x402 API (pinata-x402-api-v3.yaml, -v1.yaml)",
   "quality": {
    "docs_match": "match"
   }
  },
  {
   "t": "00:58",
   "cap": "pay",
   "capability": "Pay the agent way",
   "task": "Probe 402 on mpp.pinata.cloud upload and download",
   "route": "api",
   "documented": true,
   "result": "partial",
   "verified": true,
   "evidence": "POST https://mpp.pinata.cloud/v1/pin/public?fileSize=1024 -> 402 application/problem+json, WWW-Authenticate: Payment realm=\"MPP Payment\", method=\"tempo\", intent=\"charge\", request={\"amount\":\"1000\",\"currency\":\"0x20C0...8b50\",\"methodDetails\":{\"chainId\":4217}}; GET /v1/pin/public/{cid} -> same 402. mpp.dev/api/services lists pinata integration first-party.",
   "notes": "MPP on Tempo USDC, first-party, but only buys account-free side endpoints (upload/download), not the Pinata account plans. Not paid: no wallet. No x402. subdomains: x402.pinata.cloud does not resolve; /.well-known/ucp 404. Billing docs: card only via web billing page.",
   "quality": {
    "error_legibility": "clear",
    "docs_match": "match"
   }
  },
  {
   "t": "02:23",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Look for a headless sign-up route (API/CLI/auth.md)",
   "route": "none",
   "documented": true,
   "result": "failed",
   "verified": false,
   "evidence": "Docs only link https://app.pinata.cloud/register (web form); CLI 'pinata auth' takes an existing JWT; /auth.md 404, api.pinata.cloud/.well-known/oauth-protected-resource 404 INVALID_ROUTE",
   "notes": "No documented headless sign-up; trying the browser once."
  },
  {
   "t": "03:01",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Submit the web sign-up form at app.pinata.cloud/auth/signup",
   "route": "browser",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "After Continue on the filled form (first/last name, email, password) the form is replaced by a visible Cloudflare Turnstile 'Verify you are human' widget (screenshot browser/shots/003.png). Sign-up form is Clerk-hosted.",
   "notes": "Visible Turnstile on sign-up; not solved by us. Asking a human (own browser).",
   "quality": {
    "error_legibility": "n/a"
   }
  },
  {
   "t": "03:10",
   "cap": "signup",
   "capability": "Sign up",
   "task": "Hand the Turnstile step to a human (own browser)",
   "route": "browser",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "",
   "notes": "Cloudflare Turnstile on the Clerk sign-up form. No account, so verify, credentials, the first call and the first action are blocked."
  },
  {
   "t": "05:30",
   "cap": "discovery",
   "capability": "MCP version",
   "task": "stdio pinata-mcp 0.2.0: server/discover then initialize offering 2026-07-28",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "server/discover -> -32601 Method not found; initialize -> protocolVersion \"2025-11-25\", serverInfo Pinata 0.2.0; tools/list 35 tools",
   "notes": "Legacy (initialize-based) official stdio server; no remote product MCP (mcp.pinata.cloud does not resolve)."
  },
  {
   "t": "05:30",
   "cap": "discovery",
   "capability": "Docs MCP",
   "task": "POST server/discover on https://docs.pinata.cloud/mcp",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "200 application/json result.supportedVersions [\"2026-07-28\"]; initialize answers 2025-11-25 over SSE",
   "notes": "Mintlify-hosted docs search MCP, no auth."
  },
  {
   "t": "05:30",
   "cap": "discovery",
   "capability": "Cards",
   "task": "Probe server card, AI catalog, A2A card, agent skills",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "docs.pinata.cloud/.well-known/mcp/server-card.json 200 application/json (docs MCP); /.well-known/agent-card.json 200 application/json protocolVersion 0.3; /.well-known/agent-skills/index.json 200 (skill 'pinata'); ai-catalog.json 404 on pinata.cloud and docs; pinata.cloud/.well-known/agent-card.json 404",
   "notes": "All cards are Mintlify-generated for the docs site, not the product."
  },
  {
   "t": "05:30",
   "cap": "discovery",
   "capability": "AI preferences",
   "task": "robots.txt Content-Usage / Content-signal and headers",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "pinata.cloud/robots.txt: 'User-agent: * Allow: /' no preference lines; docs.pinata.cloud/robots.txt: 'Content-Signal: ai-train=yes, search=yes, ai-input=yes' (Cloudflare Content Signals, parses); no Content-Usage header",
   "notes": ""
  },
  {
   "t": "05:30",
   "cap": "discovery",
   "capability": "Markdown docs",
   "task": "Accept: text/markdown on docs page and .md URL",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET docs.pinata.cloud/quickstart with Accept: text/markdown -> content-type text/markdown, vary includes Accept; /quickstart.md 200 markdown",
   "notes": ""
  },
  {
   "t": "05:30",
   "cap": "credentials",
   "capability": "Get API credentials",
   "task": "Get a JWT without an account",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "API keys only from app.pinata.cloud/developers/api-keys after sign-in; unauthenticated GET api.pinata.cloud/v3/files/public -> 401 {\"error\":\"ApiKeyID: cannot be blank; ApiSecret: cannot be blank; JWT: cannot be blank.\"}",
   "notes": "Blocked by sign-up wall (Turnstile).",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-02",
   "capability": "Retrieve a file by CID through a gateway",
   "task": "Fetch a public CID (from Pinata's own docs) via MCP fetchFromGateway and via gateway.pinata.cloud",
   "route": "mcp",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "MCP fetchFromGateway cid bafkreicw5nrin7q2yrd2a34m4vav4tn6hkylgcu3kaitquervjtpa334m4 -> 'Fetched 72179 bytes from public IPFS, image/png'; GET https://gateway.pinata.cloud/ipfs/bafkreicw5nrin7q2yrd2a34m4vav4tn6hkylgcu3kaitquervjtpa334m4 -> 200 image/png 72179 bytes, x-ipfs-path matches",
   "notes": "Works without an account, but on a CID we did not upload (we could not upload). Dedicated gateway not tested.",
   "quality": {
    "verify_route": "yes",
    "docs_match": "match"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-01",
   "capability": "Upload a file to IPFS",
   "task": "Upload a file to IPFS with our account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "POST https://uploads.pinata.cloud/v3/files -> 401 {\"error\":{\"code\":401,\"message\":\"Not Authorized\"}}; MCP testAuthentication -> 'Authentication failed: 401 Unauthorized'",
   "notes": "No credentials: sign-up stopped at Cloudflare Turnstile.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-05",
   "capability": "List and query uploaded files",
   "task": "List and query uploaded files with our account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "GET api.pinata.cloud/v3/files/public -> 401 'JWT: cannot be blank'",
   "notes": "No credentials: sign-up stopped at Cloudflare Turnstile.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-03",
   "capability": "Update a file's name and metadata",
   "task": "Update a file's name and metadata with our account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "needs a file and a JWT; no account",
   "notes": "No credentials: sign-up stopped at Cloudflare Turnstile.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-04",
   "capability": "Delete a file",
   "task": "Delete a file with our account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "needs a file and a JWT; no account",
   "notes": "No credentials: sign-up stopped at Cloudflare Turnstile.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-06",
   "capability": "Pin an existing CID",
   "task": "Pin an existing CID with our account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "POST /v3/files/public/pin_by_cid needs a JWT; no account",
   "notes": "No credentials: sign-up stopped at Cloudflare Turnstile.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-10",
   "capability": "Create a group and add/remove files",
   "task": "Create a group and add/remove files with our account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "POST /v3/groups/public needs a JWT; no account",
   "notes": "No credentials: sign-up stopped at Cloudflare Turnstile.",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "05:30",
   "cap": "cap-07",
   "capability": "Private IPFS upload/retrieve",
   "task": "Private network files",
   "route": "api",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "pinata.cloud pricing / capability map: private IPFS is a paid-plan feature; and no account",
   "notes": ""
  },
  {
   "t": "05:30",
   "cap": "cap-13",
   "capability": "Dedicated gateway with custom domain",
   "task": "Create gateway + custom domain",
   "route": "api",
   "documented": true,
   "result": "plan_gated",
   "verified": false,
   "evidence": "capability map plan=paid; no account",
   "notes": ""
  },
  {
   "t": "05:30",
   "cap": "cap-24",
   "capability": "Account-free upload via MPP",
   "task": "Upload hello.txt via mpp.pinata.cloud without an account",
   "route": "api",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "POST https://mpp.pinata.cloud/v1/pin/public?fileSize=1024 -> 402 application/problem+json, WWW-Authenticate: Payment realm=\"MPP Payment\", method=\"tempo\", intent=\"charge\", request amount \"1000\" in token [redacted] on chainId 4217",
   "notes": "No wallet, so not paid. Docs list a $0.01 minimum; the challenge asks 1000 base units (token decimals not checked, so the price match is unconfirmed).",
   "quality": {
    "error_legibility": "clear"
   }
  },
  {
   "t": "06:48",
   "cap": "cancel",
   "capability": "Cancel plan",
   "task": "Cancel a paid plan",
   "route": "none",
   "documented": true,
   "result": "skipped",
   "verified": false,
   "evidence": "No account and no plan started; billing docs: plan changes and cards only on the web Billing page ('Pinata currently only accepts standard debit and credit cards')",
   "notes": "Not testable."
  },
  {
   "t": "06:48",
   "cap": "delete",
   "capability": "Delete account",
   "task": "Find a documented account-deletion route",
   "route": "none",
   "documented": true,
   "result": "blocked",
   "verified": false,
   "evidence": "No account was created; search of docs.pinata.cloud/llms-full.txt finds no account-deletion route",
   "notes": "Nothing to clean up: no account, no files. MCP package installed under run dir ./npm only."
  },
  {
   "t": "07:59",
   "cap": "discovery",
   "capability": "OpenAPI",
   "task": "Fetch the OpenAPI spec listed in llms.txt",
   "route": "api",
   "documented": true,
   "result": "done",
   "verified": true,
   "evidence": "GET https://docs.pinata.cloud/pinata-x402-api-v3.yaml 200 text/yaml, 'openapi: 3.0.0', title 'Pinata x402 Payment Instructions API'",
   "notes": "Only the x402 payment-instructions API has a listed spec; 3.0.0 is behind 3.2.1."
  }
 ],
 "stale": false,
 "icon": "/logos/pinata.png",
 "monitored": false,
 "verdict": "Needs a person to sign up: Pinata sits at L1 · Needs a person. Our agent read the docs headlessly through llms.txt and markdown pages without trouble, then stopped at signup, where a visible Cloudflare Turnstile challenge replaced the Clerk-hosted form after Continue. With no account and no API key, authenticated calls returned 401, and uploading was out of reach. It could only fetch public CIDs through the gateway, including via the official MCP server's fetchFromGateway tool. Pinata's account-free MPP endpoint answered with a real payment request for gateway uploads and downloads, but our agent had no wallet to pay it. No account meant nothing to cancel or delete.",
 "page": "https://agentdrives.com/tools/pinata?via=api"
}