Skip to content

Links

Create, list, update, delete, toggle, and bulk-create links, and fetch QR images.

Updated View as Markdown

The core of the API. Every endpoint is under https://in.bio/api/v1 and requires a bearer token — see the overview for authentication, scopes, and rate limits.

Every response returns the link resource:

{
  "id": 42,
  "slug": "spring-sale",
  "short_url": "https://in.bio/spring-sale",
  "destination_url": "https://example.com/sale",
  "title": "Spring sale",
  "description": null,
  "status": "active",
  "redirect_type": 302,
  "folder_id": 3,
  "tags": ["marketing"],
  "expires_at": null,
  "click_limit": null,
  "has_password": false,
  "total_clicks": 1240,
  "unique_clicks": 981,
  "last_clicked_at": "2026-07-21T18:03:11+00:00",
  "created_at": "2026-06-01T09:00:00+00:00",
  "updated_at": "2026-07-01T09:00:00+00:00"
}
Field Type Description
id integer Stable numeric identifier.
slug string The short code (the part after the domain).
short_url string The full short link.
destination_url string Where the link redirects.
title, description string | null Optional metadata.
status string active, disabled, archived, expired, exhausted, blocked, pending_review.
redirect_type integer 301, 302, or 307.
folder_id integer | null Folder the link belongs to.
tags string[] Tag names.
expires_at string | null ISO 8601 expiry, if set.
click_limit integer | null Max clicks before the link stops, if set.
has_password boolean Whether the link is password-protected.
total_clicks, unique_clicks integer Lifetime click counters.
last_clicked_at string | null ISO 8601 timestamp of the last click.
created_at, updated_at string ISO 8601 timestamps.

GET /api/v1/links · scope links:read

Query param Type Description
search string Matches slug, title, or destination URL.
folder_id integer Only links in this folder.
tag string Only links with this tag name.
status string Filter by status (see the resource table above).
page integer Page number (default 1).
per_page integer Items per page, 1100 (default 25).
curl "https://in.bio/api/v1/links?search=sale&per_page=25" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"
const res = await fetch("https://in.bio/api/v1/links?search=sale", {
  headers: {
    Authorization: "Bearer YOUR_TOKEN",
    Accept: "application/json",
  },
});
const { data, meta } = await res.json();
import requests

r = requests.get(
    "https://in.bio/api/v1/links",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    params={"search": "sale", "per_page": 25},
)
links = r.json()["data"]

Returns a paginated collection: link resources in data, plus Laravel-style links and meta objects.

{
  "data": [ { "id": 42, "slug": "spring-sale", "...": "link fields" } ],
  "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
  "meta": { "current_page": 1, "per_page": 25, "total": 57, "last_page": 3 }
}

POST /api/v1/links · scope links:write

Only destination_url is required.

Field Type Description
destination_url string Required. http/https, max 2048 chars.
slug string 4–64 chars [a-zA-Z0-9-_]; omitted → random.
title, description, notes string Optional metadata.
redirect_type integer 301, 302 (default), or 307.
folder_id integer Must be one of your folders.
tags string[] Up to 20; created on the fly.
utm object { source, medium, campaign, term, content }.
expires_at, fallback_url string Requires link expiration (Pro+).
click_limit integer Requires click limits (Pro+).
password string Requires password protection (Pro+).
curl -X POST https://in.bio/api/v1/links \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "destination_url": "https://example.com/sale",
    "slug": "spring-sale",
    "title": "Spring sale",
    "tags": ["marketing"],
    "utm": { "source": "newsletter", "medium": "email" }
  }'
const res = await fetch("https://in.bio/api/v1/links", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    destination_url: "https://example.com/sale",
    slug: "spring-sale",
    tags: ["marketing"],
  }),
});
const link = await res.json();
import requests

r = requests.post(
    "https://in.bio/api/v1/links",
    headers={"Authorization": "Bearer YOUR_TOKEN"},
    json={
        "destination_url": "https://example.com/sale",
        "slug": "spring-sale",
        "tags": ["marketing"],
    },
)
link = r.json()

Returns 201 Created with the link resource. Reaching your monthly link quota returns 422 with error.type = "entitlement".


Bulk create

POST /api/v1/links/bulk · scope links:write · Business

Create up to 100 links in one request. Body: { "links": [ ... ] }, each object taking the same fields as Create. Rows fail independently.

curl -X POST https://in.bio/api/v1/links/bulk \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "links": [
    { "destination_url": "https://example.com/a", "slug": "a1" },
    { "destination_url": "https://example.com/b", "slug": "a1" }
  ] }'
{
  "data": {
    "created": [ { "id": 43, "slug": "a1", "...": "link fields" } ],
    "failed": [ { "index": 1, "error": "This slug is already taken." } ]
  }
}

GET /api/v1/links/{id} · scope links:read

curl https://in.bio/api/v1/links/42 \
  -H "Authorization: Bearer YOUR_TOKEN"

Returns the link resource, or 404 if it doesn’t exist or isn’t yours.


PATCH /api/v1/links/{id} · scope links:write

Send any subset of the Create fields plus slug. Editing destination_url requires the edit-destination feature (Pro+) and re-triggers a safety scan.

curl -X PATCH https://in.bio/api/v1/links/42 \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Spring sale 2026", "tags": ["marketing", "email"] }'

Returns the updated link resource.


DELETE /api/v1/links/{id} · scope links:write

curl -X DELETE https://in.bio/api/v1/links/42 \
  -H "Authorization: Bearer YOUR_TOKEN"

Returns 204 No Content.


Enable / disable

POST /api/v1/links/{id}/enable · scope links:write
POST /api/v1/links/{id}/disable · scope links:write

Toggle a link between active and disabled. A disabled link stops redirecting but keeps its slug and stats.

curl -X POST https://in.bio/api/v1/links/42/disable \
  -H "Authorization: Bearer YOUR_TOKEN"

Returns the updated link resource. Toggling from any other state returns 409 with error.type = "state" and the current status.


QR image

GET /api/v1/links/{id}/qr · scope links:read

Returns the link’s QR code as a raw image, using whatever design is saved for the link.

Query param Type Default
format png, svg png
size 642048 (px) link default
curl "https://in.bio/api/v1/links/42/qr?format=svg&size=1024" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -o qr.svg
Navigation

Type to search…

↑↓ navigate↵ selectEsc close