API Reference

Programmatically create and manage short links. All endpoints return JSON and accept JSON request bodies.

Base URL: https://app.0.mk

Authentication

All API requests require a Bearer token. Create API keys from Settings in your dashboard.

Example request
curl -X POST https://app.0.mk/api/links \
  -H "Authorization: Bearer 0mk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

API keys start with 0mk_ and are scoped to a workspace. All links created via API belong to the workspace associated with the key.

Analytics

GET
/api/analytics

Workspace-wide analytics

GET
/api/links/:id/analytics

Per-link analytics

daysnumber

Lookback period in days (default 30, max 365)

Get workspace analytics
curl "https://app.0.mk/api/analytics?days=7" \
  -H "Authorization: Bearer 0mk_abc123"
Response (200)
{
  "totalClicks": 1423,
  "daily": [
    { "day": "2026-04-20", "clicks": 203 },
    { "day": "2026-04-21", "clicks": 187 }
  ],
  "countries": [
    { "country": "US", "clicks": 612 },
    { "country": "MK", "clicks": 298 }
  ],
  "referrers": [
    { "referrer": "twitter.com", "clicks": 421 },
    { "referrer": null, "clicks": 389 }
  ],
  "topLinks": [
    { "linkId": "cm...", "slug": "launch", "clicks": 312 }
  ]
}

Tags

GET
/api/tags

List all tags

POST
/api/tags

Create a tag

DELETE
/api/tags/:id

Delete a tag

Create a tag
curl -X POST https://app.0.mk/api/tags \
  -H "Authorization: Bearer 0mk_abc123" \
  -H "Content-Type: application/json" \
  -d '{"name": "marketing", "color": "#3b82f6"}'

Domains

GET
/api/domains

List custom domains

POST
/api/domains

Add a custom domain

PATCH
/api/domains/:id

Verify domain DNS

DELETE
/api/domains/:id

Remove a domain

Add a domain
curl -X POST https://app.0.mk/api/domains \
  -H "Authorization: Bearer 0mk_abc123" \
  -H "Content-Type: application/json" \
  -d '{"hostname": "go.acme.com"}'
Response (201)
{
  "id": "cm...",
  "hostname": "go.acme.com",
  "status": "pending",
  "dnsRecord": {
    "type": "CNAME",
    "name": "go.acme.com",
    "value": "cname.0.mk"
  },
  "createdAt": "2026-04-26T12:00:00.000Z"
}

Team

GET
/api/team

List workspace members

POST
/api/team

Invite a member

PATCH
/api/team/:id

Change member role

DELETE
/api/team/:id

Remove a member

Roles: owner, admin, member, viewer

Errors

All errors return a JSON object with an error field.

StatusMeaning
400Invalid request body or parameters
401Missing or invalid API key
403Blocked URL or insufficient permissions
404Resource not found
409Conflict (e.g. alias already taken, domain already registered)
422DNS verification failed
429Rate limit exceeded
500Server error
Error response
{
  "error": "This alias is already taken"
}

Code Examples

JavaScript / Node.js
const response = await fetch("https://app.0.mk/api/links", {
  method: "POST",
  headers: {
    "Authorization": "Bearer 0mk_your_api_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com/my-page",
    alias: "my-link",
  }),
});

const link = await response.json();
console.log(link.shortUrl); // https://0.mk/my-link
Python
import requests

response = requests.post(
    "https://app.0.mk/api/links",
    headers={"Authorization": "Bearer 0mk_your_api_key"},
    json={"url": "https://example.com/my-page", "alias": "my-link"},
)

link = response.json()
print(link["shortUrl"])  # https://0.mk/my-link
cURL - Bulk create
# Create multiple links from a file (one URL per line)
while IFS= read -r url; do
  curl -s -X POST https://app.0.mk/api/links \
    -H "Authorization: Bearer 0mk_your_api_key" \
    -H "Content-Type: application/json" \
    -d "{\"url\": \"$url\"}" | jq .shortUrl
done < urls.txt

Rate Limits

API requests are rate limited per IP address:

EndpointLimitWindow
POST /api/links30 requestsper minute
POST /api/auth/send5 requestsper minute
POST /api/reports10 requestsper minute

When rate limited, the API returns 429 Too Many Requests.