---
title: 'API and MCP server for developers · skrat.im'
description: 'The skrat.im REST API with an OpenAPI description, a plain-text endpoint for curl, an MCP server for AI agents and a bookmarklet. Rate-limited without a key, unlimited with one.'
url: https://skrat.im/en/developers/
lang: en
---

# API and MCP server

Everything the form does, the API does too. Rate-limited per IP without a key; with an account key the limit is higher and links are saved to the account.

## Quick start

One POST with a JSON body. The response is the link object; for anonymous links it also contains edit_token, which you should keep if you want to edit or delete the link later.

```sh
curl -X POST https://skrat.im/api/v1/links \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer skrat_…" \
  -d '{"url": "https://example.com/dlha/adresa", "alias": "moja-akcia", "domain": "krat.im"}'
```

```json
{
  "id": "5d1c…",
  "domain": "krat.im",
  "slug": "moja-akcia",
  "short_url": "https://krat.im/moja-akcia",
  "url": "https://example.com/dlha/adresa",
  "status": "active",
  "clicks": 0,
  "preview_url": "https://krat.im/moja-akcia+",
  "qr_png_url": "https://krat.im/moja-akcia.png",
  "stats_url": "https://skrat.im/api/v1/links/5d1c…/stats"
}
```

```sh
curl -X PATCH https://skrat.im/api/v1/links/5d1c… \
  -H "Content-Type: application/json" -H "X-Edit-Token: …" \
  -d '{"url": "https://example.com/nova/adresa"}'
```

## Authentication and limits

Without a key: 60 links per hour and 300 per day per IP address. With an API key (Authorization: Bearer skrat_… header): 1000 per hour and links belong to the account. Create a key in the account settings. Over the limit you get 429 with a Retry-After header.

## Endpoints

| Method | Path | Description |
|---|---|---|
| `POST` | `/api/v1/links` | Create a link. Body: url, alias?, domain?, title?, expires_in_days?, expires_at?, max_clicks?, password?, public_stats?, utm_* |
| `GET` | `/api/v1/links` | Links of the account (key required). |
| `GET` | `/api/v1/links/{id}` | Link detail (owner key or X-Edit-Token). |
| `PATCH` | `/api/v1/links/{id}` | Edit: url, title, expires_at \| expires_in_days, max_clicks, password ("" removes), public_stats. |
| `DELETE` | `/api/v1/links/{id}` | Delete the link. |
| `GET` | `/api/v1/links/{id}/stats` | Statistics (public unless the owner hides them). |
| `GET` | `/api/v1/check?slug=&domain=` | Alias availability, including the other domain. |
| `POST` | `/api/v1/bulk` | Bulk: urls (array or one per line), max. 20 without a key, 200 with one. |
| `GET` | `/api/shorten?url=` | Plain-text endpoint: returns only the short link. |
| `GET` | `/{alias}+` | Link preview (HTML). |
| `GET` | `/{alias}.json` | Public link info (JSON). |
| `GET` | `/{alias}.png | .svg` | QR code (size, fg, bg, margin). |

## Errors

Errors always look like { "error": { "code", "message" } }. The message follows ?lang= or Accept-Language. Codes: invalid_url, unsupported_scheme, private_host, self_reference, unsafe_url, slug_invalid, slug_reserved, slug_taken, domain_invalid, rate_limited, not_found, unauthorized, forbidden, too_many.

## MCP server for AI agents

The /mcp endpoint speaks the Model Context Protocol over Streamable HTTP (JSON-RPC 2.0, stateless). Tools: shorten_url, check_alias, get_link_info, qr_code. Without a key the per-IP limit applies; with a key in the Authorization header links are saved to the account.

Claude Code:

```sh
claude mcp add --transport http skrat https://skrat.im/mcp
```

Configuration (Claude Desktop, Cursor and similar):

```json
{
  "mcpServers": {
    "skrat": {
      "type": "http",
      "url": "https://skrat.im/mcp",
      "headers": { "Authorization": "Bearer skrat_…" }
    }
  }
}
```

## More

- OpenAPI 3.1 description (openapi.json): https://skrat.im/openapi.json
- llms.txt for AI clients: https://skrat.im/llms.txt
- MCP: https://skrat.im/mcp

The terms of use for the API are the same as for the website.
