A small API.
All the right context.
Look up all matching clicks in your account.
Authenticate
Create an API key in your dashboard. Treat it as a password and send it only from a trusted server. The full key is shown once; the service stores only its hash.
Authorization: Bearer <api_key>Search click history
GET https://iink.click/api/v1/check?ip_address=203.0.113.42
Authorization: Bearer <api_key>The response is a JSON array with all matching clicks for your account’s links, including repeated visits to the same link. Supply at least one criterion: IP, tags, device type/brand/model, operating system, screen resolution, or a UTC time bound. IP is optional. All supplied criteria combine with AND; OR is available only between tags. A valid search with no matches returns [] and consumes one API check. Use URL encoding for query values. cursor and tags_match alone do not count as criteria.
Both IPv4 and IPv6 are supported through ip_address. An explicitly supplied empty or invalid IP returns 400. The legacy ip parameter remains supported. If both parameters are supplied, they must normalize to the same address; conflicting addresses return 400.
[
{
"id": "dbd8d015-68a7-46cd-bcb2-f0acaa24a86a",
"source_url": "https://iink.click/wakeo.rey",
"target_url": "https://example.com/wakeo",
"tags": ["promo", "wakeo"],
"ip_address": "203.0.113.42",
"clicked_at": "2026-10-10 14:30:12.123 UTC",
"device_type": "smartphone",
"device_brand": "Samsung",
"device_model": "Galaxy S23",
"os_name": "Android",
"browser_name": "Chrome",
"language": "en-GB",
"referrer_url": "https://example.com/articles/wakeo?campaign=launch",
"screen_width_css": 390,
"screen_height_css": 844,
"device_pixel_ratio": 3,
"screen_width_px": 1170,
"screen_height_px": 2532
}
]| Field | Meaning |
|---|---|
| id | The click’s stable UUID version 4 identifier. It identifies this individual visit, stays the same across searches, and differs for repeated visits to the same link. The link ID is separate. |
| source_url | The complete short URL as it appeared at the time of the click. |
| target_url | The destination URL at the time of the click. |
| tags | The link’s current tags as an array of strings. Returns [] when the link has no tags. |
| ip_address | The recorded IPv4 or IPv6 address. |
| clicked_at | Click timestamp in UTC, including milliseconds. |
| device_type | The recognized device type, including detailed categories supplied by the parser. Returns "unknown" when unavailable. |
| device_brand | The recognized device brand, or null. |
| device_model | The recognized device model, or null. Generic iPhone, iPad and iPod labels and the Android placeholder K are unavailable models. |
| os_name | The recognized operating system name, or null. |
| browser_name | The recognized browser name, or null. |
| language | The preferred valid language tag from Accept-Language, respecting quality weights, or null. |
| referrer_url | The full supplied HTTP(S) Referer, including its path and query, or null. |
| screen_width_css, screen_height_css | Browser-reported screen width and height in CSS pixels, or null. |
| device_pixel_ratio | The browser-reported device pixel ratio (DPR), or null. |
| screen_width_px, screen_height_px | Estimated physical screen dimensions, calculated as floor(CSS size × DPR + 0.5), or null. These are estimates, not verified hardware specifications. |
Device and visit metadata
These fields describe supplied request information from User-Agent, Accept-Language, UA Client Hints and HTTP Referer. They do not verify a physical device or a human visitor. A browser, app, proxy or automated client can omit, reduce or change this information. Parsing failures preserve the click and any independently available fields.
Older history can have no device information. Missing device types are "unknown"; other unavailable fields are explicitly null. Screen dimensions are collected only when the link owner enables collectScreen. They are reported by the browser and do not verify hardware. IP classification is not collected. Raw request headers and dictionary identifiers are not exposed by the API.
The dashboard history API includes these same device, visit and nullable screen fields. Open Device & visit details beneath a historical link to view them. Search results contain the entire latest visit snapshot that satisfies your criteria; unavailable fields stay unavailable rather than inheriting values from other visits.
Optional screen collection
Screen collection is off by default for existing and new links. Enable Collect screen dimensions when creating or editing a dashboard link, or send the boolean collectScreen in the authenticated link API:
POST /api/dashboard/links
{
"slug": "screen-demo",
"targetUrl": "https://example.com/",
"collectScreen": true
}With PATCH /api/dashboard/links/:id, omit collectScreen to preserve the saved setting or send false to disable it. Nonboolean values return 400. Creation, editing and listing responses include collectScreen.
An enabled link serves a small intermediate page only for GET requests whose Accept header explicitly permits text/html. Its script reads screen.width, screen.height and devicePixelRatio, sends the measurements in the background and immediately opens the destination without waiting for a collector response. A separate refresh redirects after one second when JavaScript is unavailable, and a manual destination link is provided. Other GET requests and all HEAD requests keep the usual 302 response; HEAD does not record a click.
Measurements are browser-reported data. Physical screen resolution is an estimate, and collection and delivery are not guaranteed. Missing or invalid measurements leave all five screen fields null. No measurement delivery increments clicks or API checks. Screen measurements follow the original click’s 365-day retention and account history erasure; unmatched measurements are removed after 24 hours.
Manage and search tags
Create or edit a link in the dashboard using the comma-separated Tags field, for example wakeo, promo. The authenticated link API accepts tags as a JSON array:
POST /api/dashboard/links
{
"slug": "wakeo.rey",
"targetUrl": "https://example.com/wakeo",
"tags": ["wakeo", "promo"]
}New links default to []. With PATCH /api/dashboard/links/:id, omit tags to keep existing values, supply an array to replace them, or use {"tags": []} to clear them. Listing, creation and editing responses include saved tags. Link writes require an array; a comma-separated string is only accepted for search.
Tags trim surrounding whitespace, normalize Unicode to NFC, convert to lowercase, remove duplicates and sort. Use Unicode letters and digits, hyphens and underscores. Internal whitespace, commas within a tag, empty entries, other characters and non-string values are invalid. Use at most 20 distinct normalized tags, with at most 64 Unicode characters per normalized tag.
GET https://iink.click/api/v1/check?tags=wakeo
GET https://iink.click/api/v1/check?tags=wakeo,promo&tags_match=or
GET https://iink.click/api/v1/check?ip_address=203.0.113.42&tags=wakeo&os_name=Android
Authorization: Bearer <api_key>The default tags_match=and requires all requested tags; tags_match=or requires at least one. Other criteria still combine with AND. Unsupported matching modes, tags_match without tags, tags= and empty comma-separated entries return 400 without consuming a check.
Tag search uses each link’s current tags for all of its retained clicks. Editing tags immediately changes which past clicks are discoverable. Deleting a link preserves its tags and unexpired click history, so it can still appear in tag searches. Click URLs, destinations and visit metadata remain the values recorded at the time of each click.
Find matching clicks
Add any of these optional query parameters: device_brand, device_type, device_model or os_name. All supplied filters must match. Matches are exact and case-sensitive after surrounding whitespace is trimmed; for example, Samsung and samsung are different values.
GET https://iink.click/api/v1/check?ip_address=203.0.113.42&device_brand=Samsung&device_type=smartphone&device_model=Galaxy%20S23&os_name=Android
Authorization: Bearer <api_key>The API returns every retained click that satisfies your filters, including repeated clicks on the same link. For example, os_name=Android returns all matching Android visits. Your client decides whether to use the newest click or another subset. With no IP criterion, events can match across different IPs. Equal timestamps use event ID as a deterministic tie-breaker. device_type=unknown includes legacy visits without device type information. Unavailable brand, model and OS names cannot match name filters.
Each supplied filter must contain 1–256 characters after trimming and must not contain a null byte. Blank or invalid filter values return 400 without consuming an API check. A valid lookup with no matches returns [] and consumes the usual check.
Use clicked_from_utc and clicked_to_utc to filter matching events by time. Both bounds are inclusive, and either can be supplied alone. Send a UTC timestamp in YYYY-MM-DDTHH:mm:ssZ format, with optional 1–3 fractional second digits. Surrounding whitespace is trimmed. Invalid timestamps, non-UTC offsets or a start later than the end return 400 without consuming an API check. All visits inside the range that satisfy every criterion are returned.
GET https://iink.click/api/v1/check?ip_address=203.0.113.42&clicked_from_utc=2026-10-11T11:00:00Z&clicked_to_utc=2026-10-11T12:00:00Z
Authorization: Bearer <api_key>Search by estimated screen resolution
GET https://iink.click/api/v1/check?screen_resolution=1170x2532
GET https://iink.click/api/v1/check?tags=wakeo&screen_resolution=1170x2532&os_name=Android
Authorization: Bearer <api_key>screen_resolution is sufficient as the only criterion, and combines with all other criteria using AND. Use positive integer sides from 1 to 524288, separated by x, X or ×. Surrounding whitespace is ignored. Side order is normalized, so 2532x1170 matches the same resolution as 1170x2532, including a rotated screen. URL-encode spaces and the multiplication sign when needed.
Matching uses the estimated physical pixel dimensions exactly, without a range or tolerance. Events without measurements do not match. Every click with matching measurements is returned, including older and repeated visits. Invalid resolutions return 400 without consuming an API check.
Continue through results
A page contains up to 100 records. If another page is available, the response includes an X-Next-Cursor header. Results are ordered by click time descending, with descending event ID for equal timestamps. Continuation tracks individual events, including repeated clicks on one link. Pass the opaque cursor value in the next request with every original criterion and the same effective tag matching mode. Cursors bind your account, history generation, search-contract version, optional canonical IP and normalized filters, including tags, normalized screen resolution and both time bounds. Reordered tags, duplicate tags and equivalent casing are accepted; omitted tags_match and explicit and are equivalent. Swapping screen-resolution sides is equivalent; adding, removing or changing the normalized resolution invalidates the cursor before a check is charged. Preserve every time bound; equivalent fractional second precision is accepted. Adding, removing or changing criteria or matching mode invalidates the cursor before charging.
GET /api/v1/check?ip_address=203.0.113.42&device_brand=Samsung&device_type=smartphone&device_model=Galaxy%20S23&os_name=Android&cursor=<url_encoded_cursor>Do not derive meaning from or modify cursor values. Cursors expire after 15 minutes. History erasure and cursors issued under the previous search contract also invalidate continuation. Each valid page is a separate API check, including an empty result. No continuation header means you have reached the end.
Pages read current data, so new clicks and tag edits between requests can change results or which links match. Pagination does not provide a frozen snapshot.
Handle status codes
| Status | What to do |
|---|---|
| 200 | Read the array and check the continuation header. |
| 400 | Supply at least one criterion and check the supplied IP, tags, matching mode, device/screen/time values and cursor. Preserve the same normalized criteria and effective tag mode on continuation. Invalid requests do not consume a check. |
| 401 | Provide a valid, active Bearer key. |
| 429 | The monthly API allowance is exhausted. Wait for the next UTC month or upgrade. |
Know what the result represents
- Only your own account’s events are returned.
- History expires 365 days after the click, even when physical storage cleanup is still pending.
- Deleting a link preserves its tags and unexpired history. Explicitly erasing history removes the events from search immediately.
- Results normally appear within five minutes. Click collection happens after the redirect response; a failure before the queue accepts the event can lose that click.
- This endpoint returns all matching clicks with up to 100 events per page. Follow
X-Next-Cursorto retrieve the remaining events.
Allowances
Free includes 500 checks per calendar month. Pro includes 10,000. Months start at 00:00 UTC on the first day. The click threshold is separate from your API allowance and does not stop redirects or recording.
Create an API key