xmark API
chat with your x bookmarks
base URL
https://www.xmark.dev/api/v1the xmark API uses REST conventions with JSON request and response bodies. all endpoints require authentication via API key.
responses follow a consistent shape: { data: ... } for success and { error: { code, message, requestId } } for errors.
authentication
all API requests must include your API key in the Authorization header. keys are prefixed with nt_live_ and shown exactly once at creation — store them in a secret manager, never commit them.
header format
Authorization: Bearer nt_live_YOUR_API_KEYverify your key
any valid key can call GET /keys/me to introspect itself — useful for confirming a key works and seeing its scopes.
curl "https://www.xmark.dev/api/v1/keys/me" \
-H "Authorization: Bearer nt_live_YOUR_API_KEY"scopes
each API key carries a set of scopes. grant the minimum needed — an admin key can create other keys and manage webhooks, so treat it as a root credential.
| scope | description |
|---|---|
| read | read-only access to owned resources |
| write | create and update owned resources |
| delete | delete owned resources |
| admin | manage API keys and webhook endpoints |
default scopes (if none specified): read, write.
API reference
bookmarks
read, search, and sync the authenticated user's X bookmarks.
paginated list of the caller's bookmarks, newest first
fetch a single bookmark
remove a bookmark. local-only by default (the next sync re-creates anything still bookmarked on X); pass unbookmark=true to also remove it on X
semantic search over the caller's bookmark library (pgvector + OpenAI embeddings)
pull the latest bookmarks from the connected X account, embed new ones, and store them
chat
ask natural-language questions about bookmarks; Claude answers with citations grounded in them.
submit a question. xmark retrieves the most relevant bookmarks via semantic search and has Claude generate an answer with inline citations. returns a single JSON response
conversations
list, read, and delete past chat conversations.
paginated list of the caller's conversations, most recently active first
the conversation's message history, oldest first. assistant messages carry the IDs of the bookmarks retrieved for that answer
permanently delete a conversation and its messages
usage
plan and quota usage for the authenticated user.
the caller's plan, chat-message usage this month, syncs today, bookmark count, and whether an X account is connected. limits are null on unlimited plans
error handling
errors are returned as JSON with code, message, optional field, and requestId. the X-Request-ID response header carries a per-request trace id — include it when contacting support.
{
"error": {
"code": "SERVER_005",
"message": "name must be under 100 characters",
"field": "name",
"requestId": "req_abc123"
}
}| code | HTTP | description |
|---|---|---|
| AUTH_001 | 401 | missing or invalid authorization header |
| AUTH_002 | 403 | API key missing required scope |
| AUTH_004 | 401 | invalid or revoked API key |
| code | HTTP | description |
|---|---|---|
| BILLING_001 | 402 | no active subscription |
| BILLING_006 | 402 | plan usage limit reached (402 on chat quota, 429 on sync rate) |
| BILLING_007 | 402 | subscription required for this operation |
| BILLING_008 | 403 | current plan does not include this feature |
| code | HTTP | description |
|---|---|---|
| RATE_001 | 429 | too many requests - back off and retry |
| code | HTTP | description |
|---|---|---|
| SERVER_001 | 500 | internal server error |
| SERVER_002 | 400 | bad request (malformed body or missing field) |
| SERVER_003 | 404 | resource not found |
| SERVER_004 | 405 | method not allowed |
| SERVER_005 | 400 | validation failed |
| SERVER_008 | 500 | database error |
| SERVER_012 | 409 | conflict (e.g. concurrent modification) |
| code | HTTP | description |
|---|---|---|
| HOOK_001 | 401 | invalid webhook signature |
| HOOK_002 | 500 | webhook processing failed |
| HOOK_004 | 408 | webhook delivery timed out |