Short Links

Create and manage short links and QR codes programmatically. Generate branded QR codes, set redirect destinations, tag campaigns, and pull click analytics via the REST API.

Create and manage short links (QR codes and redirects) programmatically. Every short link redirects visitors to a destination URL, records a click, and can carry campaign tags and QR styling — all creatable in a single call.

A short link bundles three things:

  • A short code — generated automatically and embedded in the public URL (/redirect/{code}). You never set it; it's returned as pixel on the entity.
  • A destination (redirectUrl) — where the visitor is sent.
  • A design — campaign (utm) tags appended to the tracked URL and QR code visual styling (qr).

The composed public URL is returned as shortUrl. It encodes the short code, the link name (sent as the tracked event), and the campaign tags. That same URL is what a QR code should encode. It also resolves on any branded custom domains configured for your account, so you can front it with your own domain without regenerating printed QR codes.

POST /rest/v1/short-links creates a usable short link in one call. All fields are optional — send {} to create an unconfigured link and fill it in later with PATCH.

curl -X POST https://app.oursprivacy.com/rest/v1/short-links \
  -H "Authorization: Bearer $OURS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring Sale",
    "redirectUrl": "https://example.com/spring",
    "utm": { "campaign": "spring_sale", "source": "newsletter" },
    "qr": { "fgColor": "#001722", "dotStyle": "rounded" }
  }'

The response includes the composed shortUrl and the folded shortLinkDesign, so you can render a QR and share the link without a follow-up request.

A newly created short link only resolves at the edge once a version is published. Publish with POST /rest/v1/versions after creating or editing your short links. Until then, the destination is saved but the short URL does not redirect.

Bulk creation

To migrate or create many short links at once, loop POST /rest/v1/short-links per link, then publish a single version at the end. (A dedicated batch endpoint is planned.)

Click analytics

GET /rest/v1/short-links/{id}/results returns aggregate click analytics over a date window: total and unique clicks, a daily or hourly time series, and breakdowns by country, city, and device. QR scans are counted as clicks. This endpoint requires the shortlink:reporting scope, which is granted separately because analytics data is PHI-bearing.

GET
/rest/v1/short-links
AuthorizationBearer <token>

Ours Privacy API key

In: header

Query Parameters

limit?|

Maximum number of items to return. Defaults to 25; values below 1 are clamped to 1 and values above 100 are clamped to 100.

cursor?string

Opaque pagination cursor from pagination.nextCursor in the previous response. Do not decode or modify it. Malformed cursors return 400 Bad Request.

status?string

Filter by short link status.

nameContains?string

Case-insensitive substring filter on the short link name.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/rest/v1/short-links"
{
  "entities": [
    {
      "id": "string",
      "name": "string",
      "status": "Disabled",
      "createdAt": "string",
      "accountId": "string",
      "isPublished": true,
      "redirectUrl": "string",
      "pixel": "string",
      "shortUrl": "string",
      "shortLinkDesign": {}
    }
  ],
  "pagination": {
    "nextCursor": "string",
    "hasMore": true
  }
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
POST
/rest/v1/short-links
*object
AuthorizationBearer <token>

Ours Privacy API key

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/rest/v1/short-links" \  -H "Content-Type: application/json" \  -d '{}'
{
  "id": "string",
  "name": "string",
  "status": "Disabled",
  "createdAt": "string",
  "accountId": "string",
  "isPublished": true,
  "redirectUrl": "string",
  "pixel": "string",
  "shortUrl": "string",
  "shortLinkDesign": {}
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
GET
/rest/v1/short-links/{id}
AuthorizationBearer <token>

Ours Privacy API key

In: header

Path Parameters

id*string

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/rest/v1/short-links/string"
{
  "id": "string",
  "name": "string",
  "status": "Disabled",
  "createdAt": "string",
  "accountId": "string",
  "isPublished": true,
  "redirectUrl": "string",
  "pixel": "string",
  "shortUrl": "string",
  "shortLinkDesign": {}
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
PATCH
/rest/v1/short-links/{id}
*object
AuthorizationBearer <token>

Ours Privacy API key

In: header

Path Parameters

id*string

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X PATCH "https://example.com/rest/v1/short-links/string" \  -H "Content-Type: application/json" \  -d '{}'
{
  "id": "string",
  "name": "string",
  "status": "Disabled",
  "createdAt": "string",
  "accountId": "string",
  "isPublished": true,
  "redirectUrl": "string",
  "pixel": "string",
  "shortUrl": "string",
  "shortLinkDesign": {}
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
DELETE
/rest/v1/short-links/{id}
AuthorizationBearer <token>

Ours Privacy API key

In: header

Path Parameters

id*string

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X DELETE "https://example.com/rest/v1/short-links/string"
{
  "deleted": true
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
GET
/rest/v1/short-links/{id}/results
AuthorizationBearer <token>

Ours Privacy API key

In: header

Path Parameters

id*string

Query Parameters

from*string

Inclusive lower bound of the report window, a UTC calendar day in YYYY-MM-DD.

to*string

Inclusive upper bound of the report window, a UTC calendar day in YYYY-MM-DD.

granularity?string

Time-series bucket size. Defaults to DAILY.

excludeBots?boolean

Exclude bot traffic from the counts. Defaults to true.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/rest/v1/short-links/string/results?from=2026-06-01&to=2026-06-30"
{
  "totalClicks": 0,
  "uniqueClicks": 0,
  "timeSeries": [
    {
      "period": "string",
      "clicks": 0,
      "uniqueClicks": 0
    }
  ],
  "geoByCountry": [
    {
      "name": "string",
      "clicks": 0,
      "uniqueClicks": 0
    }
  ],
  "geoByCity": [
    {
      "name": "string",
      "clicks": 0,
      "uniqueClicks": 0
    }
  ],
  "devices": [
    {
      "name": "string",
      "clicks": 0,
      "uniqueClicks": 0
    }
  ]
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}
{
  "error": "string",
  "details": "string"
}

How is this guide?