API reference

Full HTTPS API reference: link creation, slug checks, expirations, routing, and conversions.

Prerequisites

  • An active Nimriz workspace.
  • A Workspace API Key generated from Dashboard → Settings → Integrations → API access. This key is used for all link-management API calls.
  • A secure server-side environment. Never expose your API key in browser-side code, mobile apps, or public repositories.
  • For conversion tracking: a separate Conversion API signing secret (also in Integrations). This secret is used exclusively for the Conversion API and is not the same as the workspace API key.

Fundamental rules

  • All write operations (creating links, updating slugs, changing passwords) must come from a trusted server backend.
  • Link uniqueness is domain-bound: (domain_id, short_code) must be unique, not just short_code globally.
  • Redirects default to 302. Only request 301 when you explicitly want a permanent redirect-browsers cache 301s aggressively.
  • Host matching is strict. example.com and www.example.com are completely separate domains in Nimriz.

Canonical hosts

PurposeHost
Browser dashboard and auth routeshttps://app.nimriz.com
Machine-facing API traffichttps://api.nimriz.com
Redirect trafficYour short domain (e.g., https://links.example.com)

Use api.nimriz.com for all programmatic link-management calls. Short-link domains are redirect surfaces-do not use them as the long-term machine API host.


Authentication

Every link-management API call requires a workspace API key in one of these headers:

Authorization: Bearer <WORKSPACE_API_KEY>
X-Nim-Api-Key: <WORKSPACE_API_KEY>

Both formats are supported. The Authorization: Bearer style is preferred for consistency with standard HTTP auth patterns.

The Conversion API uses a different secret. Do not use your workspace API key for Conversion API requests.


Resource identifiers

IdentifierTypeDescription
domain_idUUIDThe target short-link domain.
url_idUUIDThe created short link. Use this as your durable reference-slugs can change, but url_id is permanent.
short_codeStringThe slug path segment (e.g., spring-launch).
short_urlStringThe full short URL (e.g., https://links.example.com/spring-launch).

POST /api/shorten-Create a link

Creates a single short link.

POST https://api.nimriz.com/api/shorten
Authorization: Bearer <WORKSPACE_API_KEY>
Content-Type: application/json

Request body:

{
  "domain_id": "00000000-0000-0000-0000-000000000000",
  "long_url": "https://example.com/landing?utm_source=twitter&utm_medium=social&utm_campaign=spring",
  "custom_slug": "spring-launch",
  "expires_at": "2026-12-31T23:59:59Z",
  "password": "optional-secret",
  "redirect_status_code": 302
}
FieldRequiredDescription
domain_idYesUUID of the target domain.
long_urlYesThe destination URL. Must use https:// (or http:// if the domain policy allows).
custom_slugNoYour chosen slug. If omitted, Nimriz generates a random one.
expires_atConditionalISO 8601 timestamp. Required by some domain policies.
passwordNoPlain-text password for password protection (plan-gated).
redirect_status_codeNo302 (default) or 301. Avoid 301 unless the destination is truly permanent.

Successful response:

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "short_code": "spring-launch",
  "short_url": "https://links.example.com/spring-launch",
  "expires_at": "2026-12-31T23:59:59.000Z",
  "password_protected": false
}

POST /api/shorten/bulk-Bulk create links

Creates up to 25 links in a single request. Designed for imports and automation jobs that require idempotent retries.

POST https://api.nimriz.com/api/shorten/bulk
Authorization: Bearer <WORKSPACE_API_KEY>
Content-Type: application/json

Request body:

{
  "domain_id": "00000000-0000-0000-0000-000000000000",
  "items": [
    {
      "client_row_id": "row-1",
      "idempotency_key": "import-session-abc-row-1",
      "long_url": "https://example.com/a",
      "custom_slug": "campaign-a"
    },
    {
      "client_row_id": "row-2",
      "idempotency_key": "import-session-abc-row-2",
      "long_url": "https://example.com/b"
    }
  ]
}
FieldRequiredDescription
domain_idYesApplies to all items in the batch.
items[].client_row_idYesYour stable identifier for this row within the batch. Returned in the response so you can match results to inputs.
items[].idempotency_keyYesA stable key for this exact mutation. If you replay the same key, Nimriz returns the stored result instead of creating a duplicate.
items[].long_urlYesDestination URL for this row.
items[].custom_slugNoCustom slug for this row.
items[].expires_atNoPer-row expiration.

Rules:

  • Maximum 25 items per request.
  • Validation failures are returned per-row-a single row failing does not fail the entire batch.
  • Replaying the same idempotency_key returns the stored result with idempotent: true.

Successful response:

{
  "results": [
    {
      "client_row_id": "row-1",
      "ok": true,
      "idempotent": false,
      "url_id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
      "short_code": "campaign-a",
      "short_url": "https://links.example.com/campaign-a"
    },
    {
      "client_row_id": "row-2",
      "ok": false,
      "error": "Slug is reserved",
      "code": "slug_reserved"
    }
  ]
}

POST /api/check-slug-Check slug availability

Validates whether a candidate slug is available on a specific domain before attempting creation.

{
  "domain_id": "00000000-0000-0000-0000-000000000000",
  "slug": "spring-launch"
}

Available:

{ "available": true }

Not available:

{
  "available": false,
  "error": "Slug is reserved",
  "code": "slug_reserved"
}

PUT /api/update-slug-Update a slug

Changes the slug on an existing link. The old slug stops working immediately after the update.

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "new_slug": "spring-launch-v2"
}

