API docs
Create, update and delete short links and read their click stats from your own code. Every request goes to:
https://api.links.arusa.co.in/v1The API is available on paid plans. Each plan allows a number of requests per minute, shared by all keys in the workspace:
| Plan | API access | Requests / min |
|---|---|---|
| Free | No | — |
| Pro | Yes | 60 |
| Business | Yes | 600 |
Quickstart
- Create a key in Settings → API keys. Copy it now: it is shown only once.
- Store it in an environment variable called
API_KEY. Every example on this page reads it from there. - Check the key works:
curl -X GET 'https://api.links.arusa.co.in/v1/me' \
-H "Authorization: Bearer $API_KEY"Then create your first short link:
curl -X POST 'https://api.links.arusa.co.in/v1/links' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/blog/launch?utm_source=newsletter",
"alias": "launch",
"title": "Launch post",
"tags": [
"newsletter"
]
}'Authentication
Send your key in the Authorization header on every request:
Authorization: Bearer sk_live_… A key belongs to one workspace and acts as the member who created it. It can read and change every link in that workspace, so keep it on your server and never ship it to a browser or app. If a key leaks, revoke it in Settings → API keys and create a new one. A missing, wrong or revoked key gets a 401.
Rate limits
Limits are per workspace, per minute (see the table above). Every request with a valid key gets these headers back:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59 Over the limit you get 429 with type rate_limited and a Retry-After header in seconds. Wait that long, then retry.
Errors
Errors use the application/problem+json format. Branch on type, not on the human-readable title or detail.
{
"type": "validation_failed",
"title": "Unprocessable Content",
"status": 422,
"detail": "The url field must be a valid URL.",
"errors": { "url": ["The url field must be a valid URL."] }
}| Status | Type | Meaning |
|---|---|---|
| 401 | unauthenticated | The key is missing, wrong or revoked. |
| 402 | limit_exceeded | Your plan’s monthly link limit is used up. Upgrade or wait for the next period. |
| 403 | plan_feature_required | The request uses a feature your plan doesn’t include (the API itself, custom aliases, expiry). |
| 403 | workspace_suspended | The workspace is suspended. Contact support. |
| 404 | not_found | No such link in this workspace. |
| 409 | idempotency_in_progress | A request with this Idempotency-Key is still running. Retry shortly. |
| 409 | qr_unavailable | This link was flagged or disabled for abuse, so it has no QR code. |
| 422 | validation_failed | The input is invalid; see errors for each field. |
| 422 | idempotency_key_reused | This Idempotency-Key was already used with a different body. |
| 429 | rate_limited | Too many requests this minute. Wait for Retry-After seconds. |
| 405 | http_error | Any other HTTP error, such as a wrong method. Check status. |
| 500 | server_error | Something broke on our side. Safe to retry with the same Idempotency-Key. |
Pagination
GET /links returns one page, newest first, plus a next_cursor. Pass it back as ?cursor= to get the next page. When next_cursor is null, you have them all.
curl -X GET 'https://api.links.arusa.co.in/v1/links?cursor=eyJpZCI6MTIzNCwiX3BvaW50c1RvTmV4dEl0ZW1zIjp0cnVlfQ' \
-H "Authorization: Bearer $API_KEY"Idempotency
Networks fail. To retry POST /links safely, send an Idempotency-Key header (any unique string up to 255 characters, such as a UUID). If the same key comes back with the same body within 24 hours, you get the first response again, marked Idempotent-Replayed: true, and no second link is created. The same key with a different body gets 422 idempotency_key_reused.
curl -X POST 'https://api.links.arusa.co.in/v1/links' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 3f1c2a9e-7b6d-4c1e-9a8f-2d5e6b7c8d9e' \
-d '{
"url": "https://example.com/blog/launch?utm_source=newsletter",
"alias": "launch",
"title": "Launch post",
"tags": [
"newsletter"
]
}'Endpoints
GET/me
The key's workspace, plan and current usage
curl -X GET 'https://api.links.arusa.co.in/v1/me' \
-H "Authorization: Bearer $API_KEY"200 OK
{
"data": {
"workspace": {
"id": 42,
"name": "Acme"
},
"plan": "Pro",
"links": {
"used": 120,
"limit": 2000
},
"clicks": {
"tracked": 5310,
"untracked": 0,
"limit": 100000
},
"seats": {
"used": 3,
"limit": 5
}
}
}GET/links
List links, newest first
Parameters
qquery · string- Matches title, code or target URL
tagquery · stringcreated_afterquery · string (date)cursorquery · string- The previous page's next_cursor
curl -X GET 'https://api.links.arusa.co.in/v1/links' \
-H "Authorization: Bearer $API_KEY"200 OK
{
"data": [
{
"id": 1234,
"code": "launch",
"short_url": "https://go.example.com/launch",
"target_url": "https://example.com/blog/launch?utm_source=newsletter",
"title": "Launch post",
"is_custom": true,
"expires_at": null,
"tags": [
"newsletter"
],
"clicks_count": 87,
"created_at": "2026-11-03T10:15:00+00:00"
}
],
"next_cursor": "eyJpZCI6MTIzNCwiX3BvaW50c1RvTmV4dEl0ZW1zIjp0cnVlfQ"
}POST/links
Create a link
Parameters
Idempotency-Keyheader · string- Repeating a key with the same body within 24 hours replays the first response (with an Idempotent-Replayed: true header) instead of creating another link.
Body (JSON)
urlstring (uri)Requiredaliasstring | null- Paid plans only
titlestring | nulltagsstring[] | nullexpires_atstring | null (date-time)- Paid plans only
curl -X POST 'https://api.links.arusa.co.in/v1/links' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com/blog/launch?utm_source=newsletter",
"alias": "launch",
"title": "Launch post",
"tags": [
"newsletter"
]
}'201 Created
{
"data": {
"id": 1234,
"code": "launch",
"short_url": "https://go.example.com/launch",
"target_url": "https://example.com/blog/launch?utm_source=newsletter",
"title": "Launch post",
"is_custom": true,
"expires_at": null,
"tags": [
"newsletter"
],
"clicks_count": 87,
"created_at": "2026-11-03T10:15:00+00:00"
}
}GET/links/{id}
Show a link
curl -X GET 'https://api.links.arusa.co.in/v1/links/1234' \
-H "Authorization: Bearer $API_KEY"200 OK
{
"data": {
"id": 1234,
"code": "launch",
"short_url": "https://go.example.com/launch",
"target_url": "https://example.com/blog/launch?utm_source=newsletter",
"title": "Launch post",
"is_custom": true,
"expires_at": null,
"tags": [
"newsletter"
],
"clicks_count": 87,
"created_at": "2026-11-03T10:15:00+00:00"
}
}DELETE/links/{id}
Delete a link. Its code is never reused.
PATCH/links/{id}
Update a link
Parameters
idpath · integerRequired
Body (JSON)
urlstring (uri)titlestring | nulltagsstring[] | nullexpires_atstring | null (date-time)
curl -X PATCH 'https://api.links.arusa.co.in/v1/links/1234' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"title": "Launch post (updated)",
"tags": [
"newsletter",
"q4"
]
}'200 OK
{
"data": {
"id": 1234,
"code": "launch",
"short_url": "https://go.example.com/launch",
"target_url": "https://example.com/blog/launch?utm_source=newsletter",
"title": "Launch post (updated)",
"is_custom": true,
"expires_at": null,
"tags": [
"newsletter",
"q4"
],
"clicks_count": 87,
"created_at": "2026-11-03T10:15:00+00:00"
}
}GET/links/{id}/stats
Daily click stats for a link
Parameters
idpath · integerRequiredfromquery · string (date)toquery · string (date)intervalquery · string (day)
curl -X GET 'https://api.links.arusa.co.in/v1/links/1234/stats' \
-H "Authorization: Bearer $API_KEY"200 OK
{
"data": {
"from": "2026-10-28",
"to": "2026-11-03",
"interval": "day",
"totals": {
"clicks": 87,
"unique_visitors": 64
},
"series": [
{
"date": "2026-11-02",
"clicks": 31,
"unique_visitors": 25
},
{
"date": "2026-11-03",
"clicks": 56,
"unique_visitors": 39
}
],
"referrers": {
"t.co": 40,
"google.com": 22,
"other": 25
},
"countries": {
"IN": 51,
"US": 20,
"other": 16
},
"devices": {
"mobile": 60,
"desktop": 27
},
"browsers": {
"Chrome": 58,
"Safari": 21,
"other": 8
},
"last_24h": [
{
"hour": "2026-11-03T09:00:00+00:00",
"clicks": 12
}
]
}
}GET/links/{id}/qr
QR code for a link's short URL
Parameters
idpath · integerRequiredformatquery · string (svg, png)
curl -X GET 'https://api.links.arusa.co.in/v1/links/1234/qr' \
-H "Authorization: Bearer $API_KEY"200 The QR code image
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1024\" height=\"1024\" viewBox=\"0 0 1024 1024\">…</svg>"