0.05 — API
The Link API.
Zero friction.
Link exposes a small REST API so your code can create and measure short links. Same rules as everything we make: simple, documented, free.
Base URL
https://zerosoft.ai/api/v1Authentication
Every request needs an API key, sent as a Bearer token:
Authorization: Bearer zs_live_9f3k...Create keys in Dashboard → Settings → API keys. A key is shown exactly once — copy it and store it like a password.
Each key allows 100 requests per minute. Go over and you get a 429 with a Retry-After header. Need more? Self-host and rate-limit yourself.
Endpoints
Create a link
Creates a short link. slug is optional — leave it out and we generate one.
Request
curl -X POST https://zerosoft.ai/api/v1/links \
-H "Authorization: Bearer zs_live_9f3k..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://zerosoft.ai/blog/software-is-dead",
"slug": "manifesto",
"title": "The manifesto",
"tags": ["launch", "blog"]
}'Response · 201
{
"id": "lnk_9f3ka2",
"slug": "manifesto",
"short_url": "https://zs.ai/manifesto",
"url": "https://zerosoft.ai/blog/software-is-dead",
"title": "The manifesto",
"tags": ["launch", "blog"],
"created_at": "2026-07-14T18:22:41Z"
}List links
Your links, newest first. Paginate with page and pageSize (max 100).
Request
curl "https://zerosoft.ai/api/v1/links?page=1&pageSize=10" \
-H "Authorization: Bearer zs_live_9f3k..."Response · 200
{
"links": [
{
"id": "lnk_9f3ka2",
"slug": "manifesto",
"short_url": "https://zs.ai/manifesto",
"url": "https://zerosoft.ai/blog/software-is-dead",
"title": "The manifesto",
"tags": ["launch", "blog"],
"created_at": "2026-07-14T18:22:41Z"
}
],
"total": 48
}Link stats
Click totals and a per-day breakdown for one link.
Request
curl "https://zerosoft.ai/api/v1/links/lnk_9f3ka2/stats" \
-H "Authorization: Bearer zs_live_9f3k..."Response · 200
{
"slug": "manifesto",
"total": 4812,
"byDay": [
{ "date": "2026-07-15", "count": 412 },
{ "date": "2026-07-16", "count": 388 },
{ "date": "2026-07-17", "count": 441 }
]
}The CRM API
The CRM ships with the same API: same keys, same rate limit, same rules. Contacts, companies, deals and tasks — everything the dashboard can do, your code can do.
Create a contact
Request
curl -X POST https://zerosoft.ai/api/v1/crm/contacts \
-H "Authorization: Bearer zs_live_9f3k..." \
-H "Content-Type: application/json" \
-d '{
"first_name": "Ana",
"last_name": "Garcia",
"email": "ana@kallpa.co",
"lifecycle_stage": "sql"
}'Response · 201
{
"id": "b1f47ac2-…",
"first_name": "Ana",
"last_name": "Garcia",
"email": "ana@kallpa.co",
"lifecycle_stage": "sql",
"created_at": "2026-07-18 10:04:11"
}Every CRM endpoint
| Method | Endpoint | What it does |
|---|---|---|
| GET | /api/v1/crm/contacts | List contacts. Filters: q, page, pageSize (max 100). |
| POST | /api/v1/crm/contacts | Create a contact. |
| GET | /api/v1/crm/contacts/:id | Read one contact. |
| PATCH | /api/v1/crm/contacts/:id | Update any property. |
| GET | /api/v1/crm/companies | List companies. |
| POST | /api/v1/crm/companies | Create a company. |
| GET | /api/v1/crm/companies/:id | Read one company. |
| PATCH | /api/v1/crm/companies/:id | Update any property. |
| GET | /api/v1/crm/deals | List deals. Filter: pipelineId. |
| POST | /api/v1/crm/deals | Create a deal in a pipeline stage. |
| GET | /api/v1/crm/deals/:id | Read one deal. |
| PATCH | /api/v1/crm/deals/:id | Update amount, stage, dates. |
| GET | /api/v1/crm/tasks | List tasks. bucket: overdue, today, upcoming, done. |
| POST | /api/v1/crm/tasks | Create a task, optionally linked to a record. |
| PATCH | /api/v1/crm/tasks/:id | Edit or complete a task. |
Errors
Errors are always JSON with the same shape:
{
"error": {
"code": "slug_taken",
"message": "That slug is already in use."
}
}| Code | HTTP | Meaning |
|---|---|---|
invalid_key | 401 | The key is missing, wrong or revoked. |
invalid_url | 400 | The url field is missing or is not a valid http(s) URL. |
slug_taken | 400 | That custom slug already exists. Pick another. |
not_found | 404 | No link with that id belongs to your account. |
rate_limited | 429 | Over 100 requests in a minute. Wait for Retry-After. |
Good to know
- Slugs match
[A-Za-z0-9_-]{2,32}— letters, numbers, dash and underscore, 2 to 32 characters. - Redirects are public 302s at the root —
https://<your-domain>/<slug>. No interstitials, no ads, no tracking pages. - Analytics are cookie-less: referrer, country and device come from request headers. Nothing personal is stored.
Coming soon
Track and Cal will ship with the same style of API — REST, JSON, boring in the best way. These docs grow as each product is set free.