Skip to content

Integrations

Nonaki exposes a REST API that allows third-party tools and services to manage your redirects and read your click and impression data. Access is controlled by two separate API keys you manage from the Integrations tab in the plugin.


API Keys

Go to Nonaki LinksIntegrations to view and manage your API keys.

For each key:

  • Copy — copy the key to your clipboard to paste into a third-party service
  • Regenerate — generate a new key immediately. The old key stops working as soon as you regenerate. Make sure to update any service using the old key.

Grants access to the redirects and tags endpoints. Use this to let external tools create, update, or delete your links.

Keep this key private. Anyone who has it can read and modify all your redirects and tags.

Stats API Key

Grants access to the stats endpoints. Use this to let external tools read your click and impression data.

Keep this key private. Anyone who has it can read all your click and impression data.


Authentication

All API requests must include the key as a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Requests without a valid key receive a 401 Unauthorized response.


All endpoints are under https://yoursite.com/wp-json/nonaki/v2/ and require the Links API Key.

The redirect object

json
{
  "id": 42,
  "link_key": "dinomatic",
  "destination_url": "https://dinomatic.com/themes",
  "redirect_type": 301,
  "status": "active",
  "link_status": "ok",
  "click_count": 1024,
  "impression_count": 8820,
  "tags": [{ "id": 3, "name": "Themes", "slug": "themes" }],
  "created_at": "2025-11-04 09:15:00",
  "updated_at": "2026-03-19 14:22:11"
}

redirect_type is 301, 302, or 307. status is active or trashed. link_status is ok, broken, or unchecked.


GET /redirects

Returns a paginated list of redirects.

Query parameters:

ParameterDefaultDescription
page1Page number.
per_page20Results per page (max 100).
searchFilter by key or destination URL.
statusactiveFilter by status: active or trashed.
tag_idFilter by tag ID.

Response:

json
{
  "data": [{ "id": 42, "link_key": "dinomatic", "...": "..." }],
  "total": 120,
  "pages": 6
}

POST /redirects

Creates a new redirect.

Body:

FieldRequiredDescription
link_keyYesShort key used in the redirect URL (e.g. promo).
destination_urlYesThe URL to redirect to.
redirect_typeYes301, 302, or 307.
tag_idsNoArray of tag IDs to assign.

Returns the created redirect object with status 201 Created.


GET /redirects/{id}

Returns a single redirect by ID.


PATCH /redirects/{id}

Updates a redirect. All fields are optional — only send what you want to change.

Body: any combination of link_key, destination_url, redirect_type, tag_ids.

Sending tag_ids replaces the redirect's tags entirely.


DELETE /redirects/{id}

Moves the redirect to trash. Returns 204 No Content. Use POST /redirects/{id}/restore to undo.


POST /redirects/{id}/restore

Restores a trashed redirect back to active. Returns the redirect object.


DELETE /redirects/{id}/force-delete

Permanently deletes a redirect. This cannot be undone. Returns 204 No Content.


POST /redirects/bulk

Applies an action to multiple redirects at once.

Body:

FieldRequiredDescription
actionYesOne of: trash, restore, force-delete, tag-add, tag-remove.
idsYesArray of redirect IDs.
tag_idsFor tag-add / tag-remove onlyArray of tag IDs to add or remove.

Response:

json
{ "affected": 5 }

GET /tags

Returns all tags.

Response:

json
{
  "data": [{ "id": 3, "name": "Themes", "slug": "themes", "link_count": 12 }]
}

POST /tags

Creates a new tag.

Body: name (required).

Returns the created tag object with status 201 Created:

json
{ "data": { "id": 4, "name": "Plugins", "slug": "plugins" } }

PATCH /tags/{id}

Updates a tag's name. Body: name (required). Returns the updated tag object.


DELETE /tags/{id}

Permanently deletes a tag. Returns 204 No Content.


Stats Endpoints

All endpoints are under https://yoursite.com/wp-json/nonaki/v2/ and require the Stats API Key.

Returns a paginated list of all active links.

Query parameters: same as /stats/clicks (after_id, per_page).

Response:

json
{
  "data": [
    {
      "id": 12,
      "link_key": "dinomatic",
      "destination_url": "https://dinomatic.com/themes",
      "redirect_type": "301",
      "created_at": "2025-11-04 09:15:00"
    }
  ],
  "meta": {
    "per_page": 100,
    "has_more": false,
    "last_id": 12
  }
}

GET /stats/clicks

Returns a paginated list of raw click events.

Query parameters:

ParameterDefaultMaxDescription
after_id0Return only clicks with an ID greater than this value. Use for pagination.
per_page100500Number of results per page.

Response:

json
{
  "data": [
    {
      "id": 1042,
      "link_key": "dinomatic",
      "destination_url": "https://dinomatic.com/themes",
      "occurred_at": "2026-03-19 14:22:11",
      "device_type": "desktop",
      "browser": "Chrome",
      "os": "Windows",
      "country_code": "US",
      "referer": "https://yoursite.com/best-gambling-wp-themes/",
      "ip_hash": "a3f1c9...",
      "bot_detected": false,
      "bot_name": null
    }
  ],
  "meta": {
    "per_page": 100,
    "has_more": true,
    "last_id": 1042
  }
}

GET /stats/impressions

Returns a paginated list of raw impression events.

Query parameters: same as /stats/clicks.

Response: same structure as clicks, with page_url instead of referer:

json
{
  "data": [
    {
      "id": 8801,
      "link_key": "dinomatic",
      "destination_url": "https://dinomatic.com/themes",
      "occurred_at": "2026-03-19 14:20:05",
      "device_type": "mobile",
      "browser": "Safari",
      "os": "iOS",
      "country_code": "GB",
      "page_url": "https://yoursite.com/best-gambling-wp-themes/",
      "ip_hash": "b7e2d1...",
      "bot_detected": false,
      "bot_name": null
    }
  ],
  "meta": {
    "per_page": 100,
    "has_more": false,
    "last_id": 8801
  }
}

Returns an aggregated summary for a single link.

URL parameter: link_key — the link's short key (e.g. dinomatic).

Query parameter: days — number of days to include (e.g. ?days=30). Pass 0 for all time. Defaults to 30.

Response:

json
{
  "data": {
    "total_clicks": 412,
    "total_impressions": 3840,
    "clicks_by_day": { "2026-03-18": 24, "2026-03-19": 31 },
    "by_device": { "desktop": 280, "mobile": 120, "tablet": 12 },
    "by_country": { "US": 180, "GB": 74, "CA": 60 },
    "by_browser": { "Chrome": 210, "Safari": 98 },
    "top_referrers": { "yoursite.com/best-gambling-wp-themes/": 140 }
  }
}

Pagination

The links, clicks, and impressions endpoints use cursor-based pagination via after_id. To retrieve all records:

  1. Make an initial request (no after_id)
  2. If meta.has_more is true, make the next request with after_id set to meta.last_id
  3. Repeat until meta.has_more is false

Efficient Polling with Last-Modified

All endpoints include a Last-Modified header in their responses indicating the timestamp of the most recent event in the queried range.

On subsequent polls, send this value back as If-Modified-Since:

If-Modified-Since: Wed, 19 Mar 2026 14:22:11 GMT

If no new events exist, the server returns 304 Not Modified with an empty body — saving bandwidth and processing time on both ends.