{"openapi":"3.1.0","info":{"title":"Nodpick AI readiness API","version":"1.0.0","summary":"Free, deterministic audit of how well a website can be found and cited by AI assistants.","description":"The audit and fix-snippet endpoints need no account and no API key. The two project endpoints belong to your Nodpick account and answer only for its own projects: send a personal read-only API key as `Authorization: Bearer npk_…` (create one under Settings, paid plans) or use the portal session. No LLM is used for the audit: every result comes from fixed rules over up to five fetched URLs. Results are cached for 24 hours. Responses never contain raw content of the audited page. A Model Context Protocol server with the same tools is available at /mcp.","termsOfService":"https://nodpick.com/legal/terms","contact":{"email":"hello@nodpick.com","url":"https://nodpick.com"}},"servers":[{"url":"https://nodpick.com"}],"externalDocs":{"description":"Agent documentation (Markdown)","url":"https://nodpick.com/docs/agents.md"},"paths":{"/api/v1/ai-readiness":{"get":{"operationId":"auditAiReadiness","summary":"Audit AI readiness of a URL","description":"Fetches the page (as a browser and as an AI search bot), robots.txt, the sitemap and llms.txt (max 5 requests, 5 s and 1 MB each) and scores seven weighted checks plus one informational check (eight entries in `checks`).","parameters":[{"name":"url","in":"query","required":true,"description":"Public http(s) URL or bare domain.","schema":{"type":"string","maxLength":2048},"example":"https://example.com"},{"name":"framework","in":"query","required":false,"description":"Your stack, so fixes match. Detected from the page when omitted.","schema":{"$ref":"#/components/schemas/Framework"}}],"responses":{"200":{"description":"Audit result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditResult"}}}},"400":{"description":"Missing or invalid parameter, or a URL that may not be audited (private address, bad port, credentials).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The site could not be fetched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit reached (20 uncached audits per hour per client, 10 per target site per hour, 200 calls of any kind per hour per client).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait."}}},"503":{"description":"Global hourly capacity reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}}}}}}},"/api/v1/fix-snippet":{"get":{"operationId":"getFixSnippet","summary":"Copy-paste fix for one check on one stack","description":"Pure lookup, no fetching.","parameters":[{"name":"check","in":"query","required":true,"schema":{"$ref":"#/components/schemas/CheckId"}},{"name":"framework","in":"query","required":false,"description":"Stack of the site. Defaults to other (generic) when omitted.","schema":{"$ref":"#/components/schemas/Framework"}}],"responses":{"200":{"description":"Snippet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Snippet"}}}},"400":{"description":"Missing or invalid parameter, or a URL that may not be audited (private address, bad port, credentials).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/projects/{id}/action-plan":{"get":{"operationId":"getActionPlan","summary":"Ranked action plan of your own project, ready for a coding agent","description":"Needs a personal API key (Bearer) or the portal session. Returns the action plan of the latest finished run: per item the measured evidence with its grade, concrete steps, the matching fix snippet when the item is a code change, acceptance criteria and a ready-to-paste prompt. Nodpick provides the task and the data; your own agent makes the change in your repository. Another account's project answers 404.","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"framework","in":"query","required":false,"description":"Your stack, to pick the matching snippet. Defaults to other.","schema":{"$ref":"#/components/schemas/Framework"}},{"name":"lang","in":"query","required":false,"description":"Language of the texts and the prompt. Defaults to the account language.","schema":{"type":"string","enum":["en","de"]}}],"responses":{"200":{"description":"Action plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActionPlan"}}}},"400":{"description":"Missing or invalid parameter, or a URL that may not be audited (private address, bad port, credentials).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key, or not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The account is on the free plan, so its keys are paused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown project, or a project of another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/projects":{"get":{"operationId":"listProjects","summary":"Your tracked brands (ids for the action-plan endpoint)","description":"Returns id, brand and domain of every brand tracked in your account. Bearer API key or portal session.","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"responses":{"200":{"description":"Projects.","content":{"application/json":{"schema":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"brand":{"type":"string"},"domain":{"type":"string"}}}}}}}}},"401":{"description":"Missing, invalid or revoked API key, or not signed in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The account is on the free plan, so its keys are paused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many requests for this key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","responses":{"200":{"description":"OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"npk_…","description":"Personal read-only API key, created under Settings, API & coding agents. Paid plans."},"sessionCookie":{"type":"apiKey","in":"cookie","name":"cm_session","description":"The browser session of a signed-in account."}},"schemas":{"ActionPlan":{"type":"object","required":["projectId","brand","domain","lang","runId","items"],"properties":{"projectId":{"type":"string","format":"uuid"},"brand":{"type":"string"},"domain":{"type":"string"},"lang":{"type":"string","enum":["en","de"]},"runId":{"type":["string","null"]},"sources":{"type":"array","description":"Domains the AI engines cited in the latest run. `kind`: yours, competitors or other; `category` (kind other only): the kind of page the domain mostly is.","items":{"type":"object","required":["domain","count","kind","category"],"properties":{"domain":{"type":"string"},"count":{"type":"integer"},"kind":{"type":"string","enum":["yours","competitors","other"]},"category":{"type":["string","null"],"enum":["list","forum","video","reference","directory","news","other",null]}}}},"gaps":{"type":"array","description":"Questions where at least one rival is named and the brand is not, with the rivals named and the top cited pages.","items":{"type":"object","required":["question","rivals","sources"],"properties":{"question":{"type":"string"},"rivals":{"type":"array","items":{"type":"string"}},"sources":{"type":"array","items":{"type":"object","required":["url","domain","title","count","category"],"properties":{"url":{"type":"string"},"domain":{"type":"string"},"title":{"type":["string","null"]},"count":{"type":"integer"},"category":{"type":"string","enum":["list","forum","video","reference","directory","news","other","competitor"],"description":"competitor: a page on a rival's own site."}}}}}}},"items":{"type":"array","items":{"type":"object","required":["rank","id","priority","title","detail","why","evidence","steps","snippet","verify","prompt"],"properties":{"rank":{"type":"integer","minimum":1},"id":{"type":"string"},"priority":{"type":"integer","enum":[1,2,3]},"title":{"type":"string"},"detail":{"type":"string"},"why":{"type":"string"},"evidence":{"type":"object","required":["fact","grade","source"],"properties":{"fact":{"type":["string","null"]},"grade":{"type":"string","enum":["A","B","C"],"description":"A: documented by the platform. B: supported by a study. C: untested."},"source":{"oneOf":[{"type":"object","required":["label","url"],"properties":{"label":{"type":"string"},"url":{"type":"string","format":"uri"}}},{"type":"null"}]}}},"steps":{"type":"array","items":{"type":"string"}},"snippet":{"oneOf":[{"$ref":"#/components/schemas/Snippet"},{"type":"null"}]},"verify":{"type":"array","items":{"type":"string"},"description":"Acceptance criteria."},"prompt":{"type":"string","description":"Ready-to-paste prompt for Claude Code, Cursor or Codex."}}}}}},"Framework":{"type":"string","enum":["nextjs","astro","wordpress","static","spa","nginx","apache","other"]},"CheckId":{"type":"string","enum":["crawler_access","training_crawlers","raw_html_content","indexability","metadata","structured_data","freshness","agent_extras"]},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","examples":["invalid_url"]},"message":{"type":"string"}}}}},"Check":{"type":"object","required":["id","title","status","points","maxPoints","evidence","evidenceNote","source","finding","fix"],"properties":{"id":{"$ref":"#/components/schemas/CheckId"},"title":{"type":"string"},"status":{"type":"string","enum":["pass","warn","fail","info"]},"points":{"type":"integer","minimum":0},"maxPoints":{"type":"integer","minimum":0,"description":"Weights: crawler_access 25, raw_html_content 25, indexability 20, metadata 10, structured_data 10, freshness 5, agent_extras 5; training_crawlers is informational (0)."},"evidence":{"type":"string","enum":["A","B","C"],"description":"A: documented by the vendors. B: supported by a study. C: unproven."},"evidenceNote":{"type":"string"},"source":{"type":"string","format":"uri"},"finding":{"type":"string","description":"Our own words; never page content."},"fix":{"type":"object","required":["summary","snippetId","framework"],"properties":{"summary":{"type":"string"},"snippetId":{"oneOf":[{"$ref":"#/components/schemas/CheckId"},{"type":"null"}]},"framework":{"$ref":"#/components/schemas/Framework"}}}}},"AuditResult":{"type":"object","required":["url","finalUrl","redirectedOffsite","partial","inconclusive","score","checks","topFixes","nextStep","cachedAt","cached","framework","signals"],"properties":{"url":{"type":"string","format":"uri"},"finalUrl":{"type":"string","format":"uri","description":"After redirects, only while the final host stays on the audited site (same registrable domain). Otherwise just `https://<host>/` of the redirect target."},"redirectedOffsite":{"type":"boolean","description":"True when the page redirected to another domain."},"partial":{"type":"boolean","description":"True when part of the audit could not be verified (timeout, 5xx, 429). Unverified parts are removed from maxPoints and the score is scaled to 100; such results are cached for 10 minutes instead of 24 hours."},"inconclusive":{"type":"array","items":{"$ref":"#/components/schemas/CheckId"},"description":"Checks with unverified parts."},"score":{"type":"integer","minimum":0,"maximum":100},"checks":{"type":"array","items":{"$ref":"#/components/schemas/Check"}},"topFixes":{"type":"array","maxItems":5,"items":{"type":"object","required":["checkId","title","pointsGain","summary","snippetId","framework"],"properties":{"checkId":{"$ref":"#/components/schemas/CheckId"},"title":{"type":"string"},"pointsGain":{"type":"integer"},"summary":{"type":"string"},"snippetId":{"$ref":"#/components/schemas/CheckId"},"framework":{"$ref":"#/components/schemas/Framework"}}}},"nextStep":{"type":"object","required":["label","url"],"properties":{"label":{"type":"string"},"url":{"type":"string","format":"uri"}}},"cachedAt":{"type":"string","format":"date-time","description":"When this result was computed."},"cached":{"type":"boolean"},"framework":{"type":"object","required":["detected","used"],"properties":{"detected":{"oneOf":[{"$ref":"#/components/schemas/Framework"},{"type":"null"}]},"used":{"$ref":"#/components/schemas/Framework"}}},"signals":{"type":"object","required":["spa","spaGenerator","textChars","scriptFiles","emptyRoot"],"properties":{"spa":{"type":"boolean"},"spaGenerator":{"type":["string","null"]},"textChars":{"type":"integer"},"scriptFiles":{"type":"integer"},"emptyRoot":{"type":"boolean"}}}}},"Snippet":{"type":"object","required":["checkId","framework","title","files","notes"],"properties":{"checkId":{"$ref":"#/components/schemas/CheckId"},"framework":{"$ref":"#/components/schemas/Framework"},"title":{"type":"string"},"files":{"type":"array","items":{"type":"object","required":["path","language","code"],"properties":{"path":{"type":"string"},"language":{"type":"string"},"code":{"type":"string"}}}},"notes":{"type":"array","items":{"type":"string"}}}}}}}