REST API and MCP server

API & MCP

Reach your snippets and collections from a script, a terminal or an AI assistant.
create a snippet
curl -X POST https://pastecode.io/api/v1/snippets \
  -H "Authorization: Bearer pc_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "content": "print(\"hello\")", "language": "python" }'
Base URLhttps://pastecode.io/api/v1
MCP endpointhttps://pastecode.io/api/mcp
AuthAuthorization: Bearer

Getting started

A key belongs to your account and can do what you can do, nothing more.
Open the API & MCP tab of your profile and create a key. It is shown once, so copy it then. Choose read only for anything that should never change your snippets and collections.

Authentication

A bearer token on every request. No cookie, no session, no other header.
authenticate
curl https://pastecode.io/api/v1/me -H "Authorization: Bearer pc_YOUR_API_KEY"
Requests are accepted from any origin, since a bearer token cannot be attached by a browser on your behalf. Never put a key in client-side code: anyone reading the page can take it.

Errors

Every failure carries the right status and the same body. Branch on code; the message is for a human and may be reworded.
error
{
  "error": {
    "code": "validation_failed",
    "message": "title can not be longer than 50 characters"
  }
}
StatusCodeWhen
400validation_failedA rule refused the request. The message says which one.
401unauthorizedNo key, an unknown key, an expired one, or a missing snippet password.
403forbiddenA read only key attempted a write, or the account or the address it came from is banned.
404not_foundNo such resource, or one you do not own. The two are deliberately not distinguished.
405method_not_allowedWrong verb for this path. The Allow header lists the right ones.
409conflictThe request cannot apply, for instance asking for the body of an encrypted snippet.
410goneIt existed and was deleted or burned after reading.
413payload_too_largeThe request body itself was too large to read, before any rule looked at it.
429rate_limitedOver a ceiling: the requests an account may make, the wait between snippets, the daily snippet count, or the archive search allowance. Retry-After says how long to wait.
500internal_errorNothing handled the request. The x-request-id header names the record of it.
503unavailableThe API is switched off, or a security-critical dependency such as the address ban or password limiter is unavailable.
Every response carries an x-request-id header, whether it succeeded or failed. Quote it when you report a problem: it is what ties your call to everything the server recorded while answering it.

Snippets

Create, read, change and delete the snippets your account owns. Reading also works for any public snippet.
GET/api/v1/snippets
List the snippets you own, newest first.
Query parameters
FieldTypeNotes
pageintegerDefaults to 1.
limitintegerDefaults to 20, capped at 100.
languagestringFilter by syntax id, for example python.See all 165
searchstringMatches the title or the description, or a whole slug exactly. It does not reach the code inside a snippet; use the archive search for that. Longer than 80 characters is truncated.
order"asc" | "desc"By creation time. Defaults to desc.
Response
GET /api/v1/snippets
{
  "data": [ {
    "slug": "a1b2c3d4",
    "url": "https://pastecode.io/s/a1b2c3d4",
    "rawUrl": "https://pastecode.io/api/v1/snippets/a1b2c3d4/raw",
    "title": "Debounce hook",
    "description": "A small React hook",
    "language": "typescript",
    "visibility": "public",
    "passwordProtected": false,
    "encrypted": false,
    "burnAfterRead": false,
    "commentsAllowed": true,
    "collectionId": null,
    "hits": 12,
    "createdAt": "2026-08-06T10:00:00.000Z",
    "updatedAt": "2026-08-06T10:00:00.000Z",
    "expiresAt": null
  } ],
  "pagination": { "page": 1, "perPage": 20, "total": 42, "totalPages": 3 }
}
POST/api/v1/snippetsneeds a read & write key
Create a snippet. Answers 201 with a Location header naming the new resource.
Body
FieldTypeNotes
content *stringThe body as plain UTF-8 text, not base64.
titlestringUp to 50 characters.
descriptionstringUp to 300 characters.
languagestringSyntax id. Omitted or unrecognised is stored as plain_text.See all 165
visibility"public" | "unlisted" | "private"public is listed in the archive, unlisted is reachable by link only, private is yours alone. Defaults to unlisted.
passwordstringAt least 5 characters. A password makes a snippet unlisted.
burnAfterReadbooleanDestroyed after the first read by anyone else.
commentsAllowedbooleanDefaults to true.
collectionIdstringA collection you own.
expiresAtstringISO 8601 timestamp in the future.
Request
curl
curl -X POST https://pastecode.io/api/v1/snippets \
  -H "Authorization: Bearer pc_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "export const useDebounce = () => {}",
    "title": "Debounce hook",
    "language": "typescript",
    "visibility": "public"
  }'
