Planck API reference
A small REST API over the same objects the dashboard uses: links, domains, spaces, pixels and statistics. JSON in, JSON out, one bearer token.
Base URL and authentication
Every endpoint lives under:
https://planck.to/api/v1
Authenticate with the API token from your account settings, as a bearer token:
curl https://planck.to/api/v1/links \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Tokens are 64 characters and can be regenerated at any time, which immediately invalidates the previous one.
Endpoints
An unknown path under /api/v1 returns a JSON 404 rather than an HTML error page.
| Method | Path | Does |
|---|---|---|
GET | /links | List your links, paginated. |
POST | /links | Create a link, optionally with a QR code. |
GET | /links/{id} | Fetch one link. |
PUT | /links/{id} | Update a link. |
DELETE | /links/{id} | Delete a link. |
| all five | /domains | Manage custom domains. |
| all five | /spaces | Manage spaces, which group links by project or client. |
| all five | /pixels | Manage retargeting pixels. |
GET | /stats/{id} | Click statistics for one link. |
GET | /account | Your account and current plan. |
Creating a link
curl -X POST https://planck.to/api/v1/links \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/a-long-destination",
"domain_id": 1,
"alias": "spring-sale",
"create_qr": true
}'
Accepted fields
| Field | Type | Notes |
|---|---|---|
url | string, required | Destination. Up to 2048 characters. Checked against the URL safety rules. |
domain_id | integer, required | A domain you own, or a global one available to your plan. |
alias | string | Letters, numbers, dashes and underscores. Up to 255 characters. Generated when omitted. |
password | string | Up to 128 characters. More |
space_id | integer | Must be a space you own. |
pixel_ids | array | Retargeting pixels to fire on redirect. |
create_qr | boolean | Also generate a QR code for the link. |
disabled | boolean | Create the link without it redirecting yet. |
privacy | integer 0-2 | Who can see the statistics page. Use privacy_password with the restricted options. |
expiration_date | YYYY-MM-DD | Requires expiration_time. |
expiration_time | HH:MM | Requires expiration_date. |
expiration_clicks | integer | Stop redirecting after this many clicks. |
expiration_url | string | Where to send visitors after expiry. More |
target_type | integer 0-4 | Enables targeting by country, platform or language, and rotation. |
Response
{
"id": 1042,
"alias": "spring-sale",
"url": "https://example.com/a-long-destination",
"short_url": "https://planck.to/spring-sale",
"title": "Spring sale",
"target_type": 0,
"disabled": 0,
"privacy": 0,
"password": false,
"expiration_url": null,
"expiration_clicks": null,
"clicks": 0,
"space": null,
"domain": { "id": 1, "name": "planck.to" },
"pixels": [],
"ends_at": null,
"created_at": "2026-09-20T10:24:11.000000Z",
"updated_at": "2026-09-20T10:24:11.000000Z"
}
password and privacy_password come back as booleans, never as values.
Listing and filtering
GET /api/v1/links?search=sale&search_by=title&sort_by=clicks&sort=desc&per_page=50
search | Free text. |
|---|---|
search_by | title, alias, url |
space_id domain_id pixel_id | Filter by related object. |
sort_by | id, clicks, title, alias, url |
sort | asc, desc |
per_page | One of 10, 25, 50 or 100. Anything else falls back to the default. |
Rate limits
Two limits apply: a short-term throttle of 120 requests per minute, and a monthly allowance that comes from your plan.
| Plan | Requests per month |
|---|---|
| Free | No programmatic access |
| Starter | 2,000 |
| Professional | 10,000 |
| Agency | 100,000 |
API access is enabled on: Agency.
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid token. |
403 | Your plan does not include programmatic access, or the monthly allowance is used up. |
404 | Unknown resource, or one that belongs to another account. |
422 | Validation failed. The body names the fields. |
429 | Too many requests in the last minute. |
Errors are JSON and carry a message and a status:
{
"message": "You don't have access to this feature.",
"status": 403
}
Ready to grow your business?
No card required. Upgrade only when you outgrow it.
Get Started for Free Compare plans