API Reference
A RESTful HTTP API that lets any platform programmatically create direct and in-page safety links, manage existing links, and retrieve analytics — all authenticated with a personal API key tied to your Klook Up account.
Contents
Quick Start
Up and running in under 2 minutes.
Step 1
Create an account
Register for a free Klook Up account. An active profile is required before an API key can be issued.
Step 2
Generate an API key
Go to Settings › API Keys, give your key a name (e.g. My App), and click Generate. Copy the klup_… token — it is shown only once.
Step 3
Make your first request
Send a POST with your Bearer token and destination URL. Receive a short link in milliseconds.
Minimal working example
curl -X POST https://klookup.com/api/v1/links \
-H "Authorization: Bearer klup_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"url":"https://your-site.com/landing","type":"direct"}'Base URL
https://klookup.com/api/v1All v1 API endpoints are relative to this base URL. All requests and responses use JSON. TLS (HTTPS) is required — plain HTTP requests will be rejected.
Authentication
Every request must carry a valid API key issued to a registered user.
Bearer Token
Pass your API key in the Authorization header using the Bearer scheme:
Authorization: Bearer klup_a1b2c3d4…64hexchars Content-Type: application/json
Key Format
All Klook Up API keys follow this format:
klup_<64 lowercase hexadecimal characters>
Keys contain 256 bits of cryptographic randomness. Only a SHA-256 hash is stored server-side — the plaintext key is shown to you once only at creation time.
Account required
API keys can only be issued to registered and logged-in users. You may hold up to 10 active keys per account. Revoke unused keys from Settings › API Keys.
Request & Response Format
Requests
- Send request bodies as JSON with
Content-Type: application/json. - All strings must be UTF-8 encoded.
- Dates must be ISO-8601 strings (e.g.
2026-12-31T23:59:59Z). - Boolean-style flags use integers:
1= true,0= false.
Successful Response envelope
HTTP 200 or 201:
{
"success": true,
"data": { ... } // returned resource or array
}Error Response envelope
{
"success": false,
"error": "Human-readable message",
"details": { ... } // optional: per-field validation errors
}Error Handling
Klook Up uses standard HTTP status codes.
| HTTP Status | Meaning | Common cause |
|---|---|---|
200 OK | Success | Request processed successfully |
201 Created | Resource created | A new link or API key was created |
400 Bad Request | Validation error | Missing / invalid field in request body |
401 Unauthorized | Missing or invalid API key | No Authorization header, or key is revoked |
403 Forbidden | Access denied | You don't own the resource you are trying to modify |
404 Not Found | Resource missing | Link ID does not exist or belongs to another user |
405 Method Not Allowed | Wrong HTTP method | Using GET where POST is required, etc. |
429 Too Many Requests | Rate limit hit | Exceeded anonymous limit (5 creations / 24 h) |
500 Internal Server Error | Server error | Unexpected server-side failure — contact support |
Link Types
Klook Up supports two modes of link delivery.
direct
A standard short-link redirect. When a visitor opens klookup.com/<code> they are immediately forwarded to the target URL. This is the default mode.
inpage
An in-page safety preview. Visitors land on a Klook Up-hosted interstitial at klookup.com/<code>/page that shows the destination, your title, description, and a captcha before forwarding. Ideal for platforms sharing external links to protect their audience.
Endpoints
Create a Link
Create a new short link (direct or in-page). The link is immediately active and associated with your account.
/linksRequest Body Parameters
| Field | Type | Default | Description |
|---|---|---|---|
urlrequired | string | — | The destination URL. Must use http:// or https://. |
type | "direct" | "inpage" | "direct" | Delivery mode. Use "inpage" for the captcha safety preview. |
post_idrequired | string | — | Required when type is "inpage". The unique identifier of the post or page on YOUR website (e.g. a CMS post ID, UUID, or slug). Enforces one active inpage link per post_id per account — repeated calls with the same post_id return the existing link (HTTP 200) instead of creating a duplicate. The API will return a validation error if this is omitted for an inpage link. |
title | string | null | Optional title displayed on the in-page preview. Max 200 characters. |
description | string | null | Optional description on the in-page preview. Max 500 characters. |
expires_at | ISO-8601 string | null | Date/time when the link stops working. Omit for a permanent link. |
site_url | string | null | Your website page URL where this inpage link is embedded. Only valid when type is "inpage". Used for automatic site verification — if the link is not found on the page, deletion is scheduled after 24 hours. |
Request — direct link
POST /api/v1/links
Authorization: Bearer klup_…
{
"url": "https://example.com/article",
"type": "direct",
"title": "Read the full article"
}Request — in-page link
POST /api/v1/links
Authorization: Bearer klup_…
{
"url": "https://example.com/file.zip",
"type": "inpage",
"post_id": "post_789",
"title": "Download our app",
"description": "Verified safe by Klook Up",
"site_url": "https://yoursite.com/downloads"
}Response — 201 Created
{
"success": true,
"data": {
"id": 42,
"short_code": "aBc1234",
"short_url": "https://klookup.com/aBc1234", // direct
// "short_url": "https://klookup.com/aBc1234/page" // inpage
"target_url": "https://example.com/article",
"type": "direct",
"title": "Read the full article",
"description": null,
"expires_at": null,
"post_id": null,
"site_url": null,
"site_verified_at": null,
"created_at": "2026-02-22T10:00:00Z"
// "existing": true ← present (and true) only when a pre-existing link was returned
}
}List Links
Returns a paginated list of all links belonging to your account, sorted newest first.
/links?page=1&limit=20Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based). |
limit | integer | 20 | Results per page. Max 100. |
Response — 200 OK
{
"success": true,
"data": {
"links": [
{
"id": 42,
"short_code": "aBc1234",
"target_url": "https://example.com/article",
"link_type": "direct",
"title": "Read the full article",
"clicks": 317,
"views": 420,
"is_active": 1,
"expires_at": null,
"created_at": "2026-02-22T10:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total_count": 150,
"total_pages": 8,
"has_more": true
}
}
}Get Link + Statistics
Retrieve full details and click analytics for a single link you own.
/links/:idResponse — 200 OK
{
"success": true,
"data": {
"link": {
"id": 42,
"short_code": "aBc1234",
"target_url": "https://example.com/article",
"link_type": "direct",
"title": "Read the full article",
"clicks": 317,
"views": 420,
"is_active": 1,
"expires_at": null,
"created_at": "2026-02-22T10:00:00Z",
"updated_at": "2026-02-22T11:00:00Z"
},
"stats": {
"total_clicks": 317,
"clicks_by_country": { "PH": 120, "US": 80, "GB": 50 },
"clicks_by_device": { "mobile": 200, "desktop": 100, "tablet": 17 },
"clicks_by_browser": { "Chrome": 210, "Safari": 80, "Firefox": 27 },
"recent_clicks": [
{ "date": "2026-02-22", "count": 45 },
{ "date": "2026-02-21", "count": 62 }
]
}
}
}Update a Link
Update any field of a link you own. Only the fields you include will be changed (partial update supported).
/links/:idUpdatable Fields
| Field | Type | Default | Description |
|---|---|---|---|
url | string | — | New destination URL. |
type | "direct" | "inpage" | — | Change delivery mode. |
title | string | null | — | Update the title. Pass null to remove. |
description | string | null | — | Update the description. Pass null to remove. |
is_active | 0 | 1 | — | Disable (0) or re-enable (1) the link. |
expires_at | ISO-8601 | null | — | Set or clear the expiry date. |
Request
PUT /api/links/42
Authorization: Bearer klup_…
{
"title": "Updated article title",
"is_active": 1,
"expires_at": "2026-06-30T23:59:59Z"
}Response — 200 OK
{
"success": true,
"data": {
"id": 42,
"short_code": "aBc1234",
"title": "Updated article title",
"is_active": 1,
"expires_at": "2026-06-30T23:59:59Z",
"updated_at": "2026-02-22T12:30:00Z"
}
}Delete a Link
Permanently deletes a link and all its click logs. This action cannot be undone.
/links/:idResponse — 200 OK
{
"success": true,
"data": { "message": "Link deleted successfully" }
}In-Page Safety Link Guide
How the inpage type protects your audience end-to-end.
How it works
- Your platform calls
POST /api/v1/linkswith"type":"inpage". - Klook Up returns a
short_urlending with/page. - You share that URL with your audience (embed in a message, email, or web page).
- The visitor opens the URL and sees a branded preview page on klookup.com showing the destination domain, your title, and description.
- They complete a Cloudflare Turnstile captcha (no user-visible puzzle — usually just a checkbox).
- After passing, they click Continue to Website to proceed to the destination.
Full curl example
curl -X POST https://klookup.com/api/v1/links \
-H "Authorization: Bearer klup_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/sensitive-download.zip",
"type": "inpage",
"post_id": "post_42",
"title": "Download: Example App v2.0",
"description": "This file has been verified safe by our team."
}'Response
{
"success": true,
"data": {
"id": 99,
"short_code": "xYz5678",
"short_url": "https://klookup.com/xYz5678/page",
"target_url": "https://example.com/sensitive-download.zip",
"type": "inpage",
"title": "Download: Example App v2.0",
"description": "This file has been verified safe by our team.",
"expires_at": null,
"post_id": "post_42",
"site_url": "https://example.com/sensitive-download.zip",
"site_verified_at": null,
"created_at": "2026-02-22T12:00:00Z"
}
}The short_url ends with /page — that is the safety preview URL to share with your audience.
When to use in-page links
- Sharing download links (files, APKs, PDFs) from external storage
- Redirecting community members to third-party websites you don't fully control
- Services that want to give users a heads-up before navigating away
- Affiliate or referral programs where a preview builds visitor confidence
- Any situation where you want bot/automation filtering before sending traffic
Automatic Site Verification
When you pass site_url pointing to the page where your inpage link is embedded, Klook Up enforces a one active inpage link per site_url rule per account. If you call POST /api/v1/links again with the same site_url, the existing link is returned (HTTP 200 with "existing": true) — no duplicate is created. Klook Up will also automatically verify that the link remains active on your website.
- Klook Up periodically fetches
site_urlusing its built-in crawler. - It searches the page HTML for your inpage link's
short_code. - If found,
site_verified_atis updated and the link remains active. - If not found,
scheduled_deletion_atis set to 24 hours from that check. - If the next verification still finds the link missing and the 24-hour window has passed, the link is permanently deleted.
- Removing the inpage link from your page and forgetting to delete it via the API will therefore result in automatic cleanup.
Best practice: always delete links you no longer use via the dashboard or DELETE /api/v1/links/:id rather than simply removing them from your page.
Rate Limits
Limits are applied per API key or per IP for unauthenticated access.
| Context | Limit | Window | Scope |
|---|---|---|---|
| Authenticated (API key) | Unlimited | — | Per API key |
| Authenticated (session) | Unlimited | — | Per user account |
| Anonymous (no key) | 5 link creations | 24 hours | Per IP address |
Rate limit response
Only anonymous (unauthenticated) requests can be rate-limited. If an anonymous caller exceeds 5 creations in 24 hours they receive 429 Too Many Requests:
{
"success": false,
"error": "Rate limit exceeded. Try again after 2026-02-23T10:00:00Z"
}Authenticated requests (Bearer API key or logged-in session) are unlimited.
Code Examples
Copy-paste snippets for the most common use-cases.
cURL — create an in-page link
curl -X POST https://klookup.com/api/v1/links \
-H "Authorization: Bearer klup_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-destination.com",
"type": "inpage",
"title": "Visit our partner site",
"description": "This link has been reviewed by our team."
}'JavaScript (fetch)
const API_KEY = process.env.KLOOKUP_API_KEY; // klup_…
async function createInPageLink(url, title, description) {
const res = await fetch("https://klookup.com/api/v1/links", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url,
type: "inpage",
title,
description,
}),
});
if (!res.ok) {
const err = await res.json();
throw new Error(err.error ?? "Failed to create link");
}
const { data } = await res.json();
return data.short_url; // "https://klookup.com/xYz5678/page"
}
const safeLink = await createInPageLink(
"https://example.com/file.zip",
"Download Example App",
"Verified safe — click proceed to download."
);
console.log(safeLink);TypeScript — reusable client
interface CreateLinkOptions {
url: string;
type?: "direct" | "inpage";
/** Required when type is "inpage" — unique ID of the post/page on your site */
post_id?: string;
title?: string;
description?: string;
expires_at?: string; // ISO-8601
/**
* Your website URL where this inpage link will be embedded.
* Triggers automatic site verification — the link is deleted after 24 h
* if Klook Up cannot find it on the page.
*/
site_url?: string;
}
interface KlookUpLink {
id: number;
short_code: string;
short_url: string;
target_url: string;
type: "direct" | "inpage";
post_id?: string | null;
site_url?: string | null;
site_verified_at?: string | null;
created_at: string;
/** true when post_id was provided and an existing link was returned instead of creating a new one */
existing?: boolean;
}
class KlookUpClient {
constructor(private readonly apiKey: string) {}
async createLink(opts: CreateLinkOptions): Promise<KlookUpLink> {
const res = await fetch("https://klookup.com/api/v1/links", {
method: "POST",
headers: {
Authorization: `Bearer ${this.apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(opts),
});
const body = await res.json() as { success: boolean; data: KlookUpLink; error?: string };
if (!res.ok || !body.success) throw new Error(body.error ?? "API error");
return body.data;
}
}
// Usage
const client = new KlookUpClient(process.env.KLOOKUP_API_KEY!);
const link = await client.createLink({
url: "https://example.com",
type: "inpage",
title: "Our partner site",
});
console.log(link.short_url);Python (requests)
import os
import requests
API_KEY = os.environ["KLOOKUP_API_KEY"] # klup_…
BASE_URL = "https://klookup.com/api/v1"
def create_link(url: str, link_type: str = "direct", **kwargs) -> dict:
"""
Create a Klook Up short link.
link_type: "direct" or "inpage"
kwargs: post_id (required for inpage), title, description, expires_at, site_url
"""
payload = {"url": url, "type": link_type, **kwargs}
response = requests.post(
f"{BASE_URL}/links",
json=payload,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
timeout=10,
)
response.raise_for_status()
return response.json()["data"]
# Create an in-page safety link
link = create_link(
url="https://example.com/confidential.pdf",
link_type="inpage",
title="Confidential Document",
description="Please verify you are authorised before proceeding.",
)
print(link["short_url"]) # https://klookup.com/xYz5678/pagePHP (cURL)
<?php
function klookup_create_link(string $apiKey, array $payload): array {
$ch = curl_init("https://klookup.com/api/v1/links");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $apiKey",
"Content-Type: application/json",
],
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$json = json_decode($body, true);
if ($status >= 400 || !$json['success']) {
throw new RuntimeException($json['error'] ?? 'API error');
}
return $json['data'];
}
$link = klookup_create_link(getenv('KLOOKUP_API_KEY'), [
'url' => 'https://example.com/download',
'type' => 'inpage',
'title' => 'Download our software',
'description' => 'Verified safe by our security team.',
]);
echo $link['short_url']; // https://klookup.com/xYz5678/pageAPI Key Security
Store keys as environment variables
Never hard-code API keys in source files or commit them to version control. Use environment variables (e.g. KLOOKUP_API_KEY) or a secrets manager.
Use server-side only
API keys must never be included in client-side JavaScript, mobile app binaries, or public HTML. All requests should originate from your backend server.
Rotate keys regularly
Create a new key, update your environment variables, then revoke the old key from Settings › API Keys. Rotation limits exposure if a key is ever compromised.
One key per application
Issue a separate key for each integration or environment (staging vs production). This allows you to revoke access for a single app without disrupting others.
Monitor last-used timestamps
Each key tracks its last-used timestamp in Settings › API Keys. If you see activity for a key you no longer use, revoke it immediately.