Response:

{
  "short_code": "spring-launch-v2",
  "short_url": "https://links.example.com/spring-launch-v2"
}

PUT /api/update-expiration-Update or remove expiration

Sets, changes, or removes the expiration time on a link.

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "expires_at": "2026-12-31T23:59:59Z"
}

To remove expiration (when policy allows):

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "expires_at": null
}

Response:

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "expires_at": "2026-12-31T23:59:59.000Z",
  "was_expired": false
}

PUT /api/update-password-Set or remove password protection

Set or update a password:

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "password": "new-password"
}

Remove password protection:

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "password": null
}

POST /api/links/routing-rules-Save routing rules

Saves the complete ordered routing ruleset for a link. This replaces all existing rules-it is not an additive operation.

{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "operation": "save",
  "rules": [
    {
      "name": "US mobile users",
      "enabled": true,
      "actionType": "destination_override",
      "conditions": {
        "countryIn": ["US"],
        "deviceTypeIn": ["mobile"],
        "deviceOsIn": [],
        "timeWindows": []
      },
      "destinationUrl": "https://example.com/us-mobile"
    }
  ]
}

The rules array is ordered-the first matching enabled rule wins at redirect time. Supported actionType values: destination_override, ab_split, deep_link.


POST /api/conversions/callback/:workspace_id-Record a conversion

Sends a signed conversion event from your backend.

POST https://api.nimriz.com/api/conversions/callback/<WORKSPACE_ID>
Content-Type: application/json
X-Nim-Timestamp: <unix-seconds>
X-Nim-Signature: v1=<hex-hmac-sha256>
Idempotency-Key: <stable-key>

The signature is computed as HMAC-SHA256("${X-Nim-Timestamp}.${raw_request_body}", CONVERSION_SECRET).

Example request body:

{
  "event_name": "sale",
  "event_time": "2026-03-26T12:00:00.000Z",
  "event_id": "evt_sale_123",
  "user_data": {
    "click_id": "nimct_exampletoken",
    "external_id": "cust_123"
  },
  "custom_data": {
    "order_id": "order_abc",
    "value": 99.00,
    "currency": "USD"
  }
}

Supported event_name values: lead, sale, refund, cancellation, reversal.


Link Search and Retrieval API

GET /api/v1/links/find-Find link by URL or Domain/Slug

Look up a specific link based on its short URL or its domain ID and short code.

GET https://api.nimriz.com/api/v1/links/find?short_url=https://links.example.com/spring-launch
Authorization: Bearer <WORKSPACE_API_KEY>

Supported query parameters (must provide either short_url OR domain_id + short_code):

ParameterDescription
short_urlFull short URL to look up.
domain_idDomain UUID.
short_codeShort code on the domain.

GET /api/v1/links-List recent links

Returns a list of recently created links for the specified workspace.

GET https://api.nimriz.com/api/v1/links?account_id=WORKSPACE_UUID&limit=50
Authorization: Bearer <WORKSPACE_API_KEY>

Supported query parameters:

ParameterDescription
account_idWorkspace UUID.
limitMax number of links to return (max 100, default 50).

GET /api/v1/links/:id-Get link by ID

Returns a single link record.

GET https://api.nimriz.com/api/v1/links/22222222-2222-2222-2222-222222222222
Authorization: Bearer <WORKSPACE_API_KEY>

QR API

Professional and Enterprise workspaces can automate QR rendering, preset management, and QR-only link analytics through the same customer API host.

QR API rules

  • QR endpoints require the same workspace API key auth model shown above.
  • QR rendering always targets an existing Nimriz url_id; QR remains a view of a short link, not a separate QR object.
  • The API uses the same validation and plan checks as the dashboard, including QR CTA layout access and custom CTA text restrictions.
  • The same canonical QR style state drives dashboard previews, downloads, preset saves, and API renders.

Available QR endpoints

MethodPathPurpose
POST/api/v1/qr/generateRender a QR asset for an existing link.
GET/api/v1/qr/presetsList QR presets visible to the workspace.
POST/api/v1/qr/presetsCreate a QR preset.
PUT/api/v1/qr/presets/:idUpdate a QR preset.
DELETE/api/v1/qr/presets/:idDelete a QR preset.
GET/api/v1/links/:id/qrDownload the link's effective QR asset.
GET/api/v1/links/:id/analyticsReturn link analytics with touch_type=qr_scan by default.

POST /api/v1/qr/generate-Render a QR asset

Renders a QR image from the requested link's saved QR state, with optional preset or style overrides.

