Links
Branded short links + QR codes. Bearer-auth, team-scoped, two ability tracks: links:read / links:write for management, plus the separate links:analytics:read for the stats endpoints.
Base URL: https://formspring.io/api/v1
| Method | Path | Ability |
|---|---|---|
| GET | /links |
links:read |
| POST | /links |
links:write |
| GET | /links/search?q=… |
links:read |
| GET | /links/query?slug=… |
links:read |
| POST | /links/upsert |
links:write |
| GET | /links/{link} |
links:read |
| PATCH | /links/{link} |
links:write |
| DELETE | /links/{link} |
links:write |
| GET | /links/{link}/qr?format=svg|png |
links:read |
| GET | /links/{link}/stats/counters |
links:analytics:read |
| GET | /links/{link}/stats/views |
links:analytics:read |
| GET | /links/{link}/stats/heatmap |
links:analytics:read |
| GET | /links/{link}/stats/metrics |
links:analytics:read |
| GET | /links/{link}/stats/events |
links:analytics:read |
| GET | /links/{link}/stats/locations |
links:analytics:read |
The {link} path parameter accepts the link's ULID.
List links
GET /links?per_page=25
Returns the current team's links (excluding trashed), paginated.
Create a link
POST /links
Content-Type: application/json
{
"target_url": "https://example.com/very/long/landing/path?utm_source=…",
"slug": "spring-promo",
"title": "Spring 2026 promo",
"branded_domain_id": 4,
"utm_params": {
"utm_source": "newsletter",
"utm_campaign": "spring-2026"
}
}
target_urlrequired.slug- when omitted, the API picks an unambiguous slug from the configured alphabet (no 0/O/1/l/i).branded_domain_id- bind to a verified branded domain. Without this the link serves on the team's shortener domain (e.g.frmsp.io).utm_params- appended to the target URL on every redirect whenredirect_with_queryis enabled.
Response 201: LinkResource including the canonical short_url.
Idempotent upsert
POST /links/upsert
Content-Type: application/json
{
"slug": "spring-promo",
"target_url": "https://example.com/new-target"
}
Useful from CI / sync scripts: returns 201 when the slug is new, 200 when it already exists and the row was updated. The slug field is required.
Search
GET /links/search?q=spring
Free-text search across slug, title, and target URL. Returns up to 50 matches.
Query by exact slug
GET /links/query?slug=spring-promo
Strict lookup. Returns the resource or 404 - useful when you have a known slug from an external system and want to confirm it exists before redirecting.
Update a link
PATCH /links/{link}
Content-Type: application/json
{
"target_url": "https://example.com/new-target",
"disabled_at": null
}
All fields optional. Set disabled_at to a timestamp to disable the redirect without deleting the link; set it to null to re-enable. Disabling is also what DELETE does as a guardrail.
QR code
GET /links/{link}/qr
GET /links/{link}/qr?format=png
Renders the link's branded QR code as SVG (default) or PNG. Caches edge-side; rotation of the QR happens when the team updates branding or rotates the link.
Delete a link
DELETE /links/{link}
Soft-deletes + sets disabled_at. The short URL stops serving immediately even if the soft-delete scope is bypassed by a cached resolver. Recoverable from the admin trash.
Analytics
The six /stats/* endpoints all require links:analytics:read (separate from links:read so you can issue read-only tokens that don't see who clicked what).
counters- totals by horizon (today, 7d, 30d, all-time).views- time-series of clicks at hourly/daily resolution.heatmap- 7 × 24 matrix for day-of-week × hour-of-day visualization.metrics- bucketed dimensions (browser, OS, device, referrer host).events- recent raw click events (capped, useful for live tail).locations- top countries / cities by click volume.
Click events are recorded asynchronously; analytics has an eventual-consistency lag of a few seconds during high-traffic periods.
Errors
| Status | When |
|---|---|
| 403 | Token missing required ability |
| 404 | Link doesn't belong to the current team, or has been hard-deleted |
| 422 | Validation (e.g. slug collision when upserting against a different team's link) |
See also
- Tokens & abilities →
- MCP server → - same operations as agent tools