Response
POST /api/v1/snippets
{
  "slug": "a1b2c3d4",
  "url": "https://pastecode.io/s/a1b2c3d4",
  "rawUrl": "https://pastecode.io/api/v1/snippets/a1b2c3d4/raw",
  "title": "Debounce hook",
  "description": "A small React hook",
  "language": "typescript",
  "content": "export const useDebounce = () => {}",
  "visibility": "public",
  "passwordProtected": false,
  "encrypted": false,
  "burnAfterRead": false,
  "commentsAllowed": true,
  "collectionId": null,
  "hits": 12,
  "createdAt": "2026-08-06T10:00:00.000Z",
  "updatedAt": "2026-08-06T10:00:00.000Z",
  "expiresAt": null
}
GET/api/v1/snippets/{slug}
Read one snippet. Works for your own and for any public one. Send X-Snippet-Password for a protected one.
Request
curl
curl https://pastecode.io/api/v1/snippets/a1b2c3d4 \
  -H "Authorization: Bearer pc_YOUR_API_KEY"
Response
GET /api/v1/snippets/{slug}
{
  "slug": "a1b2c3d4",
  "url": "https://pastecode.io/s/a1b2c3d4",
  "rawUrl": "https://pastecode.io/api/v1/snippets/a1b2c3d4/raw",
  "title": "Debounce hook",
  "description": "A small React hook",
  "language": "typescript",
  "content": "export const useDebounce = () => {}",
  "visibility": "public",
  "passwordProtected": false,
  "encrypted": false,
  "burnAfterRead": false,
  "commentsAllowed": true,
  "collectionId": null,
  "hits": 12,
  "createdAt": "2026-08-06T10:00:00.000Z",
  "updatedAt": "2026-08-06T10:00:00.000Z",
  "expiresAt": null
}
GET/api/v1/snippets/{slug}/raw
The body alone, as text/plain. Send X-Snippet-Password for a protected snippet. Burn-after-read snippets are not available through this endpoint and are not consumed by it.
Request
curl
curl https://pastecode.io/api/v1/snippets/a1b2c3d4/raw \
  -H "Authorization: Bearer pc_YOUR_API_KEY"
Response
GET /api/v1/snippets/{slug}/raw
export const useDebounce = () => {}
PATCH/api/v1/snippets/{slug}needs a read & write key
Change a snippet you own. Anything you leave out keeps its current value; an explicit null clears title and description. content is the exception: it can be changed but not cleared, and a null is refused. password, burnAfterRead, expiresAt, encrypted and collectionId are fixed at creation and are refused with 400; use the collection membership endpoints to move a snippet.
Body
FieldTypeNotes
contentstringPlain UTF-8 text.
titlestring | nullUp to 50 characters.
descriptionstring | nullUp to 300 characters.
languagestringSyntax id. Unrecognised is stored as plain_text.See all 165
visibility"public" | "unlisted" | "private"public is listed in the archive, unlisted is reachable by link only, private is yours alone. Defaults to unlisted.
commentsAllowedboolean
revisionNamestringNames this revision in the history.
Request
curl
curl -X PATCH https://pastecode.io/api/v1/snippets/a1b2c3d4 \
  -H "Authorization: Bearer pc_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "title": "A better title" }'
Response
PATCH /api/v1/snippets/{slug}
{
  "slug": "a1b2c3d4",
  "url": "https://pastecode.io/s/a1b2c3d4",
  "rawUrl": "https://pastecode.io/api/v1/snippets/a1b2c3d4/raw",
  "title": "Debounce hook",
  "description": "A small React hook",
  "language": "typescript",
  "content": "export const useDebounce = () => {}",
  "visibility": "public",
  "passwordProtected": false,
  "encrypted": false,
  "burnAfterRead": false,
  "commentsAllowed": true,
  "collectionId": null,
  "hits": 12,
  "createdAt": "2026-08-06T10:00:00.000Z",
  "updatedAt": "2026-08-06T10:00:00.000Z",
  "expiresAt": null
}
DELETE/api/v1/snippets/{slug}needs a read & write key
Delete a snippet you own. Answers 204 with no body.
Response
DELETE /api/v1/snippets/{slug}
204 No Content