POST https://api.nimriz.com/api/v1/qr/generate
Authorization: Bearer <WORKSPACE_API_KEY>
Content-Type: application/json
{
  "url_id": "22222222-2222-2222-2222-222222222222",
  "format": "png",
  "size": 1024,
  "force_regenerate": false,
  "qr_preset_id": "55555555-5555-5555-5555-555555555555",
  "style": {
    "background": { "mode": "transparent" }
  }
}

Notes:

  • url_id is required and must belong to a link the API key can access.
  • format can be png or svg. Defaults to svg when omitted.
  • size is clamped to 128-2048. The default is 512.
  • force_regenerate: true bypasses any cached asset and rebuilds the QR output.
  • qr_preset_id is optional.
  • style is optional and must match the same QR style schema the dashboard uses.

Successful responses return the QR asset itself with the correct image content type and download headers.

GET /api/v1/qr/presets-List QR presets

Lists QR presets for the authenticated workspace.

GET https://api.nimriz.com/api/v1/qr/presets
Authorization: Bearer <WORKSPACE_API_KEY>

Successful responses return:

{
  "ok": true,
  "presets": [
    {
      "id": "55555555-5555-5555-5555-555555555555",
      "name": "Conference handout",
      "style": {},
      "is_default": true,
      "created_at": "2026-04-12T10:00:00.000Z",
      "updated_at": "2026-04-12T10:00:00.000Z",
      "logo_preview_url": "https://..."
    }
  ]
}

POST /api/v1/qr/presets-Create a QR preset

Creates a reusable QR preset using the same style contract as the dashboard.

{
  "name": "Conference handout",
  "is_default": true,
  "style": {
    "background": { "mode": "transparent" }
  }
}

Rules:

  • Preset names are limited to 120 characters.
  • Plan preset limits still apply.
  • Frame entitlement checks still apply.
  • If is_default is true, Nimriz clears the previous default preset in that workspace.

PUT /api/v1/qr/presets/:id-Update a QR preset

Updates one or more preset fields.

{
  "name": "Conference handout v2",
  "is_default": false,
  "style": {
    "background": { "mode": "single", "color": "#ffffff" }
  }
}

You can send any subset of name, is_default, and style. The same style validation and frame plan checks apply as on create.

DELETE /api/v1/qr/presets/:id-Delete a QR preset

Deletes the target preset and returns the deleted preset id on success.

GET /api/v1/links/:id/qr-Download the effective QR asset

Fetches the saved QR asset for an existing link.

GET https://api.nimriz.com/api/v1/links/22222222-2222-2222-2222-222222222222/qr?format=svg&size=1024&force_regenerate=1
Authorization: Bearer <WORKSPACE_API_KEY>

Supported query parameters:

ParameterDescription
formatpng or svg. Defaults to svg.
sizeOptional size from 128-2048. Defaults to 512.
force_regenerate1, true, yes, or on forces a fresh render.

GET /api/v1/links/:id/analytics-Fetch QR-filtered analytics

Returns per-day totals and points for the target link. If you do not pass touch_type, the endpoint defaults to qr_scan.

GET https://api.nimriz.com/api/v1/links/22222222-2222-2222-2222-222222222222/analytics?range_days=30&include_bots=0&touch_type=qr_scan
Authorization: Bearer <WORKSPACE_API_KEY>

Supported query parameters:

ParameterDescription
range_daysOptional daily range from 1-365. Defaults to 30.
include_bots0/1 or boolean-like values. Defaults to 0.
touch_typeqr_scan or short_link_click. Defaults to qr_scan.

Successful responses return:

{
  "ok": true,
  "url_id": "22222222-2222-2222-2222-222222222222",
  "range_days": 30,
  "include_bots": false,
  "touch_type": "qr_scan",
  "available": true,
  "totals": {
    "clicks": 120,
    "bot_clicks": 8,
    "human_clicks": 112,
    "selected_clicks": 112
  },
  "points": [
    {
      "date": "2026-04-01",
      "clicks": 12,
      "bot_clicks": 1,
      "human_clicks": 11,
      "selected_clicks": 11
    }
  ]
}

Common error codes

CodeHTTPMeaning
plan_limit403The request exceeds the current plan's preset or capability limit.
monthly_quota_exceeded429Monthly link-creation quota exceeded.
slug_reserved422Slug is a system path or below the minimum length.
slug_unavailable422Slug is taken or recently deleted.
domain_disabled422Target domain is inactive.
custom_domain_not_ready422Domain is not yet Ready for traffic.
account_suspended403Account is suspended.
destination_blocked422Destination URL uses a forbidden scheme or points to a Nimriz domain.
invalid_expires_at422Expiration timestamp is malformed or in the past.
expiration_required422Domain policy requires an expiration date.
expiration_update_not_allowed422Domain policy blocks expiration changes on this link.
feature_not_enabled403The requested feature (e.g., password protection) is not available on your plan.
routing_rules_not_allowed403Routing rules are not enabled for this workspace.

Retry guidance

  • Do not retry 4xx errors immediately-they indicate input problems or policy failures that will not resolve with a retry.
  • Do retry 429, 502, 503, 504 with exponential backoff.
  • For bulk import jobs, use POST /api/shorten/bulk with stable idempotency_key values so retries are safe.

Related guides