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:

  1. Create an account
  2. Go to your Dashboard
  3. 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"
}
GET /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


                                
GET /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


                                
POST /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


                                
POST /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
}