Getting Started
Endpoints
MCP Server
Reference
API Documentation
Everything you need to integrate the Fetching Company Brand Intelligence API.
Last updated: March 2026
Authentication
All API requests require a bearer token. To get your token:
- Create an account
- Go to your Dashboard
- Navigate to API Tokens and create a new token
Include the token in every request as a Bearer token in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Making Requests
Base URL: https://fetching.company/api/v1
Content-Type: All requests must send application/json
Response format: All responses are wrapped in a {"data": ...} envelope.
curl https://fetching.company/api/v1/me \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
Rate Limiting
Rate limits vary by plan. Limits are applied per-token on a per-minute basis.
| Plan | Requests/min |
|---|---|
| Free | 10 |
| Pro | 60 |
| Business | 120 |
| Enterprise | 500 |
Rate limit information is included in response headers:
| Header | Description |
|---|---|
| X-RateLimit-Limit | Requests allowed per minute |
| X-RateLimit-Remaining | Requests remaining in current window |
| Retry-After | Seconds to wait before retrying (only on 429) |
When rate limited, you receive a 429 response:
{ "type": "https://httpstatuses.com/429", "title": "Too Many Requests", "status": 429, "detail": "Rate limit exceeded. Retry after 30 seconds.", "plan": "pro", "upgrade_url": "https://fetching.company/pricing" }
Credits & Billing
Each API call to /analyze costs 1 credit. AI Enhancement via /enhance costs 2 credits per call. Calls to /me and /usage are free.
Your remaining credits are returned in the X-Credits-Remaining response header.
When credits are exhausted, a 402 error is returned:
{ "type": "https://httpstatuses.com/402", "title": "Insufficient Credits", "status": 402, "detail": "You have 0 credits remaining.", "credits_balance": 0, "plan": "free", "upgrade_url": "https://fetching.company/pricing" }
/me
Auth required
Returns current user, plan, credits balance, and rate limits.
Parameters
No parameters required.
Response
{ "data": { "name": "Jasper", "email": "jasper@coding.agency", "plan": "pro", "plan_label": "Pro", "credits_balance": 487, "credits_monthly": 500, "rate_limit_per_minute": 60, "ai_enhancement": true, "credits_reset_at": "2026-04-01T00:00:00Z" } }
Code Examples
curl https://fetching.company/api/v1/me \ -H "Authorization: Bearer YOUR_API_KEY"
$response = Http::withToken('YOUR_API_KEY') ->get('https://fetching.company/api/v1/me'); $account = $response->json('data');
const response = await fetch('https://fetching.company/api/v1/me', { headers: { 'Authorization': 'Bearer YOUR_API_KEY' }, }); const { data } = await response.json();
import requests response = requests.get( 'https://fetching.company/api/v1/me', headers={'Authorization': 'Bearer YOUR_API_KEY'}, ) account = response.json()['data']
Try it
/usage
Auth required
Returns paginated credit transaction history.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| per_page | integer | No | Results per page (default: 25, max: 100) |
Response
{ "data": [ { "id": 142, "amount": -1, "balance_after": 487, "type": "api_call", "description": "POST /analyze stripe.com", "created_at": "2026-03-23T10:15:00Z" } ], "links": { "first": "...", "last": "...", "prev": null, "next": "..." }, "meta": { "current_page": 1, "last_page": 6, "per_page": 25, "total": 142 } }
Code Examples
curl "https://fetching.company/api/v1/usage?per_page=50" \ -H "Authorization: Bearer YOUR_API_KEY"
$response = Http::withToken('YOUR_API_KEY') ->get('https://fetching.company/api/v1/usage', [ 'per_page' => 50, ]);
const response = await fetch('https://fetching.company/api/v1/usage?per_page=50', { headers: { 'Authorization': 'Bearer YOUR_API_KEY' }, });
response = requests.get( 'https://fetching.company/api/v1/usage', headers={'Authorization': 'Bearer YOUR_API_KEY'}, params={'per_page': 50}, )
Try it
/analyze
Auth required
Extracts logos, colors, fonts, contact information, and social links from the given URL.
Costs 1 credit per call. Results are cached for 24 hours.
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The URL to analyze (max 2048 chars) |
| locale | string | No | Locale override (e.g. "nl", "de") |
Response
{ "data": { "url": "https://stripe.com", "domain": "stripe.com", "status": "completed", "meta": { "name": "Stripe", "title": "Stripe | Financial Infrastructure", "description": "...", "language": "en", "favicon": "https://stripe.com/favicon.ico" }, "logos": [{ "url": "https://...", "type": "svg", "source": "nav", "width": null, "height": null, "inline_svg": "<svg...>" }], "colors": { "primary": "#635BFF", "secondary": "#0A2540", "accent": "#00D4AA", "all_colors": ["#635BFF", "#0A2540", "..."] }, "fonts": { "heading": "Inter", "body": "Inter", "all_fonts": [{ "name": "Inter", "weights": [400, 600] }] }, "contact": { "emails": ["support@stripe.com"], "phones": [{ "e164": "+18888263462" }], "address": null }, "socials": [ { "platform": "twitter", "url": "https://twitter.com/stripe" } ], "analyzed_at": "2026-03-23T10:15:00Z" } }
Code Examples
curl -X POST https://fetching.company/api/v1/analyze \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://stripe.com"}'
$response = Http::withToken('YOUR_API_KEY') ->post('https://fetching.company/api/v1/analyze', [ 'url' => 'https://stripe.com', ]); $brand = $response->json('data');
const response = await fetch('https://fetching.company/api/v1/analyze', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ url: 'https://stripe.com' }), }); const { data } = await response.json();
import requests response = requests.post( 'https://fetching.company/api/v1/analyze', headers={'Authorization': 'Bearer YOUR_API_KEY'}, json={'url': 'https://stripe.com'}, ) brand = response.json()['data']
Try it
/enhance
Auth required
Pro+
Enriches extracted brand data with AI-generated descriptions, color corrections, and additional context.
Requires Pro plan or higher. Costs 2 credits per call.
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The analyzed URL |
| meta | object | Yes | Object with name and language properties |
| colors | object | No | Extracted color data from /analyze |
| fonts | object | No | Extracted font data from /analyze |
| contact | object | No | Extracted contact data from /analyze |
| socials | object | No | Extracted social data from /analyze |
| page_evidence | string | No | Raw page text for additional AI context |
Response
{ "data": { "organization_name": "Stripe", "description": "Stripe is a financial infrastructure platform...", "color_primary": "#635BFF", "color_secondary": "#0A2540", "color_accent": "#00D4AA", "primary_heading_font": "Inter", "primary_body_font": "Inter", "primary_email": "support@stripe.com", "primary_phone": "+18888263462", "confidence_percent": 92, "_usage": { "input_tokens": 1250, "output_tokens": 340, "total_tokens": 1590, "cost_usd": 0.0048 } } }
Code Examples
curl -X POST https://fetching.company/api/v1/enhance \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://stripe.com","meta":{"name":"Stripe","language":"en"}}'
$response = Http::withToken('YOUR_API_KEY') ->post('https://fetching.company/api/v1/enhance', [ 'url' => 'https://stripe.com', 'meta' => ['name' => 'Stripe', 'language' => 'en'], ]);
const response = await fetch('https://fetching.company/api/v1/enhance', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json', }, body: JSON.stringify({ url: 'https://stripe.com', meta: { name: 'Stripe', language: 'en' }, }), });
response = requests.post( 'https://fetching.company/api/v1/enhance', headers={'Authorization': 'Bearer YOUR_API_KEY'}, json={ 'url': 'https://stripe.com', 'meta': {'name': 'Stripe', 'language': 'en'}, }, )
Try it
MCP Server Setup
NewFetching Company provides a Model Context Protocol (MCP) server for direct AI agent integration. Connect Claude Code, Claude Desktop, ChatGPT, Cursor, or any MCP-compatible client to analyze and enhance brands without writing API wrapper code.
Connection URL
Authentication
The MCP server uses the same Bearer token authentication as the REST API. Pass your Sanctum API token in the Authorization header.
Available Tools
| Tool | Description | Credits |
|---|---|---|
| analyze-brand | Extract logos, colors, fonts, contacts, and socials from any URL | 1 credit |
| enhance-brand | AI-powered brand descriptions, color validation, and font mapping | 2 credits |
| account-info | Check your current plan, credit balance, and rate limits | Free |
| usage-history | View recent credit transactions and API usage | Free |
Configuration Examples
Claude Code / Claude Desktop
{ "mcpServers": { "fetching-company": { "url": "https://fetching.company/mcp/brand-intelligence", "headers": { "Authorization": "Bearer YOUR_API_TOKEN" } } } }
Cursor
Add this to your .cursor/mcp.json:
{ "mcpServers": { "fetching-company": { "url": "https://fetching.company/mcp/brand-intelligence", "headers": { "Authorization": "Bearer YOUR_API_TOKEN" } } } }
Credit costs: MCP tool calls use the same credit system as the REST API. analyze-brand costs 1 credit, enhance-brand costs 2 credits, and account-info / usage-history are free.
Error Codes
All errors follow the RFC 7807 Problem Details format.
| Status | Title | When it occurs |
|---|---|---|
| 401 | Unauthorized | Bearer token is missing, invalid, or expired. |
| 402 | Insufficient Credits | No credits remaining. Purchase more or upgrade your plan. |
| 403 | Plan Upgrade Required | Feature (e.g. AI Enhancement) requires a higher plan. |
| 422 | Validation Error | Request body failed validation. Check the errors object for details. |
| 429 | Too Many Requests | Rate limit exceeded. Respect the Retry-After header. |
| 500 | Internal Server Error | Unexpected error on our end. Contact support if it persists. |
Response Schemas
BrandAnalysis
Returned by POST /analyze
{ "url": string, "domain": string, "status": "completed" | "failed", "meta": { name, title, description, language, favicon }, "logos": [{ url, type, source, width, height, inline_svg }], "colors": { primary, secondary, accent, all_colors[] }, "fonts": { heading, body, all_fonts[] }, "contact": { emails[], phones[], address }, "socials": [{ platform, url }], "analyzed_at": datetime }
AiEnhancement
Returned by POST /enhance
{ "organization_name": string, "description": string, "color_primary": string (hex), "color_secondary": string (hex), "color_accent": string (hex), "primary_heading_font": string, "primary_body_font": string, "primary_email": string, "primary_phone": string (E.164), "confidence_percent": integer (0-100), "_usage": { input_tokens, output_tokens, total_tokens, cost_usd } }
AccountInfo
Returned by GET /me
{ "name": string, "email": string, "plan": "free" | "pro" | "business" | "enterprise", "plan_label": string, "credits_balance": integer, "credits_monthly": integer, "rate_limit_per_minute": integer, "ai_enhancement": boolean, "credits_reset_at": datetime | null }
CreditTransaction
Returned by GET /usage
{ "id": string (ULID), "amount": integer, "balance_after": integer, "type": "api_call" | "monthly_reset" | "purchase" | "refund" | "bonus", "description": string | null, "metadata": object | null, "created_at": datetime }