/v1/tools REST Gateway
Reference documentation for the /v1/tools REST gateway: authenticating with a personal API key, discovering the public tool catalog, invoking tools, handling idempotency, and interpreting billing and error responses.
The /v1/tools endpoint is a catalog-derived REST gateway that lets you invoke every tool in the public MarkDocket tool catalog using a personal API key. It is the same surface used by the @markdocket/cli package in password-mode and by any script that needs direct programmatic access without a full OAuth 2.1 / MCP client.
One catalog, four surfaces. The same tool registry that powers the CLI, the stdio MCP server, and the hosted /mcp endpoint also backs /v1/tools. A tool added to the catalog automatically becomes available here — no extra integration needed.
Authentication
All requests to /v1/tools must carry a personal API key in the Authorization header:
Authorization: Bearer mdk_live_...Personal API keys are generated from your account settings in the MarkDocket dashboard. API keys authenticate as your user identity and are subject to the same plan limits and billing rules as interactive sessions.
OAuth access tokens cannot be used here. OAuth 2.1 access tokens issued during the browser-login flow are resource-bound to the hosted /mcp endpoint and are rejected on /v1/tools. If you authenticated with markdocket login (browser flow), use the hosted MCP surface instead; /v1/tools is for personal API key sessions only.
HMAC catalog provenance
Requests are verified to have originated through the cataloged gateway before any /api/ route is reached. This happens transparently — you do not compute the proof yourself; it is added by the gateway before dispatching your call. The practical effect is that only tools explicitly listed in the catalog can be invoked; no undocumented /api/ routes are reachable through this surface.
Discovering the tool catalog
Fetch the full list of available tools with a GET request:
GET /v1/tools
Authorization: Bearer mdk_live_...Each entry in the response includes the tool name, a human-readable description, its JSON Schema for inputs, the tool category, and whether the operation is read-only or write-mutating.
{
"tools": [
{
"name": "trademark_search",
"description": "Search USPTO trademark records by keyword, owner, or serial number.",
"category": "trademarks",
"readOnly": true,
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string" }
},
"required": ["query"]
}
}
]
}Agent-only tools are excluded. Tools such as web_search and classify_goods that depend on a live LLM agent session are not available through /v1/tools or the CLI. The catalog you see here is the full public surface.
Invoking a tool
Call any cataloged tool with a POST request:
POST /v1/tools/{tool_name}
Authorization: Bearer mdk_live_...
Content-Type: application/json
Idempotency-Key: <your-unique-key>
{
"query": "ACME coffee"
}Replace {tool_name} with the exact name returned by the catalog listing.
The request body must conform to the inputSchema for the tool. Requests that fail schema validation return 400 Bad Request with a description of the validation error.
Response format
A successful invocation returns 200 OK with the tool's structured result:
{
"result": { ... }
}The shape of result varies by tool and matches the tool's documented output schema.
Idempotency
All write-mutating tool calls (tools where readOnly is false) require an Idempotency-Key header. Read-only tools accept the header but do not require it.
Idempotency-Key: 01HZEX7Q3BVN4YK1A2C5D6E7F8Choose any string that is unique per logical operation — a UUID or ULID works well. The server persists your key and deduplicates replays: if you retry a request with the same key, you receive the original response without the operation being performed again.
Omitting Idempotency-Key on a write-mutating call returns 400 Bad Request. Generate a fresh key for each distinct operation and reuse it only on retries of that same operation.
Billing and plan limits
Tool invocations are metered against your plan. When a call would exceed your available balance or requires a plan upgrade, the API returns 402 Payment Required with a structured billing block envelope:
{
"reason": "insufficient_credits",
"requiredAction": "add_credits",
"contractVersion": "2026-07-12-payg-v1",
"feature": "trademark_search"
}The reason field describes why the call was blocked. The requiredAction field tells you what the user must do to unblock it. Possible actions include adding credits, upgrading the plan, or enabling a specific feature. These two fields always correspond — a given reason maps to exactly one requiredAction.
Handle 402 responses by surfacing the requiredAction to your user and directing them to the billing section of the dashboard.
Error reference
| Status | Meaning |
|---|---|
400 Bad Request | Invalid input — schema validation failure or missing Idempotency-Key on a write call |
401 Unauthorized | Missing or invalid API key |
402 Payment Required | Billing block — see billing block envelope above |
403 Forbidden | Valid key but insufficient scope or feature access |
404 Not Found | Tool name not found in the current catalog |
409 Conflict | Optimistic concurrency failure (relevant for update operations) |
429 Too Many Requests | Rate limit exceeded — back off and retry |
500 Internal Server Error | Unexpected server error — safe to retry with the same Idempotency-Key |
Rate limits and retries
When you receive 429 Too Many Requests, wait before retrying. The response includes a Retry-After header indicating the minimum number of seconds to wait. For 5xx errors, retrying with the original Idempotency-Key is safe and will not duplicate the operation.
Comparison with other surfaces
| Surface | Auth method | Transport | Agent-only tools |
|---|---|---|---|
/v1/tools | Personal API key | REST (JSON) | Excluded |
Hosted /mcp | OAuth 2.1 access token | MCP Streamable HTTP | Excluded |
@markdocket/cli (password mode) | Personal API key | REST via /v1/tools | Excluded |
@markdocket/cli (browser login) | OAuth 2.1 | MCP via hosted /mcp | Excluded |
| Agent chat | Session cookie or delegated token | SSE streaming | Included |
Quick start example
The following example searches for USPTO trademark records using curl:
curl -X POST https://api.markdocket.com/v1/tools/trademark_search \
-H "Authorization: Bearer mdk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"query": "ACME coffee"}'To list all available tools first:
curl https://api.markdocket.com/v1/tools \
-H "Authorization: Bearer mdk_live_YOUR_KEY_HERE"TypeScript example
const key = process.env.MARKDOCKET_API_KEY;
// Discover the catalog
const catalogRes = await fetch('https://api.markdocket.com/v1/tools', {
headers: { Authorization: `Bearer ${key}` },
});
const { tools } = await catalogRes.json();
// Invoke a tool
const res = await fetch('https://api.markdocket.com/v1/tools/trademark_search', {
method: 'POST',
headers: {
Authorization: `Bearer ${key}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({ query: 'ACME coffee' }),
});
if (res.status === 402) {
const block = await res.json();
// Direct user to billing: block.requiredAction
throw new Error(`Billing required: ${block.requiredAction}`);
}
if (!res.ok) {
throw new Error(`Tool call failed: ${res.status}`);
}
const { result } = await res.json();
console.log(result);MCP Server (stdio)
Documents the @markdocket/cli stdio MCP server: how to connect it to AI hosts, how tools are registered from the shared catalog, and how MCP behavioral annotations are derived automatically from tool metadata.
Hosted MCP Endpoint
Reference page for the MarkDocket hosted MCP endpoint: how to connect over OAuth 2.1, how access tokens are scoped, and which tools are available compared to the stdio server.