Filoo API
Programmable links for AI agents.
Create, observe, and modify short links via REST. Authenticate with a Bearer token. Ship faster than building it yourself.
60-second quick start
# 1. Sign up at filoo.app, claim a username, subscribe to Pro or Agents
export FILOO_KEY="flo_live_..."
# 2. Create your first link
curl -X POST https://filoo.app/api/v1/links \
-H "Authorization: Bearer $FILOO_KEY" \
-H "Content-Type: application/json" \
-d '{
"destination": "https://example.com/long-url",
"slug": "campaign-2025"
}'
# Response:
# {
# "code": "yourname:campaign-2025",
# "short_url": "https://filoo.app/yourname/campaign-2025",
# "destination": "https://example.com/long-url",
# "created_at": 1736789012,
# "active": true
# }
# 3. Read the stats anytime
curl https://filoo.app/api/v1/links/yourname:campaign-2025/stats \
-H "Authorization: Bearer $FILOO_KEY"That's it. Your link is live. Every scan is tracked.
Authentication
All API requests require a Bearer token in the Authorization header. Tokens are prefixed `flo_live_` and shown only once at creation time.
Generate keys at filoo.app/dashboard/api-keys.
Authorization: Bearer flo_live_xxxxxxxxxxxxxxxxEach Pro account can issue up to 5 keys. Agents up to 50. Revoke any key at any time. The previous one stops working immediately.
Keys are HMAC-hashed in our database. We literally cannot recover yours if you lose it. Generate a new one and rotate.
Endpoints
/api/v1/meGet current user. Returns information about the authenticated user, including tier, limits, and usernames owned.
curl https://filoo.app/api/v1/me \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const me = await filoo.me();
console.log(me.tier, me.limits.active_links);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
me = filoo.me()
print(me['tier'], me['limits']['active_links'])Response schema
{
"id": "01HK...",
"email": "you@yours.com",
"primary_username": "agency",
"usernames": ["agency", "client1"],
"tier": "pro",
"boost_credits": 500,
"limits": {
"active_links": 5500,
"links_per_day": 200,
"api_rate_per_min": 100,
"usernames": 5
},
"is_admin": false
}/api/v1/usageGet current usage vs quotas. Returns today's links_created and api_calls along with current active_links count and the cap.
curl https://filoo.app/api/v1/usage \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const u = await filoo.usage();
console.log(`${u.active_links}/${u.active_links_limit} active links`);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
u = filoo.usage()
print(f"{u['active_links']}/{u['active_links_limit']} active links")Response schema
{
"date": "2026-05-10",
"links_created_today": 14,
"links_created_limit": 200,
"api_calls_today": 387,
"active_links": 412,
"active_links_limit": 5500,
"boost_credits": 500
}/api/v1/usernamesList your usernames. Returns the array of usernames the authenticated user owns.
curl https://filoo.app/api/v1/usernames \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const { usernames } = await filoo.usernames();
for (const u of usernames) console.log(u.username, u.is_primary);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
result = filoo.usernames()
for u in result['usernames']:
print(u['username'], u['is_primary'])Response schema
{ "usernames": [ {"username": "agency", "is_primary": 1, "created_at": 1736789012} ] }/api/v1/linksscope: links:writeCreate a link. Create a permanent short link under one of your usernames. Counts against your daily creation quota and active link cap.
curl -X POST https://filoo.app/api/v1/links \
-H "Authorization: Bearer $FILOO_KEY" \
-H "Content-Type: application/json" \
-d '{"destination":"https://example.com","slug":"q4-launch"}'import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const link = await filoo.links.create({
destination: 'https://example.com',
slug: 'q4-launch',
});
console.log(link.short_url);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
link = filoo.links.create(
destination='https://example.com',
slug='q4-launch',
)
print(link['short_url'])Request body schema
{
"destination": "https://example.com/long-url",
"username": "agency",
"slug": "campaign-1",
"label": "Spring 2026"
}Response schema
{
"code": "agency:campaign-1",
"short_url": "https://filoo.app/agency/campaign-1",
"destination": "https://example.com/long-url",
"slug": "campaign-1",
"username": "agency",
"created_at": 1736789012
}/api/v1/linksscope: links:readList your links. Cursor-paginated list of your links, newest first. `limit` max 100.
curl "https://filoo.app/api/v1/links?limit=20" \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const { items, cursor } = await filoo.links.list({ limit: 20 });
for (const l of items) console.log(l.code, l.destination);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
result = filoo.links.list(limit=20)
for l in result['items']:
print(l['code'], l['destination'])Response schema
{ "items": [...], "cursor": "1736789012" }/api/v1/links/{code}scope: links:readGet a link. Returns full link details for the given `code` (URL-encode the colon as `%3A`).
curl https://filoo.app/api/v1/links/agency%3Acampaign-1 \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const link = await filoo.links.get('agency:campaign-1');
console.log(link.destination);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
link = filoo.links.get('agency:campaign-1')
print(link['destination'])Response schema
{ "code": "agency:campaign-1", "destination": "...", ... }/api/v1/links/{code}scope: links:writeUpdate a link. Update destination, label, show_on_profile, or active. Past destinations are kept in the link_destinations_history table.
curl -X PATCH https://filoo.app/api/v1/links/agency%3Acampaign-1 \
-H "Authorization: Bearer $FILOO_KEY" \
-H "Content-Type: application/json" \
-d '{"destination":"https://new-target.com"}'import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
await filoo.links.update('agency:campaign-1', {
destination: 'https://new-target.com',
});from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
filoo.links.update('agency:campaign-1', destination='https://new-target.com')Request body schema
{ "destination": "https://new-target.com", "label": "Updated" }Response schema
{ "ok": true }/api/v1/links/{code}scope: links:writeDelete a link. Permanent deletion. Scan history is preserved (no FK on scans.link_code).
curl -X DELETE https://filoo.app/api/v1/links/agency%3Acampaign-1 \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
await filoo.links.delete('agency:campaign-1');from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
filoo.links.delete('agency:campaign-1')Response schema
{ "ok": true }/api/v1/links/{code}/statsscope: stats:readGet link scan stats. Returns totals + top countries + top sources for the given link.
curl https://filoo.app/api/v1/links/agency%3Acampaign-1/stats \
-H "Authorization: Bearer $FILOO_KEY"import { Filoo } from '@filooapp/sdk';
const filoo = new Filoo({ apiKey: process.env.FILOO_KEY! });
const stats = await filoo.links.stats('agency:campaign-1');
console.log(stats.totals.total, stats.top_countries);from filoo import Filoo
filoo = Filoo(api_key=os.environ['FILOO_KEY'])
stats = filoo.links.stats('agency:campaign-1')
print(stats['totals']['total'], stats['top_countries'])Response schema
{
"totals": { "total": 1247, "uniques": 893, "bots": 41 },
"top_countries": [ {"name": "FR", "n": 612}, {"name": "BE", "n": 187} ],
"top_sources": [ {"source": "qr-vitrine", "n": 412}, {"source": "qr-menu", "n": 289} ]
}Outbound webhooks
Filoo sends a signed POST to your endpoint when events you subscribe to happen. Configure at filoo.app/dashboard/webhooks.
Subscribed event types:
link.createdlink.updatedlink.deletedlink.scannedlink.malicious_flagsubscription.activatedsubscription.canceledboost.purchasedaccount.username_claimedPayload example:
{
"id": "evt_01H8K...",
"type": "link.scanned",
"created_at": 1736789012,
"data": {
"link_code": "jr:q4-launch",
"country": "FR",
"device_type": "mobile",
"referrer_host": "twitter.com"
}
}Each request includes an `X-Filoo-Signature` header containing `sha256=<hex>`. The signature is HMAC-SHA256 of the raw request body, using the webhook secret you configured.
# Use the TypeScript or Python tab — language-specific signature verification.import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(body: string, signature: string, secret: string): boolean {
const expected = 'sha256=' + createHmac('sha256', secret).update(body).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}import hmac, hashlib
def verify(body: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)Replays: each event has a unique `id`. Your handler should be idempotent. We retry up to 5 times with exponential backoff if your endpoint returns non-2xx.
Rate limits
Per API key, sliding window: Pro: 100 requests / minute Agents: 1,000 requests / minute When exceeded, you get HTTP 429 with a `Retry-After` header in seconds.
HTTP/2 429
Retry-After: 18
Content-Type: application/json
{"error":"rate_limited","retry_after":18}Daily creation limits are separate (200/day Pro, 5,000/day Agents). Exceeding those returns 429 with `error: "daily_limit"`. Active link limits are checked at creation, returning 429 with `error: "active_limit"` when full. Buy a Boost Pack or upgrade.
AI agent integration
Filoo is built for AI agents. Give your agent a single API key and let it create, track, and modify short links programmatically — no dashboard required.
How it works
Your agent gets one or more short links it can reuse across sessions. Each link is observable: the agent can read click totals, top countries, and referrer data at any time via the stats endpoint. And each link is editable: the agent can rotate the destination URL without changing the short link — perfect for A/B testing, campaign updates, or correcting a mistake after the link is live.
Example workflow
- 1. Agent calls POST /api/v1/links with a destination URL and a descriptive slug → receives { code, short_url }
- 2. Agent embeds the short_url in an email, Slack message, or generated document
- 3. When someone clicks the link, Filoo logs the scan with country, device, referrer, and timestamp
- 4. Agent calls GET /api/v1/links/{code}/stats → receives totals, top_countries, top_sources
- 5. Based on stats, agent calls PATCH /api/v1/links/{code} with a new destination URL → destination rotates, link unchanged
- 6. Loop: the agent reads stats, decides, and adapts — all via the same API.
Prompts for AI coding tools
Use these prompts with Cursor, Claude Code, Copilot, or any AI coding tool to integrate Filoo instantly:
Shorten a URL
"Create a function that shortens URLs using the Filoo API. Use POST /api/v1/links with Bearer token auth. Return the short_url from the response."
Read click stats
"Write a function that fetches click analytics for a Filoo short link using GET /api/v1/links/{code}/stats. Print total clicks and top countries."
Rotate destination
"Create a function that updates the destination URL of an existing Filoo short link using PATCH /api/v1/links/{code}. Accept the new URL as a parameter."
A/B test workflow
"Write a script that creates a Filoo short link pointing to variant A, waits for N clicks, reads the stats, then rotates the destination to variant B. Use the official @filooapp/sdk."
Best practices for agent-managed links
- Use labels — set the label field on each link so your agent can identify links by purpose when listing them later.
- Rotate destinations for A/B testing — keep the short URL constant, change the destination via PATCH, and compare stats before vs. after.
- Monitor click analytics — have your agent poll stats periodically or subscribe to link.scanned webhooks for real-time feedback.
- Set descriptive slugs — use human-readable slugs like campaign-q2-v1 so debugging via the dashboard stays easy.
- Clean up inactive links — use DELETE /api/v1/links/{code} to retire links that have stopped receiving traffic, staying under your active link cap.
- Use the Agents tier — 50,000 active links, 5,000 creations/day, 1,000 API req/min. Designed specifically for autonomous workloads.
Most useful endpoints for agents
The existing Filoo API already covers everything an agent needs. The most relevant endpoints are:
- POST /api/v1/links — Create a new short link (agents can generate hundreds automatically)
- GET /api/v1/links/{code}/stats — Read scan totals, countries, and referrers
- PATCH /api/v1/links/{code} — Update the destination URL (rotate without breaking the short link)
- GET /api/v1/links — List all links with cursor pagination (find links by label or date)
- GET /api/v1/usage — Check daily creation quotas and active link counts before generating more
Error format
All error responses follow this shape:
{
"error": "machine_readable_code",
"message": "Human-readable explanation",
"details": {}
}Codes by HTTP status:
400 invalid_input | 401 not_authenticated | 403 forbidden
404 not_found | 409 conflict | 422 unprocessable
429 rate_limited | 500 server_error | 503 service_unavailable
Specific 422 codes: malicious_destination, blocked_destination,
slug_reserved, username_inactive.
Specific 429 codes: rate_limited, active_limit, daily_limit.Specification
The full schema is published as OpenAPI 3.0 at https://filoo.app/api/openapi.json Import into Postman, Insomnia, Swagger UI, or generate clients in any language with openapi-generator.
Changelog
Stable since v0.3.1 (2026-05-10). No breaking changes planned. Track at filoo.app/changelog.
Get an API key.
Pro plan starts at €9/month. Agents at €29/month. 14-day refund.