API/Tools API

Tools API

Discover and execute organization tools from one unified registry.

Every organization tool is declared once in convex/tools/definitions/ and exposed through three surfaces: this REST API, the MCP server, and the pnpm tools CLI. Adding a tool to the registry publishes it everywhere at once.

Endpoints

GET  /v1/tools
GET  /v1/tools/:name
POST /v1/tools/:name
EndpointDescription
GET /v1/toolsList every tool with its JSON Schema
GET /v1/tools/:nameJSON Schema of a single tool
POST /v1/tools/:nameExecute a tool with a JSON body as its input

Authentication

Create an organization API key from the organization settings page:

/orgs/{orgSlug}/settings/api-keys

Send it with x-api-key or as a bearer token:

Authorization: Bearer pk_live_YOUR_KEY
Authorization: Bearer YOUR_API_KEY

The key resolves the organization, so no organization id is ever passed in a tool input.

An OAuth access token issued to an MCP client is sent the same way, as a bearer token. API keys are recognized by their pk_live_ prefix, everything else is verified as an OAuth token, so both credentials reach the same handlers.

Available tools

ToolCategoryAccessInputReturns
create_pinpinswrite{ account_id, board_id, image_url, ... }The pin, queued or scheduled
list_pinspinsread{ status?, cursor?, limit? }Pins, newest first
get_pinpinsread{ pin_id }One pin
cancel_pinpinswrite{ pin_id }The cancelled pin
generate_videopinswrite{ image_url, prompt, duration?, model? }{ run_id, request_id, status }
list_video_runspinsread{ product_sku? }Runs with their state and file URL
create_video_pinpinswrite{ video_url, cover_image_url, ... }The video pin, queued or scheduled
attach_video_to_pinpinswrite{ pinterest_pin_id, video_url }The file's address on the shop's server
list_accountsaccountsreadnoneConnected Pinterest accounts
list_boardsaccountsread{ account_id }The account's boards
get_analyticsanalyticsread{ startDate, endDate }Impressions, saves and outbound clicks
get_organizationorganizationreadnoneOrganization id, name, slug
list_membersmembersread{ cursor?, limit? }{ members, count, nextCursor, hasMore }
get_membermembersread{ memberId }One member
get_subscriptionbillingreadnonePlan, status, seats and plan limits

Videos have their own page: Videos API. To reach these tools from Claude Code or another MCP client, see Connect an MCP client.

Discovery response

GET /v1/tools returns a JSON Schema per tool, ready to feed an LLM or a client generator:

{
  "total": 15,
  "tools": [
    {
      "name": "get_member",
      "description": "Get a single member of the organization by member id.",
      "category": "members",
      "access": "read",
      "inputSchema": {
        "type": "object",
        "properties": {
          "memberId": { "type": "string", "minLength": 1 }
        },
        "required": ["memberId"]
      },
      "endpoint": "/v1/tools/get_member",
      "method": "POST",
      "route": { "method": "GET", "path": "/v1/members/:memberId" }
    }
  ]
}

route is the tool's REST alias, or null when it only answers on /v1/tools/<name>. Both paths run the same tool; the alias returns the payload without the data envelope. See Unified Tools for how to declare one.

Execution response

Successful executions return the tool payload under data:

{
  "data": {
    "members": [{ "id": "mem_123", "role": "owner" }],
    "count": 1,
    "nextCursor": null,
    "hasMore": false
  }
}

CLI

export PINCAST_API_KEY="YOUR_API_KEY"
pnpm tools list
pnpm tools run get_member '{"memberId":"mem_123"}'

MCP

The MCP server mounts at /api/mcp and serves the same registry. Authenticate with the same organization API key:

{
  "mcpServers": {
    "pincast": {
      "url": "https://pincast.io/api/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

MCP OAuth

Clients that cannot store an API key (ChatGPT connectors, Claude, MCP Inspector) sign in with OAuth instead. Point the client at /api/mcp with no credentials and it discovers everything it needs:

  1. The unauthenticated request answers 401 with a WWW-Authenticate header pointing at /.well-known/oauth-protected-resource/api/mcp.
  2. That document names the authorization server, /api/auth, whose metadata is served from /.well-known/oauth-authorization-server.
  3. The client registers itself dynamically, then sends the user through sign in, organization selection (/auth/oauth/select-organization) and consent (/auth/oauth/consent).
  4. The issued access token is a JWT carrying the chosen organization_id, so it is scoped to exactly one organization, exactly like an API key.
ScopeGrants
pincast.readEvery read tool and the discovery endpoints
pincast.writeRequired on top of pincast.read for write tools

Only owners and admins can authorize a connection. A token missing pincast.write gets a 403 when it calls a write tool.

Access tokens are short-lived. When one expires, the client starts the authorization-code flow again so the current organization role and consent are checked before a new token is issued.

Errors

StatusDescription
400Invalid JSON body or input that fails the tool schema
401Missing, invalid, or expired key or access token
403Valid token without the scope the tool requires
404Unknown tool, or a resource the tool could not find
413Request body larger than 256 KB
500Internal server error
Get Organization Member APIConnect an MCP client