Getting Started
Endpoints
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
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": integer, "amount": integer, "balance_after": integer, "type": "api_call" | "monthly_reset" | "purchase" | "refund" | "bonus", "description": string | null, "metadata": object | null, "created_at": datetime }