Quick start
curl https://incy.my/api/v1/me \
-H "Authorization: Bearer stk_YOUR_KEY_HERE"
Authentication
Every request needs an Authorization: Bearer <key> header. Mint keys at /admin/api-keys — name them per integration (e.g. zapier-prod, internal-cron) so you can revoke individual keys without breaking others.
Keys are shown once when minted. Store them in a secret manager — we only keep a hash. Revoke from the same page.
Base URL
https://incy.my/api/v1
Endpoints
GET /me | Returns user, org, available domains, folders, bio pages |
GET /links | List links. Params: search, tag_id |
POST /links | Create a link |
GET /links/{id} | Fetch one link with stats |
PATCH /links/{id} | Update (owner only) |
DELETE /links/{id} | Delete (owner only) |
GET /links/{id}/stats | Click stats payload |
GET /tags | List org tags |
POST /tags | Create a tag |
Creating a link
curl -X POST https://incy.my/api/v1/links \
-H "Authorization: Bearer stk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"destination_url": "https://example.com/some/page",
"title": "Spring launch",
"tags": ["launch", "q2"],
"folder_id": 3,
"utm": { "utm_source": "linkedin", "utm_medium": "social" }
}'
Optional fields you might use:
slug— pick a custom back-half. Omit to auto-generate a 6-char code.domain_id— which of your domains hosts the link. Omit to use the org's default.destination_ios,destination_android— device-specific overrides.expires_at— UTC ISO datetime; link returns 410 after.password— gate the redirect behind a password prompt.
Response (201):
{
"data": {
"id": 42,
"slug": "k7Qn2b",
"short_url": "https://incy.my/k7Qn2b",
"destination_url": "https://example.com/some/page?utm_source=linkedin&utm_medium=social",
"title": "Spring launch",
"is_active": true,
"folder": { "id": 3, "name": "Campaigns" },
"tags": [{"id": 8, "name": "launch"}, {"id": 9, "name": "q2"}],
"owner": { "id": 1, "name": "Jane Doe" }
}
}
Error responses
401 | Missing or invalid bearer token |
402 | Plan doesn't include API access (Enterprise required) |
403 | You don't own this resource |
404 | Resource not found |
422 | Validation error (message in error field) |
500 | Internal error — please report |
Error body shape:
{ "error": "That slug is already in use on incy.my" }
Conventions
- Auto-tagging: every API-created link is auto-tagged with the API key's name (e.g. a key named
zapier-prodtags links with#zapier-prod) so you can filter API-minted links on the dashboard. - Slug case: slugs are case-insensitive at lookup; canonical form is whatever you submitted (lowercase recommended).
- Slug uniqueness: per-domain.
incy.my/launchandlinks.example.com/launchare different links. - Idempotency on collision: if you try to POST a slug that already exists, you get a 422. Pattern: try POST, on 422 fall back to
GET /links?search=<slug>, then PATCH the existing one if the destination differs. - Rate limits: not currently enforced. We monitor and may add per-key limits if needed; we'll email you before changing.
- CORS: enabled for all origins so browser clients work directly. Bearer token still required.
Full guide
The full user guide at /help covers everything else: dashboard, billing, bio pages, custom domains, folders, tags, etc. The bits above are the API-specific surface.