Collections

Collections are named folders of snippets. Membership is its own resource, so attaching is a PUT and detaching a DELETE.
GET/api/v1/collections
List the collections you own.
Response
GET /api/v1/collections
{ "data": [ {
    "id": "abc123",
    "url": "https://pastecode.io/collections/abc123",
    "name": "React hooks",
    "description": "Things I keep rewriting",
    "isPublic": true,
    "snippetCount": 4,
    "createdAt": "2026-08-06T10:00:00.000Z",
    "updatedAt": "2026-08-06T10:00:00.000Z"
  } ] }
POST/api/v1/collectionsneeds a read & write key
Create a collection. Answers 201 with a Location header.
Body
FieldTypeNotes
name *stringBetween 3 and 180 characters.
descriptionstringUp to 300 characters.
isPublicbooleanFree accounts are capped on private collections.
Request
curl
curl -X POST https://pastecode.io/api/v1/collections \
  -H "Authorization: Bearer pc_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "React hooks", "isPublic": true }'
Response
POST /api/v1/collections
{
  "id": "abc123",
  "url": "https://pastecode.io/collections/abc123",
  "name": "React hooks",
  "description": "Things I keep rewriting",
  "isPublic": true,
  "snippetCount": 4,
  "createdAt": "2026-08-06T10:00:00.000Z",
  "updatedAt": "2026-08-06T10:00:00.000Z"
}
GET/api/v1/collections/{id}
Read one collection.
Response
GET /api/v1/collections/{id}
{
  "id": "abc123",
  "url": "https://pastecode.io/collections/abc123",
  "name": "React hooks",
  "description": "Things I keep rewriting",
  "isPublic": true,
  "snippetCount": 4,
  "createdAt": "2026-08-06T10:00:00.000Z",
  "updatedAt": "2026-08-06T10:00:00.000Z"
}
PATCH/api/v1/collections/{id}needs a read & write key
Rename a collection or change whether it is public.
Body
FieldTypeNotes
namestringBetween 3 and 180 characters.
descriptionstringUp to 300 characters.
isPublicboolean
Response
PATCH /api/v1/collections/{id}
{
  "id": "abc123",
  "url": "https://pastecode.io/collections/abc123",
  "name": "React hooks",
  "description": "Things I keep rewriting",
  "isPublic": true,
  "snippetCount": 4,
  "createdAt": "2026-08-06T10:00:00.000Z",
  "updatedAt": "2026-08-06T10:00:00.000Z"
}
DELETE/api/v1/collections/{id}needs a read & write key
Delete an empty collection. One still holding snippets has to be emptied first.
Response
DELETE /api/v1/collections/{id}
204 No Content
GET/api/v1/collections/{id}/snippets
List the snippets inside a collection.
Query parameters
FieldTypeNotes
pageintegerDefaults to 1.
limitintegerDefaults to 20, capped at 100.
languagestringFilter by syntax id.See all 165
searchstringMatch against the title or the description.
sortBy"createdAt" | "title" | "language"Defaults to createdAt.
sortOrder"ASC" | "DESC"Defaults to DESC.
Response
GET /api/v1/collections/{id}/snippets
{
  "data": [ {
    "slug": "a1b2c3d4",
    "url": "https://pastecode.io/s/a1b2c3d4",
    "rawUrl": "https://pastecode.io/api/v1/snippets/a1b2c3d4/raw",
    "title": "Debounce hook",
    "description": "A small React hook",
    "language": "typescript",
    "visibility": "public",
    "passwordProtected": false,
    "encrypted": false,
    "burnAfterRead": false,
    "commentsAllowed": true,
    "collectionId": null,
    "hits": 12,
    "createdAt": "2026-08-06T10:00:00.000Z",
    "updatedAt": "2026-08-06T10:00:00.000Z",
    "expiresAt": null
  } ],
  "pagination": { "page": 1, "perPage": 20, "total": 42, "totalPages": 3 }
}
PUT/api/v1/collections/{id}/snippets/{slug}needs a read & write key
Put one of your snippets in this collection. Idempotent, answers 204.
Request
curl
curl -X PUT https://pastecode.io/api/v1/collections/abc123/snippets/a1b2c3d4 \
  -H "Authorization: Bearer pc_YOUR_API_KEY"
