API Documentation
Everything below reflects the live public API — every endpoint on this page works today.
Base URL
https://getmicrourl.com/api/v1Authentication
Every request needs an API key in the Authorization header. Generate one from Dashboard → Settings.
Authorization: Bearer ck_live_...Response format
Every successful response is wrapped in a data envelope:
{ "data": ... }List endpoints add a pagination key:
{ "data": [...], "pagination": { "nextCursor": "lnk_..." } }Errors follow the same shape, always with a machine-readable code:
{ "error": { "code": "not_found", "message": "Link not found" } }| Error code | HTTP status |
|---|---|
invalid_request | 400 |
unauthenticated | 401 |
forbidden | 403 |
not_found | 404 |
slug_taken | 409 |
plan_limit_reached | 402 |
malicious_url | 400 |
rate_limited | 429 |
internal_error | 500 |
Rate limits
Limits are per API key, per minute, based on your plan. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. A 429 response also includes Retry-After.
| Plan | Limit |
|---|---|
| Free | 10 requests/min |
| Starter | 60 requests/min |
| Growth | 300 requests/min |
| Business | 600 requests/min |
Endpoints
/linksCreate a short link. If no slug is given, one is generated.
curl -X POST https://getmicrourl.com/api/v1/links \
-H "Authorization: Bearer ck_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/a-very-long-page",
"slug": "my-link",
"title": "My link",
"utm": { "source": "twitter", "medium": "social" }
}'Body: url (required), slug, title, expiresAt (ISO 8601), utm.{source,medium,campaign,term,content} — all optional. The destination URL is checked against Google Web Risk before the link is created; a known-malicious URL is rejected with malicious_url.
Returns 201 with the created link.
/linksList links for your organization, newest first.
curl "https://getmicrourl.com/api/v1/links?limit=20" \
-H "Authorization: Bearer ck_live_..."Query params: limit (max 100, default 20), cursor (from the previous response’s pagination.nextCursor).
/links/:idFetch a single link by ID.
curl https://getmicrourl.com/api/v1/links/lnk_abc123 \
-H "Authorization: Bearer ck_live_..."/links/:idUpdate a link. The slug cannot be changed — editing a slug would break every existing short URL pointing at it. Edit the destination URL instead.
curl -X PATCH https://getmicrourl.com/api/v1/links/lnk_abc123 \
-H "Authorization: Bearer ck_live_..." \
-H "Content-Type: application/json" \
-d '{ "destinationUrl": "https://example.com/new-target", "isActive": true }'Updatable fields: destinationUrl, title, isActive, expiresAt, fallbackUrl.
/links/:idDelete a link. Returns 204 with no body.
curl -X DELETE https://getmicrourl.com/api/v1/links/lnk_abc123 \
-H "Authorization: Bearer ck_live_..."/links/bulkCreate up to 100 links in one request. Each row succeeds or fails independently.
curl -X POST https://getmicrourl.com/api/v1/links/bulk \
-H "Authorization: Bearer ck_live_..." \
-H "Content-Type: application/json" \
-d '{
"links": [
{ "url": "https://example.com/one" },
{ "url": "https://example.com/two", "slug": "two" }
]
}'Response: an array with one result per input row.
{
"data": [
{ "index": 0, "status": "success", "link": { ... } },
{ "index": 1, "status": "error", "error": { "code": "slug_taken", "message": "..." } }
]
}Questions
Email [email protected] — this API is actively growing, and feedback shapes what we build next.