API Reference
A simple REST API to categorize any URL or block of text in seconds. One endpoint, a fixed 25-category taxonomy, a confidence score.
Overview
CategorizeAPI provides a single HTTP endpoint that accepts a URL or a block of text and returns a category, an optional subcategory, a confidence score, and a short reasoning. The API is designed to be minimal and predictable — one endpoint, JSON in, JSON out.
Base URL
Key capabilities
- URL or text input — Send a link and we fetch the page server-side, or send text directly
- Auto-detection — Set
typetoautoand we'll detect which one you sent - Fixed taxonomy — 25 top-level categories, consistent across every request
- Confidence + reasoning — Every response includes a 0-1 confidence score and a one-line explanation
- Automatic fallback — A secondary model/provider kicks in if the primary call fails
Authentication
All requests must include a valid API key in the Authorization header using the Bearer scheme.
Authorization: Bearer YOUR_API_KEY
API key format
API keys follow the format sk_live_xxxxxxxxxxxxxxxxxxxxxxxx (production) or sk_test_xxxxxxxxxxxxxxxxxxxxxxxx (test environment). Keep your key secret — treat it like a password.
Quick Start
Send a POST request to /api/categorize with a URL or text. You'll get a category back in a couple of seconds.
# Install: curl is available on all platforms curl -X POST https://categorizeapi.com/api/categorize \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"input": "https://example.com", "type": "auto"}'
const categorize = async (input) => { const res = await fetch('https://categorizeapi.com/api/categorize', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ input, type: 'auto' }) }); const data = await res.json(); console.log(data.category, data.confidence); }; categorize('https://example.com');
import requests response = requests.post( "https://categorizeapi.com/api/categorize", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"input": "https://example.com", "type": "auto"} ) data = response.json() print(data["category"], data["confidence"])
<?php $response = file_get_contents('https://categorizeapi.com/api/categorize', false, stream_context_create(['http' => [ 'method' => 'POST', 'header' => "Authorization: Bearer YOUR_API_KEY\r\nContent-Type: application/json", 'content' => json_encode(['input' => 'https://example.com', 'type' => 'auto']) ]]) ); $data = json_decode($response, true); echo $data['category'];
Example response
{
"success": true,
"category": "Technology & Computing",
"subcategory": "Web Services",
"confidence": 0.93,
"reasoning": "The page describes a software product and its documentation.",
"input_type": "url",
"processing_time": 1.14,
"requests_remaining": 4997
}
Endpoint
The API exposes a single categorization endpoint.
Categorizes the provided URL or text and returns a structured JSON response.
Request headers
| Header | Value | Required |
|---|---|---|
| Authorization | Bearer YOUR_API_KEY |
Required |
| Content-Type | application/json |
Required |
Request Parameters
Send a JSON body with the following fields. Only input is required.
| Parameter | Type | Default | Description |
|---|---|---|---|
| input required |
string | — | A URL (http:// or https://) or a block of text. Text input is capped at 7,500 characters. |
| type optional |
string | auto |
How to interpret input.auto — detect URL vs text automaticallyurl — force URL handling (errors if input isn't a valid URL)text — force plain-text handling, even if it looks like a URL
|
Full request example
{
"input": "https://example.com/blog/electric-vehicles-2030",
"type": "auto"
}
type=url (or an auto-detected URL), the page is fetched server-side with an 8-second timeout, up to 3 redirects, and a ~300KB download cap. The title, meta description, and a content excerpt are extracted and classified — the raw HTML is never returned or stored.Response Format
All responses are JSON. A successful request returns HTTP 200.
{
"success": true,
"category": "News & Politics",
"subcategory": "World News",
"confidence": 0.87,
"reasoning": "The text reports on an international diplomatic event.",
"input_type": "text",
"processing_time": 0.92,
"requests_remaining": 4996
}
Response fields
| Field | Type | Description |
|---|---|---|
| success | boolean | Always true on success. |
| category | string | One of the 25 top-level categories — see Categories. |
| subcategory | string | null | A more specific free-form label, when the model can be more precise. Not a fixed list. |
| confidence | float | Model confidence in the assigned category, from 0.0 to 1.0. |
| reasoning | string | One short sentence explaining why that category was chosen. |
| input_type | string | Either url or text — how the input was actually interpreted. |
| processing_time | float | Request duration in seconds. |
| requests_remaining | integer | Remaining requests in the current billing period. |
Categories
Every response's category field is exactly one of these 25 values, verbatim:
| # | Category |
|---|---|
| 1 | Arts & Entertainment |
| 2 | Automotive |
| 3 | Business & Industrial |
| 4 | Careers |
| 5 | Education |
| 6 | Family & Parenting |
| 7 | Finance & Investing |
| 8 | Food & Drink |
| 9 | Gaming |
| 10 | Health & Fitness |
| 11 | Hobbies & Interests |
| 12 | Home & Garden |
| 13 | Law & Government |
| 14 | News & Politics |
| 15 | Pets & Animals |
| 16 | Real Estate |
| 17 | Science |
| 18 | Shopping & Retail |
| 19 | Society & Culture |
| 20 | Sports |
| 21 | Style & Fashion |
| 22 | Technology & Computing |
| 23 | Travel & Tourism |
| 24 | Religion & Spirituality |
| 25 | Adult Content |
Errors
Error responses include an error field describing what went wrong. HTTP status codes follow standard conventions.
{
"error": "Invalid API key"
}
| Status | Error | Description |
|---|---|---|
| 400 | Invalid parameters | Missing input, type not one of auto/url/text, text exceeds the character limit, or malformed JSON body. |
| 401 | Unauthorized | Missing, expired, or invalid API key. Check the Authorization header. |
| 405 | Method not allowed | Only POST requests are accepted. |
| 422 | URL fetch failed | type=url was requested but the page could not be fetched — timed out, returned a non-2xx/3xx status, or had no extractable content. |
| 429 | Rate limit exceeded | Monthly request quota or the 60 req/min burst limit was reached. Upgrade your plan or slow down. |
| 500 | Server error | Both the primary and fallback models failed. Retry with exponential backoff. If the problem persists, contact support. |
cURL Examples
Complete examples using curl — available on Linux, macOS, and Windows.
Categorize a URL
curl -X POST https://categorizeapi.com/api/categorize \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "input": "https://www.espn.com", "type": "url" }'
Categorize raw text
curl -X POST https://categorizeapi.com/api/categorize \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "input": "The Federal Reserve announced a quarter-point rate cut today, citing cooling inflation and a softening labor market.", "type": "text" }'
JavaScript Examples
Works in Node.js 18+ (built-in fetch) and all modern browsers.
class CategorizeAPIClient { constructor(apiKey, baseURL = 'https://categorizeapi.com/api') { this.apiKey = apiKey; this.baseURL = baseURL; } async categorize(input, type = 'auto') { const res = await fetch(`${this.baseURL}/categorize`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ input, type }) }); if (!res.ok) { const err = await res.json(); throw new Error(err.error || 'API error'); } return res.json(); } } // Usage const client = new CategorizeAPIClient('YOUR_API_KEY'); const result = await client.categorize('https://example.com'); console.log('Category:', result.category); console.log('Confidence:', Math.round(result.confidence * 100) + '%');
// npm install axios const axios = require('axios'); const client = axios.create({ baseURL: 'https://categorizeapi.com/api', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }); async function categorize(input, type = 'auto') { const { data } = await client.post('/categorize', { input, type }); return data; } categorize('https://example.com') .then(r => console.log(r.category, r.confidence)) .catch(e => console.error(e.response?.data?.error || e.message));
Python Examples
Works with Python 3.7+. Uses the requests library (pip install requests).
import requests class CategorizeAPIClient: def __init__(self, api_key: str, base_url: str = "https://categorizeapi.com/api"): self.api_key = api_key self.base_url = base_url def categorize(self, input: str, type: str = "auto") -> dict: response = requests.post( f"{self.base_url}/categorize", headers={"Authorization": f"Bearer {self.api_key}"}, json={"input": input, "type": type}, timeout=30 ) response.raise_for_status() return response.json() # Usage client = CategorizeAPIClient("YOUR_API_KEY") result = client.categorize("https://example.com") print(f"Category: {result['category']}") print(f"Confidence: {round(result['confidence'] * 100)}%")
import aiohttp import asyncio async def categorize(api_key: str, input: str, type: str = "auto") -> dict: async with aiohttp.ClientSession() as session: async with session.post( "https://categorizeapi.com/api/categorize", headers={"Authorization": f"Bearer {api_key}"}, json={"input": input, "type": type} ) as resp: return await resp.json() # Usage result = asyncio.run(categorize( "YOUR_API_KEY", "https://example.com" )) print(result["category"])
PHP Examples
Works with PHP 7.4+. Uses cURL (enabled by default in most PHP installations).
<?php class CategorizeAPIClient { private string $apiKey; private string $baseUrl = 'https://categorizeapi.com/api'; public function __construct(string $apiKey) { $this->apiKey = $apiKey; } public function categorize(string $input, string $type = 'auto'): array { $payload = json_encode(['input' => $input, 'type' => $type]); $ch = curl_init($this->baseUrl . '/categorize'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $this->apiKey, 'Content-Type: application/json' ], CURLOPT_TIMEOUT => 30 ]); $body = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode !== 200) { $err = json_decode($body, true); throw new \RuntimeException($err['error'] ?? 'API error'); } return json_decode($body, true); } } // Usage $client = new CategorizeAPIClient('YOUR_API_KEY'); $result = $client->categorize('https://example.com'); echo $result['category'] . PHP_EOL; echo $result['confidence'] . PHP_EOL;
<?php // composer require guzzlehttp/guzzle use GuzzleHttp\Client; $client = new Client([ 'base_uri' => 'https://categorizeapi.com/api/', 'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'] ]); $response = $client->post('categorize', [ 'json' => [ 'input' => 'https://example.com', 'type' => 'auto' ] ]); $data = json_decode($response->getBody(), true); echo $data['category'];
Rate Limits
Monthly request limits are enforced per calendar month and reset on the 1st of each month. A separate burst limit of 60 requests/minute applies to every plan.
| Plan | Requests / month | API access |
|---|---|---|
| Free | 100 | Full API access |
| Professional — $5/mo | 5,000 | Full API access + priority processing |
| Business — $14/mo | Unlimited | Full API access + dedicated support + SLA 99.9% |
When you exceed your monthly limit, the API returns HTTP 429. The requests_remaining field in every successful response lets you track usage programmatically.
Changelog
- Initial public release
- REST API with JSON request/response
- URL and text input, auto-detected
- 25-category fixed taxonomy with confidence + reasoning
- Automatic fallback to a secondary model/provider
- API key authentication
- Free tier — 100 requests/month
Have a feature request or found a bug? Contact us — we read every message.