Response
PUT /api/v1/collections/{id}/snippets/{slug}
204 No Content
DELETE/api/v1/collections/{id}/snippets/{slug}needs a read & write key
Take a snippet out of this collection. The snippet itself is not deleted.
Response
DELETE /api/v1/collections/{id}/snippets/{slug}
204 No Content

Archive search

Search the public archive, including the code inside snippets. This is how to find something you do not already have a slug for. A query shorter than 3 characters does not reach snippet bodies, because a trigram index cannot serve it.
GET/api/v1/archive/snippets
Search or browse public snippets. Returns at most 100 matches.
Query parameters
FieldTypeNotes
qstringMatches title, description, author nick and snippet body, or a whole slug exactly.
languagestringRestrict to one syntax.See all 165
sort"relevance" | "newest" | "popular"relevance applies only while searching, and is the default then. It ranks a whole slug first, then the title and description, then the body, then the author, and settles ties on visit count.
pageintegerPages the capped result set.
limitintegerDefaults to 20, capped at 100.
Request
curl
curl "https://pastecode.io/api/v1/archive/snippets?q=useState&language=typescript" \
  -H "Authorization: Bearer pc_YOUR_API_KEY"
Response
GET /api/v1/archive/snippets
{
  "data": [
    {
      "slug": "a1b2c3d4",
      "url": "https://pastecode.io/s/a1b2c3d4",
      "title": "Debounce hook",
      "description": "A small React hook",
      "language": "typescript",
      "languageLabel": "TypeScript",
      "author": "alice",
      "preview": "const [value, setValue] = useState('')",
      "previewTruncated": true,
      "matchedInBody": true,
      "hits": 12,
      "createdAt": "2026-08-06T10:00:00.000Z"
    }
  ],
  "pagination": { "page": 1, "perPage": 20, "total": 42, "totalPages": 3 },
  "query": "useState",
  "resultLimit": 100
}
GET/api/v1/archive/languages
The syntaxes public snippets actually use, and so the valid values for the language filter.
Response
GET /api/v1/archive/languages
{ "data": [ { "language": "typescript", "label": "TypeScript" } ] }

Account

Who the key acts as, and what it may do.
GET/api/v1/me
The account behind this key, and the key itself.
Request
curl
curl https://pastecode.io/api/v1/me -H "Authorization: Bearer pc_YOUR_API_KEY"
Response
GET /api/v1/me
{
  "userId": "9d4c...",
  "nick": "you",
  "email": "[email protected]",
  "premium": true,
  "key": { "name": "Claude Code", "scope": "read_write" }
}

MCP setup

The Model Context Protocol over streamable HTTP at https://pastecode.io/api/mcp, with the same key. Pick your client and paste.
Run this in any terminal.
terminal
claude mcp add --transport http pastecode https://pastecode.io/api/mcp \
  --header "Authorization: Bearer pc_YOUR_API_KEY"

MCP tools

A read only key is offered the read tools alone, so an assistant is never shown something it would only be refused.
ToolKeyWhat it does
search_archivereadSearch public snippets by metadata, author and the code inside them.
list_archive_languagesreadThe syntaxes the public archive actually uses.
list_snippetsreadList the snippets this account owns.
get_snippetreadRead one snippet, yours or any public one, including its content.
list_collectionsreadList the collections this account owns.
get_collectionreadRead one collection.
list_collection_snippetsreadList the snippets inside a collection.
create_snippetread & writeCreate a snippet.
update_snippetread & writeChange a snippet, keeping anything left out.
delete_snippetread & writeDelete a snippet.
create_collectionread & writeCreate a collection.
update_collectionread & writeRename a collection or change its visibility.
delete_collectionread & writeDelete an empty collection.
set_snippet_collectionread & writeMove a snippet into a collection, or out of the one it is in.