{"openapi":"3.1.0","info":{"title":"BirdSift API","version":"1.0.0","description":"BirdSift API v1 — list saved leads, run bounded local-business searches, and draft outreach. Human-readable reference: https://www.birdsift.com/docs/api. Agent instructions: https://www.birdsift.com/agent-instructions. Rate limit: 60 requests/minute per API key. Searches and outreach drafts consume workspace credits.","contact":{"name":"BirdSift","url":"https://www.birdsift.com/developers"}},"servers":[{"url":"https://api.birdsift.com"}],"externalDocs":{"description":"BirdSift API reference","url":"https://www.birdsift.com/docs/api"},"tags":[{"name":"docs","description":"Public reference material"},{"name":"auth","description":"OAuth 2.0 discovery metadata"},{"name":"leads","description":"Saved workspace leads"},{"name":"searches","description":"Bounded lead discovery"},{"name":"credits","description":"Workspace credit balance"},{"name":"mcp","description":"Model Context Protocol server"}],"paths":{"/openapi.json":{"get":{"tags":["docs"],"summary":"OpenAPI specification","description":"Returns this OpenAPI 3.1 document for codegen and agent function calling.","operationId":"getOpenApiSpec","security":[],"responses":{"200":{"description":"OpenAPI 3.1 JSON document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/v1/docs":{"get":{"tags":["docs"],"summary":"API reference (markdown)","description":"Public markdown API reference. No authentication required — use to discover endpoints before calling /v1.","operationId":"getV1Docs","security":[],"responses":{"200":{"description":"Markdown API reference","content":{"text/markdown":{"schema":{"type":"string"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["auth"],"summary":"OAuth 2.0 authorization server metadata","description":"RFC 8414 authorization server metadata for the OAuth 2.0 flow behind /mcp. No authentication required — fetch this first to discover the authorization, token and dynamic client registration endpoints.","operationId":"getOAuthAuthorizationServerMetadata","security":[],"responses":{"200":{"description":"RFC 8414 authorization server metadata","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["auth"],"summary":"OAuth 2.0 protected resource metadata","description":"RFC 9728 protected resource metadata naming the authorization server that guards /mcp. No authentication required.","operationId":"getOAuthProtectedResourceMetadata","security":[],"responses":{"200":{"description":"RFC 9728 protected resource metadata","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/mcp":{"post":{"tags":["mcp"],"summary":"MCP Streamable HTTP endpoint","description":"Model Context Protocol endpoint (Streamable HTTP transport) exposing the BirdSift tools for local-business search, saved leads and outreach drafts. Unlike /v1 — which takes a workspace API key — this endpoint authenticates with an OAuth 2.0 access token; see /.well-known/oauth-protected-resource. Request and response bodies are JSON-RPC 2.0 messages defined by the MCP specification, not by this document.","operationId":"postMcpMessage","security":[{"OAuth2":["email","profile"]}],"requestBody":{"required":true,"description":"JSON-RPC 2.0 request as defined by the MCP specification","content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"JSON-RPC 2.0 response, or an SSE stream when the client accepts one","content":{"application/json":{"schema":{"type":"object"}},"text/event-stream":{"schema":{"type":"string"}}}},"401":{"description":"Missing or invalid access token. The WWW-Authenticate header carries a `resource_metadata` pointer to /.well-known/oauth-protected-resource/mcp, which is where an MCP client starts OAuth discovery. The body is an RFC 6749 error object, not the /v1 ErrorResponse shape — see mcp/auth.ts.","headers":{"WWW-Authenticate":{"description":"RFC 9728 challenge naming the protected resource metadata URL","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthErrorResponse"}}}}}}},"/v1/leads":{"get":{"tags":["leads"],"summary":"List saved leads","description":"Returns a cursor-paginated list of leads saved in the authenticated workspace.","operationId":"listLeads","parameters":[{"name":"limit","in":"query","description":"Page size (1–100)","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque cursor from a previous response's next_cursor"}],"responses":{"200":{"description":"Lead page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadListResponse"}}}},"400":{"description":"Invalid query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (60 requests/minute per key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/leads/{id}":{"get":{"tags":["leads"],"summary":"Get one saved lead","description":"Fetch a single lead by UUID, including website audit flags used for outreach.","operationId":"getLead","parameters":[{"name":"id","in":"path","required":true,"description":"Lead UUID","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Lead detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadDetail"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/credits":{"get":{"tags":["credits"],"summary":"Get credit balance","description":"Returns the remaining credit balance for the authenticated workspace.","operationId":"getCredits","responses":{"200":{"description":"Current balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditsResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/searches":{"post":{"tags":["searches"],"summary":"Run a bounded search and save results","description":"Queries Google Places for local businesses matching trade + location filters, verifies websites, saves matches as workspace leads, and debits credits.","operationId":"createSearch","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}}},"responses":{"200":{"description":"Search results saved as leads","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"400":{"description":"invalid_request — malformed body, queries or max_results out of range, or more than 2 queries from a workspace that has never bought credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (60 requests/minute per key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/leads/{id}/outreach-draft":{"post":{"tags":["leads"],"summary":"Draft outreach email for a saved lead","description":"Generates a fact-based cold email draft for a saved lead using verified Google Places and website audit data.","operationId":"draftOutreach","parameters":[{"name":"id","in":"path","required":true,"description":"Lead UUID","schema":{"type":"string","format":"uuid"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutreachDraftRequest"}}}},"responses":{"200":{"description":"Draft email","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutreachDraftResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"402":{"description":"Insufficient credits","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Insufficient audit data to draft outreach","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"OAuthErrorResponse":{"type":"object","required":["error"],"description":"RFC 6749 §5.2 error object, as returned by the OAuth-guarded /mcp endpoint.","properties":{"error":{"type":"string","description":"OAuth error code, e.g. `invalid_token`"},"error_description":{"type":"string","description":"Human-readable error message"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code"},"message":{"type":"string","description":"Human-readable error message"}}}}},"LeadSummary":{"type":"object","required":["id","place_id","name","category","address","website","email","outreach_status","added_at"],"properties":{"id":{"type":"string","format":"uuid","description":"BirdSift lead UUID"},"place_id":{"type":"string","description":"Google Places ID"},"name":{"type":"string"},"category":{"type":"string","description":"Business category or trade"},"address":{"type":"string","nullable":true},"website":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"outreach_status":{"type":"string","enum":["new","contacted","replied","won","lost"],"description":"Where the lead sits in the outreach pipeline"},"added_at":{"type":"string","format":"date-time"}}},"LeadDetail":{"allOf":[{"$ref":"#/components/schemas/LeadSummary"},{"type":"object","required":["no_website_flag","not_mobile_friendly_flag","outdated_website_flag"],"properties":{"no_website_flag":{"type":"boolean","nullable":true},"not_mobile_friendly_flag":{"type":"boolean","nullable":true},"outdated_website_flag":{"type":"boolean","nullable":true},"last_media_year":{"type":"integer","nullable":true,"description":"Year the newest photo on the homepage was uploaded. Null when no dated media path was readable — never assume recent."}}}]},"LeadListResponse":{"type":"object","required":["leads","next_cursor"],"properties":{"leads":{"type":"array","items":{"$ref":"#/components/schemas/LeadSummary"}},"next_cursor":{"type":"string","nullable":true,"description":"Pass as ?cursor= on the next page"}}},"CreditsResponse":{"type":"object","required":["balance"],"properties":{"balance":{"type":"integer","description":"Remaining workspace credits"}}},"SearchQuery":{"type":"object","required":["location","category"],"properties":{"location":{"type":"string","description":"City or region, e.g. Austin, TX"},"category":{"type":"string","description":"Trade or business type, e.g. dentist"}}},"SearchFilters":{"type":"object","properties":{"min_rating":{"type":"number","description":"Minimum Google rating (0–5)"},"no_website":{"type":"boolean","description":"Only businesses with no website"},"not_mobile_friendly":{"type":"boolean","description":"Only non-mobile-friendly sites"},"outdated_website":{"type":"boolean","description":"Only outdated-looking sites"},"stale_content":{"type":"boolean","description":"Only sites whose newest homepage photo is 3+ years old. Narrow — the date is only readable on sites that file media by date."}}},"SearchRequest":{"type":"object","required":["queries","max_results"],"properties":{"queries":{"type":"array","minItems":1,"maxItems":5,"description":"Up to 5 queries. A workspace that has never bought credits can send at most 2 (400 invalid_request otherwise).","items":{"$ref":"#/components/schemas/SearchQuery"}},"filters":{"$ref":"#/components/schemas/SearchFilters"},"max_results":{"type":"integer","minimum":1,"maximum":25,"description":"Maximum leads to return across all queries"}}},"SearchResultLead":{"allOf":[{"$ref":"#/components/schemas/LeadSummary"},{"type":"object","properties":{"has_website":{"type":"boolean","nullable":true},"is_mobile_friendly":{"type":"boolean","nullable":true},"is_outdated":{"type":"boolean","nullable":true}}}]},"SearchResponse":{"type":"object","required":["results","credits_spent","truncated"],"properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SearchResultLead"}},"credits_spent":{"type":"integer","description":"Credits consumed by this search"},"truncated":{"type":"boolean","description":"True when max_results or the per-query cap (60) stopped the scan early, or analysis budget ran out"}}},"OutreachDraftRequest":{"type":"object","properties":{"locale":{"type":"string","enum":["en","fr"],"description":"Draft language"}}},"OutreachDraftResponse":{"type":"object","required":["subject","body","facts_used"],"properties":{"subject":{"type":"string"},"body":{"type":"string"},"facts_used":{"type":"array","items":{"type":"string"},"description":"Verified facts referenced in the draft"}}}},"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","description":"Workspace API key (`bsk_live_…`). Create from the app."},"OAuth2":{"type":"oauth2","description":"Supabase OAuth 2.0 access token for workspace-scoped MCP access. Metadata: GET /.well-known/oauth-authorization-server","flows":{"authorizationCode":{"authorizationUrl":"https://tzngbfxhkxvbtoxsypii.supabase.co/auth/v1/oauth/authorize","tokenUrl":"https://tzngbfxhkxvbtoxsypii.supabase.co/auth/v1/oauth/token","scopes":{"email":"Email address","profile":"Basic profile"}}}}}},"security":[{"ApiKeyAuth":[]}]}