API and MCP server
Create tokens in your space, under Developers. Each token has limited scopes, can be edited (name and scopes) and revoked at any time.
Authentication
Authorization: Bearer rl_live_…
JSON responses. Errors: { "error": { "code", "message" } }. Rate limit by plan (Solo 20, Pro 60, Agence 120 requests per minute) and at most 1 request per second, shown in the X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Burst headers. Beyond: 429 with Retry-After. Service under heavy load: 503 with Retry-After. To create many links, use /v1/links/batch.
Updating: POST or PATCH
The three update endpoints accept POST as well as PATCH, on the same path and with the same body. Prefer POST: some infrastructure (firewalls, hosting front ends, corporate proxies) drops PATCH requests before they reach the service, and the connection is then reset with no HTTP response. The X-HTTP-Method-Override: PATCH header and the _method field are accepted too; they are not required.
curl -X POST https://api.reli.es/v1/links/42 \
-H "Authorization: Bearer rl_live_…" \
-H "Content-Type: application/json" \
-d '{"url": "https://exemple.fr/nouvelle-page"}'
Create a link
curl https://api.reli.es/v1/links \
-H "Authorization: Bearer rl_live_…" \
-H "Content-Type: application/json" \
-d '{
"url": "https://exemple.fr/offre",
"slug": "offre-hiver",
"tags": ["sms"],
"utm": {"source": "sms", "campaign": "hiver"},
"expires_at": "2026-12-31T23:59:00+01:00"
}'
201 Created
{
"data": {
"id": 42,
"short_url": "https://reli.es/offre-hiver",
"domain": "reli.es",
"slug": "offre-hiver",
"destination": "https://exemple.fr/offre",
"title": null,
"status": "active",
"tags": ["sms"],
"utm": {"source": "sms", "campaign": "hiver"},
"protected": false,
"starts_at": null,
"ends_at": "2026-12-31T23:59:00+01:00",
"expired_url": null,
"clicks": 0,
"qr_svg": "https://api.reli.es/v1/links/42/qr.svg",
"created_at": "2026-09-29T10:12:04+02:00"
}
}
Field names
The response names the destination “destination” and the end date “ends_at”. On input both spellings are accepted: url or destination, expires_at or ends_at. Any other name is refused with a 422 that names it — a misspelled field is never silently ignored.
422 Unprocessable Content
{ "error": {
"code": "unknown_field",
"message": "Champ inconnu : lien. Champs acceptés : url, destination, …",
"unknown": ["lien"],
"accepted": ["url", "destination", "title", "tags", "utm", "starts_at", "expires_at", "ends_at", "expired_url", "password"]
} }
Listing links
Filters: tag, status (active, archived, blocked, review), domain, q, limit (100 max) and cursor. The next-page cursor sits at the root of the response; it is null on the last page. Links belonging to bio pages and campaigns are not in this list.
GET https://api.reli.es/v1/links?tag=sms&limit=50
{ "data": [ { "id": 42, … } ], "next_cursor": "42" }
Statistics
GET /v1/links/{id}/stats?days=30 (1 to 365 days). A click is recorded straight away and shows up at once. Repeat openings by the same visitor within 30 minutes count in repeats, never in clicks. A call coming from a server (no display language, HEAD, or prefetched by the browser) counts in bots: a command-line test therefore does not raise clicks.
{ "data": {
"days": 30, "clicks": 128, "uniques": 96, "qr": 12, "bots": 31, "repeats": 7,
"previous_period_clicks": 88,
"daily": [ {"date": "2026-09-01", "clicks": 4}, … ],
"countries": [ {"label": "FR", "n": 101}, … ],
"cities": [ … ], "devices": [ … ], "sources": [ … ],
"link": { "id": 42, "short_url": "https://reli.es/offre-hiver" }
} }
Link endings
Chosen link ending (slug): 2 to 64 characters, lowercase letters, digits and hyphens, no hyphen at the start or the end. Uppercase input is lowercased. An ending already taken, reserved or blocked returns a 422 whose message suggests a variant. An ending is never reassigned, even after archiving.
Without a slug, the service assigns a six-character lowercase ending with no ambiguous character (no 0 or o, no 1, l or i): readable under a printed QR code and easy to dictate over the phone.
Endpoints
| Method | Path | Permission | Role |
|---|---|---|---|
| POST | /v1/links | links:write | Create a link: url, domain, slug, title, tags, utm, starts_at, expires_at, expired_url, password |
| POST | /v1/links/batch | links:write | Create up to 100 links: { "links": [ … ] }; 207 response with one row per link |
| GET | /v1/links | links:read | List: tag, status, domain, q, cursor, limit (100 at most) |
| GET | /v1/links/{id} | links:read | Read a link |
| POST · PATCH | /v1/links/{id} | links:write | Edit destination, title, tags, dates, UTM |
| DELETE | /v1/links/{id} | links:write | Archive (the link ending is never reassigned) |
| GET | /v1/links/{id}/stats | stats:read | Statistics: days (1 to 365) |
| GET | /v1/links/{id}/qr.svg | links:read | QR code SVG or PNG |
| GET | /v1/domains | domains:read | Usable domains. This scope is only needed here: creating a link on reli.es does not require it. |
| GET · POST · PATCH | /v1/pages/{handle} | pages:read · pages:write | Read a bio page, edit title and bio |
| GET | /v1/account | — | Plan, limits and usage |
| GET | /v1/managed-accounts | accounts:managed | Managed accounts, targeted with the Relies-Account header |
Campaigns: one link per contact
Reserved for agency accounts and the accounts they manage. A campaign carries a destination, a domain, tracking parameters and an end date; each contact then gets its own link ending, created in batches of 100 in a single request. The contact reference (ref) is your own identifier: 1 to 64 characters, letters, digits, dot, colon, hyphen and underscore. It is stored as is: never put a name, a phone number or an e-mail address in it.
| Method | Path | Role |
|---|---|---|
| GET · POST | /v1/campaigns | List, create: name, url, domain, utm, expires_at, expired_url, kore_ref |
| GET · POST · PATCH | /v1/campaigns/{id} | Read, update: name, url, expires_at, expired_url, kore_ref |
| POST | /v1/campaigns/{id}/contacts | Add 1 to 100 contacts in a single request: { "contacts": [ {"ref": "c-1024"}, {"ref": "c-1025", "url": "https://exemple.fr/page-b"} ] } |
| GET | /v1/campaigns/{id}/contacts | List the contacts: clicked, clicked_since, limit (500 max) |
| DELETE | /v1/campaigns/{id}/contacts/{ref} | Forget a contact: its reference is erased, the link is archived |
curl https://api.reli.es/v1/campaigns/7/contacts \
-H "Authorization: Bearer rl_live_…" \
-H "Content-Type: application/json" \
-d '{"contacts": [{"ref": "c-1024"}, {"ref": "c-1025", "url": "https://exemple.fr/page-b"}]}'
200 OK (207 if a row fails)
{ "data": [ { "index": 0, "ref": "c-1024", "ok": true, "created": true,
"link": { "id": 512, "short_url": "https://reli.es/k7m4qp", … } }, … ],
"created": 2, "existing": 0, "failed": 0 }
A reference the campaign already knows returns the existing link (existing): the same batch can be replayed without creating duplicates. Each contact's first click fires the campaign.contact_clicked webhook.
Token scopes
links:read · links:write · stats:read · pages:read · pages:write · domains:read · campaigns:read · campaigns:write · accounts:managed
A missing scope returns a 403 “forbidden” naming the expected scope. A token's scopes can be changed in your space, under Developers, without changing its value: tools already connected keep working.
Webhooks
Events: link.created, link.blocked, link.clicked (grouped by minute), page.form_submitted, campaign.contact_clicked (managed accounts). Each delivery carries the X-Relies-Signature header: t=timestamp,v1=signature, where the signature is the HMAC-SHA256 of “timestamp.body” with your secret. Reject deliveries older than 5 minutes. Three retries on failure: after 1 minute, 10 minutes, 1 hour.
$payload = file_get_contents('php://input');
[$t, $v1] = sscanf($_SERVER['HTTP_X_RELIES_SIGNATURE'], 't=%d,v1=%s');
$valid = abs(time() - $t) < 300
&& hash_equals(hash_hmac('sha256', $t.'.'.$payload, $secret), $v1);
MCP server
Address: https://api.reli.es/mcp · HTTP transport, same token as the API.
claude mcp add --transport http reli-es https://api.reli.es/mcp \ --header "Authorization: Bearer rl_live_…"
| Tool | Role |
|---|---|
liens_creer | Create one or more links |
liens_chercher | Search by destination, tag, status |
liens_stats | Statistics for a link or the account |
lien_modifier | Edit destination, title, tags, dates |
lien_archiver | Archive, with explicit confirmation |
page_lire · page_modifier | Read a bio page, add a link button |
qr_exporter | QR code SVG or PNG address |
compte_etat | Plan, limits and usage |