A URL shortener API lets your application create and manage short links through HTTP requests. Before integrating, check authentication, request limits, link ownership and what you can export. A free website interface does not necessarily include free API access: 302.sh public API access starts on Creator, while Free provides a separate dashboard allowance.
This guide uses the current 302.sh API reference and its OpenAPI contract. It covers a backend integration, not building your own redirect service or ranking providers. If you are still comparing services, use the separate URL shortener API comparison guide and verify each provider's current contract.
Create a token for the correct workspace
- Choose a plan with public API access and select the workspace that should own the links.
- Create a token in Dashboard → API tokens. Save its full value securely when it is shown.
- Store it in your backend's secret store or server environment. Send it as
Authorization: Bearer tok_...over HTTPS. - Verify access with a read request before adding link creation to a production job.
A token is bound to its workspace. A bearer request cannot switch workspaces using X-Workspace-Id. Tokens read their workspace's resources and can manage its short links; publishing a hosted bio page additionally requires bio:write. Do not invent a links:write scope or assume a token is restricted to one campaign.
Keep personal API tokens out of browser JavaScript, mobile app bundles, screenshots, source control and shared URLs. The OWASP REST Security Cheat Sheet recommends HTTPS and keeping credentials out of URLs, where they can appear in logs. If a token leaks, revoke it in the dashboard and replace the server secret. Token-management endpoints require a signed-in session; an API token cannot mint its own replacement.
curl --fail-with-body --silent --show-error \
'https://302.sh/api/links?limit=1' \
-H "Authorization: Bearer $SHORTLINK_API_TOKEN"This read-only check verifies access to the token's workspace. It does not prove that a later create request fits your plan, hostname configuration or link allowance.
Create one link and read it back
The create endpoint is POST /api/links. Its required JSON field is target. Optional slug chooses the path; optional host selects an allowed hostname, such as an active verified custom domain. Omitting the host currently creates links on 3go.to. The API base remains https://302.sh.
A successful create returns HTTP 201 with a link object. Store its id, host, slug and target. Build the public address from the returned host and slug, rather than assuming it shares the API's hostname. Use the ID for GET, PATCH and DELETE /api/links/{id}.
// Save as create-link.mjs; run on your backend with Node.js 22+.
// This creates one account-owned link when you run it.
const token = process.env.SHORTLINK_API_TOKEN;
if (!token) throw new Error("Set SHORTLINK_API_TOKEN in your server environment");
const base = "https://302.sh";
const headers = {
Authorization: "Bearer " + token,
"Content-Type": "application/json",
};
const created = await fetch(base + "/api/links", {
method: "POST",
headers,
body: JSON.stringify({ target: "https://example.com" }),
signal: AbortSignal.timeout(15000),
});
const result = await created.json();
if (created.status !== 201) {
throw new Error("Create failed: " + created.status + " " + result.error);
}
const link = result.link;
const shortURL = "https://" + link.host + "/" + link.slug;
// Persist this mapping in your application before distributing the URL.
console.log(JSON.stringify({ id: link.id, shortURL, target: link.target }));
const read = await fetch(base + "/api/links/" + encodeURIComponent(link.id), {
headers,
signal: AbortSignal.timeout(15000),
});
if (!read.ok) throw new Error("Read failed: " + read.status);
const saved = await read.json();
if (saved.link.target !== link.target) throw new Error("Target changed; inspect link");
console.log("Readback matches the created target");This example makes a real create request if you run it with your token. Its contract was checked against the actual handler and local test fixtures; it is not a transcript of a production request. No example response IDs or success results are presented as live observations.
For an application, persist the returned mapping in durable storage before marking the job complete. The example prints it for inspection. If creation succeeds but readback fails, retain that ID and retry the read separately. Rerunning the entire script creates another link. A timeout means the response was not obtained; it does not establish that the server created nothing.
To replace a destination later, send {"target":"https://example.com/new-page"} to PATCH /api/links/{id}, then read it back. Preserve the hostname and slug if the public address must stay unchanged. Test the short URL separately from API readback; doing so may create a recorded visit.
Separate API requests, link allowances and analytics
| Plan | Public API requests / token / UTC day | Owned links | Recorded analytics events / month |
|---|---|---|---|
| Free | No public API access | 50 | 2,000 |
| Creator | 10,000 | 500 | 25,000 |
| Pro | 100,000 | 5,000 | 250,000 |
| Business | 500,000 | 25,000 | 2,000,000 |
Free also limits new dashboard links to 5 per UTC month. Paid plans currently have no monthly creation ceiling, but still limit how many links a workspace can own. Deleting a Free link does not refund its monthly creation allowance. Check current plans before choosing an integration tier.
API requests are counted per token per UTC day, including requests that pass authentication and quota checks but fail later. One created link can therefore consume several API requests as you create, read, update and inspect it. A daily-limit response is 429 with error: "rate_limited" and a Retry-After header indicating the wait until reset.
The analytics allowance counts recorded events, not API requests or unique people. Reaching it stops additional tracking for the period; that allowance alone does not stop redirects. Deletion, expiration, owner-set restrictions and safety enforcement can still prevent a redirect. Link analytics also do not establish purchases, registrations or unique visitors; see why link visits and website sessions differ.
Handle errors without creating duplicate links
| Response or failure | What to do |
|---|---|
| 401 | Check that the correct, unrevoked bearer token reached the server. Do not log its value. |
| 402 public_api_requires_creator | Check the workspace's plan. Dashboard Free access is not public API entitlement. |
| 402 link_limit_reached | Inspect owned-link usage. Review obsolete links or change plan; do not delete active campaign URLs blindly. |
| 400 target_url_invalid | Correct the destination. Repeating the same invalid request will not fix it. |
| 409 slug_taken | Inspect the exact host and slug. A conflict does not prove that your earlier request succeeded or that you own the existing link. |
| 429 | Inspect the error code and Retry-After. Daily quota and other safety limits are different causes; avoid a tight retry loop. |
| Timeout or lost create response | Reconcile the job against existing workspace links before sending another POST. |
The current create API does not document an Idempotency-Key contract. Do not assume that sending such a header deduplicates requests. HTTP semantics in RFC 9110 explain why automatic retries of non-idempotent requests require knowledge that retrying is safe or that the original request was not applied.
For a queued integration, save a job-to-link mapping as soon as you receive the response. If you requested a known slug, inspect your workspace's links for the exact hostname, slug and target after an uncertain result. Search results and a 409 are clues, not ownership proof. Without a reliable reconciliation match, stop the job for review instead of silently generating a second public URL.
Retry read requests separately with a bounded delay. For daily quota exhaustion, honor the returned wait rather than rotating tokens to evade the limit. Keep status, error code and your internal job ID in logs, with credentials redacted.
What can you take with you when you migrate?
Owning a link record is different from controlling its public domain. A short address on a provider's shared hostname stays dependent on that provider. A custom domain you control can support a move only if the replacement also serves the same paths and you complete its domain and TLS setup.
| Asset | What to preserve | 302.sh export boundary |
|---|---|---|
| Basic link mapping | Slug, target, expiry and comment. | Bulk export includes these fields. Follow cursor pagination until list_complete. |
| Exact public URL | Hostname plus path, with domain control where migration is required. | Bulk export omits the hostname. Save the host from full link records separately; a slug alone is insufficient. |
| Passwords and routing | Required access rules and device, country or split destinations. | Bulk export indicates password protection but does not export the password or provide a full routing backup. Review configuration separately. |
| Historical analytics | Reports and their date range and counting rules. | Bulk link export does not contain analytics. Retain needed reports separately; importing links does not transfer their history. |
GET /api/links/bulk-export is a paginated basic mapping export, not a full recovery snapshot. Pause your own automated edits during an export and verify the final mapping because paginated reads are not a transaction snapshot. Bulk import starts on Pro. Inspect each import result: a successful HTTP response can contain rows that were skipped or conflicted.
Before moving traffic, compare the exact host/path/target map, test access restrictions and keep a rollback destination. The short-link migration guide covers preserving public addresses. Never infer that exporting a provider-hosted slug gives you control of that provider's hostname.
Before connecting a production job
- Confirm the selected workspace, API entitlement and token storage; test a read request.
- Create one authorized test link, persist its returned identity and verify its destination.
- Exercise invalid input and quota handling in a local fixture or controlled test setup. Do not intentionally exhaust production limits.
- Separate create from read retries, and define who reviews an uncertain create result.
- Save complete public URL mappings and identify what an export cannot restore.
A reliable integration can explain which link a job created, why a request failed and what remains portable if the service changes. Those checks matter more than the number of API calls in a demo.
What is included in 302.sh?
Free allows 5 new links per UTC month and up to 50 owned links, with 5 custom slugs per month of at least 6 characters. Deleting a link does not refund its monthly creation allowance.
Free includes 2,000 analytics events per month and 90-day retention. Reaching that analytics allowance stops additional tracking, not redirects. Link deletion, owner-set limits and safety enforcement can still stop redirects. Branded domains require a paid plan and completed domain setup. See current plans and limits.
Try the workflow
Explore the dashboard demo, or create a short link using a destination you own or are authorized to share. Verify the destination before distributing it.



