Skip to content
Language: English

API for developers

The LinkHarbor API at a glance

Updated 1 November 2026 5 min read

Base URL, sandbox, versioning, data format, pagination and authentication: what to know before your first LinkHarbor REST API call.

The REST API lets you control LinkHarbor from your own programs: create pages and links, edit and publish drafts, generate short links or pull statistics into your own reporting. This article is for developers and explains the ground rules that apply to every endpoint.

Which route fits?

You want to …RouteMore
Manage pages, links and content from a script or serverREST API with an API keyThis section
Get notified when something happens (e.g. a page is published)WebhooksWebhooks
Match sales from your shop to a link clickSale callbacksCallbacks
Show live data from your own tools on your page“Custom (API)” integrationCallbacks
Work in a chat with Claude or ChatGPTMCP serverAI assistants

Base URL and versioning

Base URL
https://dock.at-harbor.com – all product endpoints live under /v1, for example https://dock.at-harbor.com/v1/pages.
Version
There is currently only version v1. The version number is part of the path.
Protocol
HTTPS only.
OpenAPI
The machine-readable description (OpenAPI 3.1) is at https://dock.at-harbor.com/openapi.yaml. You can load it into Postman, Insomnia or a code generator.

Testing in the sandbox

For development and testing there is a separate sandbox. It behaves like the real API but is completely separate from it: its own accounts, its own data, and none of it ends up in your real workspace.

API
https://drydock.at-harbor.com, with the same paths as above, for example https://drydock.at-harbor.com/v1/pages.
Dashboard
https://sandbox-deck.linkharbor.com, for example to create API keys.
Pages
Published pages appear at https://<handle>.sandbox.linkharbor.com.
Account
Your real LinkHarbor account does not work there. Create a separate sandbox account.

The sandbox does not send e-mails. If you register via the API (POST /v1/auth/register), the verification code comes back directly in the response, in the _dev_verification field. The same applies to password resets and e-mail changes. This field only exists in the sandbox, so do not rely on it in your code.

  • Push notifications are switched off
  • Payments run through Stripe's test mode, no real money moves
  • Rate limits are about a third of the real values, and new accounts are limited to 5 per hour and IP address
  • On the 1st of every month at 3:00 UTC the sandbox is wiped completely, and all accounts and data are gone afterwards
  • Every response carries the header X-Environment: sandbox

Authentication in brief

  1. As an owner or admin, create an API key with the scopes you need in the dashboard under “Callback & API” (from Creator Pro)
  2. Exchange the key ID and key secret for an access token via POST /v1/token
  3. Send the token with every request in the header Authorization: Bearer …
  4. Get a new token after 15 minutes

All the details are in API keys and tokens, the permissions in Scopes.

Requests and responses

Format
Requests and responses are JSON in UTF-8. File uploads also use multipart/form-data.
Content-Type
Send the header Content-Type: application/json with every request that has a body. Any other type is rejected with 400 bad_request – including the one curl sets automatically for -d when this header is missing.
Unknown fields
Fields an endpoint does not know lead to 422 validation_failed. The response names the unknown fields.
Broken JSON
Leads to 400 invalid_json.
Size
Depending on the endpoint, a body may be at most 64 KB, 1 MB or 2 MB, and a file upload 10 MB. If it is larger, the API responds with 413 request_too_large. All limits are listed under Rate limits.
Lists
Come as an object with the field items, for example {"items":[…]}.
Creating
Responds with HTTP 201 and the new ID, for example {"id":123}.
Actions without a return value
Respond with {"ok":true}.
Errors
Always have a fixed format with a machine-readable code. See Error format and error codes.

Pagination

There is no single pagination scheme. Most lists are small and come back complete; only a few endpoints have parameters:

EndpointBehaviourParameters
GET /v1/pages, /v1/pages/{id}/links, /v1/pages/{id}/blocks, /v1/formsComplete list–
GET /v1/forms/{id}/submissionsNewest first, paged with a cursor: next_cursor from the response is the cursor for the next page, null on the last onelimit 1–500 (default 100), cursor
GET /v1/short-linksPaged, with total in the responselimit 1–100 (default 50), offset, sort, q
GET /v1/push/historyPagedlimit up to 100 (default 50), offset
Statistics endpointsBy periodperiod, from, to, granularity

For sort on short links there are created_desc, created_asc, redirects_desc and redirects_asc; q searches slug, title and target URL (up to 100 characters, not case-sensitive). For statistics, period accepts 24h, 7d, 30d, 90d, this_month, last_month, last_30d and custom; alternatively you pass from and to. granularity is hour or day.

Request ID and language

  • Every response carries the header X-Request-Id – include it when you contact support
  • If you send an X-Request-Id header yourself, the API uses it
  • The error text in message is in the account language of the workspace owner, otherwise it follows Accept-Language; the code in error always stays the same

Calling it from the browser?

Technically, the API allows calls from the browser (CORS). But a key secret never belongs in code that runs on the visitor's side – neither in a website nor in an app. Always call the API from your own server.

Plans

PlanAPI keysWebhooksCallback secrets
Creator Free–––
Creator Proup to 5up to 5up to 5
Creator Agencyup to 20up to 25up to 5
Enterpriseup to 50 (adjustable)up to 100 (adjustable)up to 5

There is no quota of API calls per plan. Only the per-minute rate limits apply. Your plan's content limits – such as pages, links or blocks per page – apply via the API just as they do in the dashboard. See Plans compared.

Your first call

Get a token and list pages
# Exchange the key for a token
curl -X POST https://dock.at-harbor.com/v1/token \
  -H "Content-Type: application/json" \
  -d '{"key_id":"6F668EA6598B0692","key_secret":"lt_…"}'
# → {"token":"eyJ…","expires_in":900}

export LH_TOKEN="eyJ…"

# List pages (scope read:pages)
curl https://dock.at-harbor.com/v1/pages \
  -H "Authorization: Bearer $LH_TOKEN"

A complete example that adds a link, changes the design and publishes is in Update a page via the API.

Nothing found?

Tell us what you need, and our support team will help you personally.

Contact support