API
Authenticate, create cards, upload files, and build reliable Teak integrations
Teak provides a public REST API for saving, querying, and syncing cards. Use this guide for integration decisions and the generated reference for every operation, field, schema, and code sample.
API Reference
Explore the complete OpenAPI contract and samples in curl, JavaScript, and Python.
MCP
Connect an AI client to Teak through its remote MCP server.
Base URL
Production: https://teakvault.com/api/v1
The machine-readable OpenAPI document is available at https://teakvault.com/api/openapi.json. Local development URLs are in the Development guide.
Authentication
Every API request uses a bearer token in the Authorization header.
Generate a long-lived teakapi_ key in Teak Settings. Each account can have
up to 10 active keys, and new keys can be created at most five times per
minute. Use Revoke all keys if you need to clear every key, including any
that no longer appear in the list.
Authorization: Bearer teakapi_...
Native clients using browser sign-in send short-lived OAuth access tokens instead — see Development.
Create your first card
curl https://teakvault.com/api/v1/cards \
--request POST \
--header "Authorization: Bearer $TEAK_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: first-card" \
--data '{
"content": "# Project notes\n\nKeep the original spacing.",
"cardType": "text",
"tags": ["project"]
}'const response = await fetch("https://teakvault.com/api/v1/cards", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TEAK_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": "first-card",
},
body: JSON.stringify({
content: "# Project notes\n\nKeep the original spacing.",
cardType: "text",
tags: ["project"],
}),
});Create behavior
cardType is optional. Set it to text to preserve raw Markdown exactly, even when the content looks like a URL, quote, or color. When omitted, Teak automatically detects links, quotes, and palettes.
cardType?| "text"
| "link"
| "image"
| "video"
| "audio"
| "document"
| "palette"
| "quote"
Optional card type. Set to `text` to store raw Markdown exactly; omit it to keep automatic URL, quote, and palette detection.
| "text"
| "link"
| "image"
| "video"
| "audio"
| "document"
| "palette"
| "quote"inferredcontent?string
Markdown or plain text body for the card. Prefer this for notes; use `url` when saving a link.
stringnotes?string
Free-form notes attached to the card.
stringsource?string
Where the card was saved from (extension, CLI, API, and so on).
stringtags?string[]
Tags to apply on create.
string[]url?string
URL to save as a link card. Teak may classify the type automatically when `cardType` is omitted.
stringA create response includes the new cardId and its Teak app URL. See Create Card in the API Reference for the complete request and response schemas.
Upload files
File cards use a direct upload flow, so large bytes never pass through the REST API.
Create an upload
Send the file name, media type, and size to POST /v1/uploads.
Upload the bytes
PUT the file to the returned presigned URL and retain its ETag response header.
Create the card
Send the returned fileKey, retained fileEtag, and file metadata to POST /v1/cards.
Files can be up to 100 MB. Uploaded .md and .markdown files become editable text cards, must contain valid UTF-8, and are limited to 512 KiB. .mdx remains a document.
Supported uploads include common image, audio, video, source, design-token, document, archive, and Figma formats. The API Reference is the canonical source for accepted fields and validation responses.
Reliable requests
X-Request-Id?response header
Returned for support and log correlation.
response headerIdempotency-Key?request header
Safely retries card creation and bulk operations without duplicating work.
request headerRateLimit-Limit?response header
Appears with Remaining, Reset, and Retry-After rate-limit headers.
response headerBulk operations accept up to 100 items. Cursor-based listing and the card changes endpoint are available for integrations that need complete pagination or incremental sync.
Endpoint overview
| Route | Purpose |
|---|---|
/v1/cards |
Create or list cards |
/v1/uploads |
Start a direct file upload |
/v1/cards/bulk |
Create or update multiple cards |
/v1/cards/changes |
Read incremental card changes |
/v1/tags |
List tags |
/v1/cards/:cardId |
Read, update, or delete one card |
/v1/cards/:cardId/favorite |
Favorite or unfavorite one card |
See /openapi.json or the API Reference for methods, parameters, schemas, and response examples.
Search and favorites
Search and favorites are filtered card listings. GET /v1/cards supports
q, type, tag, sort, createdAfter, createdBefore, limit,
cursor, favorited, and include:
- Search:
GET /v1/cards?q=design&include=content,metadata - Favorites:
GET /v1/cards?favorited=true&include=content,metadata
The include=content,metadata pair returns full-card fields. The list
response is paginated (items plus pageInfo).
Image card responses include intentionally different URLs: thumbnailUrl is the optimized grid rendition, compactUrl is a smaller rendition for compact lists, placeholderUrl is a tiny loading placeholder, detailUrl is the optimized full-card rendition, and fileUrl remains the signed original used for downloads. These URLs are temporary, signed credentials — consume them as returned instead of storing or modifying them. See the API Reference for field details.
Errors
Errors keep a stable { code, error } shape and can also include requestId, details, or retryAt.
{
"code": "INVALID_INPUT",
"error": "Body must include `content` or `url`"
}
Use the returned request ID when contacting Support. For MCP tool contracts, continue to the dedicated MCP guide.
Check for a saved URL
GET /v1/cards/duplicate?url=<encoded-url> accepts the same bearer credentials as other card endpoints. It checks the exact URL against your non-deleted cards and returns { "cardId": "..." }, or { "cardId": null } when no match exists. The URL must use HTTP or HTTPS and be at most 8,192 characters. Invalid input returns 400; invalid or revoked credentials return 401.