API Reference
The Bittlebits REST API lets you programmatically score pages, retrieve rewrite suggestions, and poll for results. All endpoints are available at https://bittlebits.ai/api/v1/.
Authentication
All requests require an API key. Pass it as one of the following headers:
Authorization: YOUR_API_KEY
X-API-Key: YOUR_API_KEY
Generate or rotate your key from Settings → API Key in the Bittlebits dashboard. Requests without a valid key return 401 Unauthorized.
Score
Score a page against Bittlebits' GEO metrics. Each metric is rated 0–10.
POST /v1/score
Submit a URL for scoring. Parameters are passed as query strings.
Rate limit: 100 requests/hour per IP.
POST /v1/score?url=https://example.com/page
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | one of url / url_id | The page URL to score |
url_id | number | one of url / url_id | A previously submitted URL by its Bittlebits ID |
link_user | boolean | no | Associate this URL with your account (default: true) |
Example Code
const res = await fetch('https://bittlebits.ai/api/v1/score?url=https://example.com/page', {
method: 'POST',
headers: { 'X-API-Key': YOUR_API_KEY },
});
const data = await res.json();
// { status: 'submitted', url_id: 42, created: true }
import requests
res = requests.post(
'https://bittlebits.ai/api/v1/score',
params={'url': 'https://example.com/page'},
headers={'X-API-Key': YOUR_API_KEY},
)
data = res.json()
# { 'status': 'submitted', 'url_id': 42, 'created': True }
Response 200 OK
{
"status": "submitted",
"url_id": 42,
"created": true
}
created: true means the URL is new and must be scraped before scoring. created: false means the URL was already known and scoring has been queued directly. In either case, poll GET /v1/score for the result.
GET /v1/score
Retrieve the latest score for a URL. Parameters are passed as query strings.
Rate limit: 5 requests/second per IP.
GET /v1/score?url_id=42
X-API-Key: YOUR_API_KEY
| Parameter | Type | Required | Description |
|---|---|---|---|
url_id | number | one of url_id / url | The Bittlebits URL ID |
url | string | one of url_id / url | The page URL |
Response — ready 200 OK
{
"url_id": 42,
"metrics": {
"citation_readiness": 8.2,
"content_depth": 6.5,
"entity_clarity": 7.1
}
}
Response — pending 202 Accepted
{
"status": "pending",
"task_id": "abc123",
"url_id": 42
}
Poll at a 2-second interval until you receive 200 OK. See Polling.
Rewrite
Retrieve GEO rewrite suggestions for a page.
POST /v1/rewrite
Queue a rewrite for a URL. Same parameters and response shape as POST /v1/score.
POST /v1/rewrite?url_id=42
X-API-Key: YOUR_API_KEY
Example:
const res = await fetch('https://bittlebits.ai/api/v1/rewrite?url=https://example.com/page', {
method: 'POST',
headers: { 'X-API-Key': YOUR_API_KEY },
});
const data = await res.json();
// { status: 'submitted', url_id: 42, created: true }
GET /v1/rewrite
Retrieve rewrite suggestions for a URL. Parameters are passed as query strings.
Rate limit: 5 requests/second per IP.
GET /v1/rewrite?url_id=42
X-API-Key: YOUR_API_KEY
| Parameter | Type | Required | Description |
|---|---|---|---|
url_id | number | one of url_id / url | The Bittlebits URL ID |
url | string | one of url_id / url | The page URL |
Response — ready 200 OK
{
"url_id": 42,
"parsed_html": "# Original page content...",
"suggestions": [
{
"stable_id": "hero-h1",
"current_text": "Welcome to our site",
"suggested_text": "The leading platform for X",
"rationale": "More specific entity signal for AI citation",
"is_addition": false
}
]
}
Response — pending 202 Accepted
{
"status": "pending",
"task_id": "abc123",
"url_id": 42
}
Polling
Scoring and rewriting are async. A 202 Accepted response means the task is queued or running — poll the GET endpoint until you receive 200 OK.
Recommended interval: 2 seconds. Most operations complete within 30–60 seconds.
async function pollUntilReady(urlId) {
for (let i = 0; i < 30; i++) {
const res = await fetch(`https://bittlebits.ai/api/v1/score?url_id=${urlId}`, {
headers: { 'X-API-Key': YOUR_API_KEY },
});
const data = await res.json();
if (res.status === 200) return data;
if (res.status !== 202) throw new Error(data.error);
await new Promise(r => setTimeout(r, 2000));
}
throw new Error('Timed out waiting for score');
}
import time
import requests
def poll_until_ready(url_id):
for _ in range(30):
res = requests.get(
'https://bittlebits.ai/api/v1/score',
params={'url_id': url_id},
headers={'X-API-Key': YOUR_API_KEY},
)
if res.status_code == 200:
return res.json()
if res.status_code != 202:
raise RuntimeError(res.json().get('error', res.text))
time.sleep(2)
raise TimeoutError('Timed out waiting for score')
Do not retry with a new POST while a task is already pending for the same URL.
Errors
All error responses follow the same shape:
{
"error": "Human-readable description of the error"
}
| Status | Meaning |
|---|---|
200 Success | The request was successful and the data was returned |
202 Accepted / Poll | The request was accepted and the response is processing. Poll the api endpoint until 200 |
400 Bad Request | Missing or invalid parameters (e.g. neither url nor url_id provided) |
401 Unauthorized | Missing or invalid API key |
404 Not Found | The requested url_id does not exist, or no task has been submitted for it yet |
410 Gone | The task was revoked — resubmit with POST |
429 Too Many Requests | Rate limit exceeded — back off and retry |
500 Internal Server Error | Something went wrong on our end |
504 Gateway Timeout | The task timed out — resubmit with POST |