01Quick start
- Create an API key in the API keys section below. It starts with
wpl_and is shown once. - Save it as an environment variable on your server or in CI:
export WARPLO_API_KEY=wpl_your_key_here - Shorten a link from Node, or straight from your terminal:
import { Warplo } from "warplo"; const warplo = new Warplo(); const link = await warplo.create({ url: "https://example.com/spring-sale", slug: "spring" }); console.log(link.shortUrl); // https://warplo.link/springnpx warplo https://example.com/spring-sale --slug spring
02API keys
Keys act as your account, so keep them secret. Use them from servers, scripts and CI, never in a web page or an app people can download. If a key leaks, delete it here and it stops working straight away.
Sign in to create keys
Use your Google account. API keys are free: one key and 100 calls a day on Free, ten keys and 10,000 calls a day on Pro.
Continue with GoogleChecking your account…
Your keys
–COPY IT NOW · SHOWN ONCE
Need more keys or calls? Upgrade to Pro for 10 keys and 10,000 calls a day.
03npm package
The warplo package has no dependencies and is fully typed. The SDK only needs fetch, which is built into Node 18 and later.
import { Warplo, WarploError } from "warplo";
const warplo = new Warplo({ apiKey: process.env.WARPLO_API_KEY });
// Shorten, with an optional ending and expiry
const link = await warplo.create({ url: "https://example.com/page", slug: "launch", expiresInDays: 30 });
// Just the short URL
const short = await warplo.shorten("https://example.com/other");
// Every link, page by page
for await (const l of warplo.links()) console.log(l.slug, l.url);
// Clicks by day and country (30 days by default, up to 90 on Free and 365 on Pro)
const stats = await warplo.stats("launch", { days: 90 });
// Delete
await warplo.delete("launch");
// Errors have a code you can check
try {
await warplo.create({ url: "https://example.com", slug: "launch" });
} catch (err) {
if (err instanceof WarploError && err.code === "slug_taken") {
// try another slug
}
}
// Calls left today, updated after each request
console.log(warplo.rateLimit); // { limit: 100, remaining: 96 }
| Method | Returns |
|---|---|
create({ url, slug?, expiresInDays? }) | The new link: slug, shortUrl, url, expiresAt |
shorten(url, options?) | The short URL as a string |
list({ cursor? }) | One page of up to 50 links and the next cursor |
links() | An async iterator over every link |
stats(slug, { days? }) | total, days, byDay, byCountry |
delete(slug) | Nothing; the link stops working |
me() | Your plan, limits and link count |
04Command line
The same package includes a warplo command. It reads your key from WARPLO_API_KEY, or pass --key. Add --json for machine-readable output.
npx warplo https://example.com/a/very/long/page
npx warplo shorten example.com/launch --slug launch --expires 30
npx warplo list
npx warplo stats launch --days 90
npx warplo delete launch
npx warplo whoami
05REST API
Any language works. Send JSON to https://warplo.link with your key in the Authorization header. Every response says how many calls you have left today in X-RateLimit-Limit and X-RateLimit-Remaining.
curl https://warplo.link/api/links \
-H "Authorization: Bearer $WARPLO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/page","slug":"launch","expiresInDays":30}'
{
"slug": "launch",
"shortUrl": "https://warplo.link/launch",
"url": "https://example.com/page",
"expiresAt": 1795219200
}
| Request | What it does |
|---|---|
POST /api/links | Creates a link. Body: url (required), slug (3 to 32 letters, numbers, - or _), expiresInDays (1 to 3650). Returns 201. |
GET /api/links | Your links, newest first, 50 at a time. Pass ?cursor= from the last response to get the next page. |
GET /api/links/:slug/stats | Clicks by day and country. ?days= sets the range: 30 by default, up to 90 on Free and 365 on Pro. |
DELETE /api/links/:slug | Deletes a link and its click counts. Returns 204. |
GET /api/me | The account behind the key: plan, limits and how many active links you have. |
Each destination is checked against phishing and malware lists before the link is saved. Expiry times are Unix seconds; null means the link never expires.
06Limits
| Free | Pro · $5/month | |
|---|---|---|
| Active links | 50 | Unlimited |
| Click history | 90 days | 1 year |
| API keys | 1 | 10 |
| API calls a day | 100 | 10,000 |
| New links a minute | 20 | 20 |
Daily calls reset at midnight UTC. Links created through the API count towards the same link limit as the dashboard. Need more? Upgrade to Pro or talk to us.
07Errors
Errors come back as JSON with an error code, and a limit when you've hit one: {"error":"link_limit","limit":50}. The npm package throws them as WarploError with the same code.
| Status · code | Meaning |
|---|---|
400 invalid_url | Not an http or https address, or it points back to warplo |
400 invalid_slug | The slug has the wrong characters or length, or is reserved |
400 invalid_expiry | expiresInDays isn't a whole number from 1 to 3650 |
401 invalid_api_key | The key is missing, wrong or deleted |
403 link_limit | You've reached your plan's active link limit |
403 history_limit | days is longer than your plan's click history |
404 not_found | No link with that slug on your account |
409 slug_taken | Someone already uses that slug |
422 unsafe_url | The destination is on a phishing or malware list |
429 rate_limited | More than 20 new links in a minute |
429 api_quota_exceeded | Today's API calls are used up |
503 safety_check_unavailable | The safety check couldn't run, so nothing was saved. Retry shortly |