Every sample below calls POST https://api.blinkhop.com/v1/links and needs no API key. They are tested as written. For the full list of fields and error codes, see the API reference.
cURL
# Create a short link
curl https://api.blinkhop.com/v1/links \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/a/very/long/link"}'
# Choose the ending
curl https://api.blinkhop.com/v1/links \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/spring", "alias": "spring-sale"}'
# Get only the short URL, as plain text
curl -s "https://api.blinkhop.com/v1/links?format=text" \
--data-urlencode "url=https://example.com/report?q=3&y=2026"
# See where a short link goes
curl "https://api.blinkhop.com/v1/expand?url=https://zou.sh/spring-sale"
Shell function
Add this to ~/.bashrc or ~/.zshrc, open a new terminal, then run shorten https://example.com/long/link:
shorten() {
curl -fsS "https://api.blinkhop.com/v1/links?format=text" --data-urlencode "url=$1"
}
Pipe it to your clipboard: shorten https://example.com | pbcopy on macOS, | xclip -selection clipboard on Linux, | clip in Windows Git Bash.
JavaScript
Works in browsers and in Node.js 18 or later, with no dependencies. The API allows calls from any web page.
async function shorten(url, alias) {
const res = await fetch("https://api.blinkhop.com/v1/links", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(alias ? { url, alias } : { url }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
return data.short_url;
}
console.log(await shorten("https://example.com/a/very/long/link"));
Node.js with retries
A reusable helper that waits and retries when you hit the rate limit. Save it as shorten.mjs and run node shorten.mjs.
const API = "https://api.blinkhop.com/v1";
export async function shorten(url, { alias, retries = 3 } = {}) {
for (let attempt = 0; ; attempt++) {
const res = await fetch(`${API}/links`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(alias ? { url, alias } : { url }),
});
if (res.status === 429 && attempt < retries) {
const wait = Number(res.headers.get("retry-after") ?? 1);
await new Promise((resolve) => setTimeout(resolve, wait * 1000));
continue;
}
const data = await res.json();
if (!res.ok) {
throw Object.assign(new Error(data.error.message), { code: data.error.code, status: res.status });
}
return data;
}
}
const link = await shorten("https://example.com/a/very/long/link");
console.log(link.short_url, link.qr_url);
Bulk shortening
Shorten up to 100 URLs in one request. Each URL gets its own result, in order.
const res = await fetch("https://api.blinkhop.com/v1/links/bulk", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ urls: ["https://example.com/a", "https://example.org/b"] }),
});
const { links } = await res.json();
for (const l of links) {
console.log(l.error ? `Failed: ${l.url} (${l.error.message})` : `${l.short_url} -> ${l.url}`);
}
Python
With the popular requests library (Python 3.10 or later):
import requests
API = "https://api.blinkhop.com/v1"
def shorten(url: str, alias: str | None = None) -> str:
payload = {"url": url} if alias is None else {"url": url, "alias": alias}
r = requests.post(f"{API}/links", json=payload, timeout=10)
data = r.json()
if not r.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
return data["short_url"]
print(shorten("https://example.com/a/very/long/link"))
Python without dependencies
The same call with the standard library only:
import json
import urllib.error
import urllib.request
def shorten(url: str) -> str:
req = urllib.request.Request(
"https://api.blinkhop.com/v1/links",
data=json.dumps({"url": url}).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(req, timeout=10) as res:
return json.load(res)["short_url"]
except urllib.error.HTTPError as e:
err = json.load(e)["error"]
raise RuntimeError(f"{err['code']}: {err['message']}") from None
print(shorten("https://example.com/a/very/long/link"))
Go
Standard library only. Save as main.go and run go run main.go.
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"time"
)
type Link struct {
ShortURL string `json:"short_url"`
URL string `json:"url"`
QRURL string `json:"qr_url"`
}
type apiError struct {
Error struct {
Code string `json:"code"`
Message string `json:"message"`
} `json:"error"`
}
func shorten(url string) (*Link, error) {
body, _ := json.Marshal(map[string]string{"url": url})
client := &http.Client{Timeout: 10 * time.Second}
res, err := client.Post("https://api.blinkhop.com/v1/links", "application/json", bytes.NewReader(body))
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode >= 300 {
var e apiError
_ = json.NewDecoder(res.Body).Decode(&e)
return nil, fmt.Errorf("%s: %s", e.Error.Code, e.Error.Message)
}
var link Link
if err := json.NewDecoder(res.Body).Decode(&link); err != nil {
return nil, err
}
return &link, nil
}
func main() {
link, err := shorten("https://example.com/a/very/long/link")
if err != nil {
log.Fatal(err)
}
fmt.Println(link.ShortURL)
}
PHP
With the cURL extension, enabled on most PHP installs:
<?php
function shorten(string $url): string
{
$ch = curl_init('https://api.blinkhop.com/v1/links');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_POSTFIELDS => json_encode(['url' => $url]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
$body = curl_exec($ch);
if ($body === false) {
throw new RuntimeException(curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$data = json_decode($body, true);
if ($status >= 300) {
throw new RuntimeException($data['error']['code'] . ': ' . $data['error']['message']);
}
return $data['short_url'];
}
echo shorten('https://example.com/a/very/long/link'), PHP_EOL;
PowerShell
Works in Windows PowerShell 5.1 and PowerShell 7:
$body = @{ url = "https://example.com/a/very/long/link" } | ConvertTo-Json
$link = Invoke-RestMethod -Method Post -Uri "https://api.blinkhop.com/v1/links" `
-ContentType "application/json" -Body $body
$link.short_url
Google Sheets
Shorten a whole column with a custom formula. In your sheet, open Extensions → Apps Script, paste this code, save, then type =SHORTEN(A2) in a cell.
/**
* Shortens a URL with Blinkhop.
* @param {string} url The long URL.
* @return The short zou.sh link.
* @customfunction
*/
function SHORTEN(url) {
if (!url) return "";
const key = Utilities.base64Encode(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, String(url)));
const cache = CacheService.getScriptCache();
const hit = cache.get(key);
if (hit) return hit;
const res = UrlFetchApp.fetch("https://api.blinkhop.com/v1/links", {
method: "post",
contentType: "application/json",
payload: JSON.stringify({ url: String(url) }),
muteHttpExceptions: true,
});
const data = JSON.parse(res.getContentText());
if (data.error) return "Error: " + data.error.message;
cache.put(key, data.short_url, 21600);
return data.short_url;
}
Requests from Google Sheets come from Google’s shared servers, so the per-IP limit of 20 links per minute can run out sooner than you expect. The cache above avoids calling the API again for the same URL. For large sheets, shorten in batches or use the bulk endpoint.
Bookmarklet
Shorten the page you’re on with one click. Drag this button to your bookmarks bar:
It sends the current address to the API and shows the short link, ready to copy. A few sites with strict security policies block outside requests: on those, paste the link on blinkhop.com instead.
No-code tools
Any automation tool that can send an HTTP request can shorten links: n8n (HTTP Request node), Make (HTTP module) or Zapier (Webhooks by Zapier). Use these settings:
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://api.blinkhop.com/ |
| Header | Content-Type: application/ |
| Body | {"url": "<the long URL>"} |
| Result | Read short_url from the JSON response |
These tools share their servers between many users, so add a short delay between calls if you shorten many links in a row.
AI assistants
To let Claude, ChatGPT, Cursor or VS Code shorten links for you, you don’t need code at all: connect the Blinkhop MCP server with a single URL.