API Reference
REST API to create and manage pastes programmatically. Bearer auth, JSON responses, works with cURL, fetch, or any HTTP client.
Overview
The CodeThis REST API lets you create, read, update, and delete pastes programmatically. All API routes are under:
https://codethis.dev/api/v1/
The API returns JSON. Successful responses have a data field. Errors have statusCode and message.
Authentication
All API requests require an API key. Pass it as a Bearer token in the Authorization header:
Authorization: Bearer ct_your_api_key_here
API keys start with ct_. They are stored as SHA-256 hashes — the plaintext key is only shown once when created.
Creating an API Key
API keys are free — every registered account can create up to 2 keys on Free, and up to 20 keys on Pro (with higher rate limits). Anonymous users cannot create keys.
- Go to Settings > API Keys (or visit
/dashboard/settings?tab=api-keys) - Click Create API Key
- Give it a name (e.g., "Claude Desktop", "CI pipeline")
- Copy the key immediately — it will not be shown again
To revoke a key, click Delete next to it in the settings page. Revoked keys stop working instantly.
Endpoints
POST /api/v1/paste
Create a new paste.
Request
POST https://codethis.dev/api/v1/paste
Authorization: Bearer ct_...
Content-Type: application/json
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | Yes | The paste content |
title | string | No | Optional filename (e.g., app.tsx). Language is auto-detected from the extension. |
language | string | No | Language identifier (e.g., typescript, python). Overridden by title extension if both are set. Defaults to plaintext. |
duration | string | No | How long the slug should live. Defaults to your tier's default. See duration options below. |
visibility | string | No | One of public, unlisted, or private. Default: public. See visibility options below. |
Note: Password-protection is not yet supported via the REST API. Set a password from the dashboard after creating the paste. Requests that include a
passwordfield return501 Not Implemented.
Visibility options
| Value | Public link | Search / profile | Use case |
|---|---|---|---|
public | Yes | Yes | Default. Shareable and discoverable. |
unlisted | Yes | No | Link-only — not in sitemap or your profile. |
private | No | No | Saved to your account with no public link. slug and url come back null. |
Duration options
| Value | Description | Minimum tier |
|---|---|---|
1h | 1 hour | All |
4h | 4 hours | All |
1d | 1 day | All |
3d | 3 days | All |
7d | 7 days | All |
30d | 30 days | Free |
90d | 90 days | Free |
1y | 1 year | Free |
forever | Never expires | Free (opt-in via the "Keep forever" toggle on /new) |
Response
{
"data": {
"id": "clx9abc123...",
"slug": "xK7mQ2pN",
"url": "https://codethis.dev/doc/xK7mQ2pN",
"friendlyName": "brave-tiger",
"language": "typescript",
"visibility": "public",
"expiresAt": "2026-05-17T00:00:00.000Z",
"createdAt": "2026-04-17T10:23:45.000Z"
}
}
When visibility is private, slug, url, and expiresAt are all null — the paste is saved to your account but has no public link.
Example — create a TypeScript paste that expires in 30 days
curl -X POST https://codethis.dev/api/v1/paste \
-H "Authorization: Bearer ct_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"content": "const greet = (name: string) => `Hello, ${name}!`",
"title": "greet.ts",
"duration": "30d"
}'
Example — create a permanent unlisted paste
curl -X POST https://codethis.dev/api/v1/paste \
-H "Authorization: Bearer ct_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"content": "my secret config here",
"title": "config.env",
"duration": "forever",
"visibility": "unlisted"
}'
GET /api/v1/paste/:slug
Fetch a paste by its slug.
Request
GET https://codethis.dev/api/v1/paste/:slug
Authorization: Bearer ct_...
The Authorization header is optional for public pastes. It is required to access password-protected pastes you own.
Path parameters
| Parameter | Type | Description |
|---|---|---|
slug | string | The paste slug (the short ID at the end of the paste URL) |
Response
{
"data": {
"slug": "xK7mQ2pN",
"title": "greet.ts",
"friendlyName": "brave-tiger",
"content": "const greet = (name: string) => `Hello, ${name}!`",
"language": "typescript",
"size": 52,
"createdAt": "2026-04-17T10:23:45.000Z",
"updatedAt": "2026-04-17T10:23:45.000Z",
"expiresAt": "2026-05-17T00:00:00.000Z",
"isOwner": true
}
}
The isOwner field is true when your API key belongs to the paste's owner.
Example — fetch a public paste
curl https://codethis.dev/api/v1/paste/xK7mQ2pN
Example — fetch a paste you own (including password-protected)
curl https://codethis.dev/api/v1/paste/xK7mQ2pN \
-H "Authorization: Bearer ct_your_api_key_here"
PUT /api/v1/paste/:slug
Update an existing paste you own. At least one of content, title, or language is required.
Request
PUT https://codethis.dev/api/v1/paste/:slug
Authorization: Bearer ct_...
Content-Type: application/json
Body parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | No | Replace the paste content. |
title | string | null | No | Update the title. Pass null to clear. When set, language is re-detected from the file extension unless language is also provided. |
language | string | No | Explicitly set the language. |
Updating a paste does not reset its expiry or generate a new slug. The
updatedAtfield on the paste changes; the slug and its expiry stay put.
Response
{
"data": {
"id": "clx9abc123...",
"slug": "xK7mQ2pN",
"url": "https://codethis.dev/doc/xK7mQ2pN",
"updated": true
}
}
Example — append a line and rename
curl -X PUT https://codethis.dev/api/v1/paste/xK7mQ2pN \
-H "Authorization: Bearer ct_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "content": "const greet = (name: string) => `Hi, ${name}!`", "title": "hi.ts" }'
DELETE /api/v1/paste/:slug
Soft-delete a paste you own. The document and every public slug for it are marked deleted. /doc/:slug subsequently returns 410 Gone (not 404) so link previewers learn the URL is permanently gone.
Request
DELETE https://codethis.dev/api/v1/paste/:slug
Authorization: Bearer ct_...
Response
{
"data": {
"id": "clx9abc123...",
"slug": "xK7mQ2pN",
"deleted": true
}
}
Example
curl -X DELETE https://codethis.dev/api/v1/paste/xK7mQ2pN \
-H "Authorization: Bearer ct_your_api_key_here"
GET /api/v1/pastes
List your pastes, ordered by most recently updated.
Request
GET https://codethis.dev/api/v1/pastes
Authorization: Bearer ct_...
Query parameters
| Parameter | Type | Default | Max | Description |
|---|---|---|---|---|
page | number | 1 | — | Page number for pagination |
limit | number | 20 | 50 | Results per page |
Response
{
"data": [
{
"id": "clx9abc123...",
"title": "greet.ts",
"friendlyName": "brave-tiger",
"language": "typescript",
"size": 52,
"slug": "xK7mQ2pN",
"createdAt": "2026-04-17T10:23:45.000Z",
"updatedAt": "2026-04-17T10:23:45.000Z"
}
]
}
The slug field is null if the document has no active (non-expired) public slug.
Example — list your most recent 5 pastes
curl "https://codethis.dev/api/v1/pastes?limit=5" \
-H "Authorization: Bearer ct_your_api_key_here"
Example — paginate
curl "https://codethis.dev/api/v1/pastes?page=2&limit=20" \
-H "Authorization: Bearer ct_your_api_key_here"
Error Responses
All errors follow this format:
{
"statusCode": 401,
"message": "API key required. Pass Authorization: Bearer ct_... header."
}
Common status codes:
| Code | Meaning |
|---|---|
400 | Bad request — missing or invalid parameter |
401 | Unauthorized — missing or invalid API key |
403 | Forbidden — document limit reached, or paste is password-protected and you are not the owner |
404 | Not found — paste does not exist or has expired |
413 | Payload too large — content exceeds your tier's size limit |
500 | Internal server error |
Tier-Based Limits
| Limit | Free | Pro |
|---|---|---|
| Max paste size | 1 MB | 5 MB |
| Max paste count | 100 | Unlimited |
| Max duration | forever | forever |
| API key creation | Yes (2 keys) | Yes (20 keys) |
| Password-protected pastes | No | Yes |
If you exceed the paste count limit, the API returns 403 with a message suggesting you upgrade to Pro.
Using with Shell Scripts
Here's a complete example that creates a paste from a file and prints the URL:
#!/bin/bash
API_KEY="ct_your_api_key_here"
FILE="$1"
if [ -z "$FILE" ]; then
echo "Usage: $0 <file>"
exit 1
fi
CONTENT=$(cat "$FILE")
TITLE=$(basename "$FILE")
RESPONSE=$(curl -s -X POST https://codethis.dev/api/v1/paste \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"content\": $(echo "$CONTENT" | jq -Rs .), \"title\": \"$TITLE\", \"duration\": \"7d\"}")
URL=$(echo "$RESPONSE" | jq -r '.data.url')
echo "Published: $URL"
Usage:
chmod +x share.sh
./share.sh ./app.tsx
# Published: https://codethis.dev/doc/xK7mQ2pN