# Code samples

> Working snippets to shorten links from the tools you already use. No key, no SDK to install: each one is a single HTTP request.

Source: https://blinkhop.com/docs/code-samples

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](https://blinkhop.com/docs/api).

## cURL

```bash
# 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`:

```bash
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.

```js
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`.

```js
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.

```js
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](https://requests.readthedocs.io/) library (Python 3.10 or later):

```python
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:

```python
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`.

```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
<?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:

```powershell
$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.

```js
/**
 * 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](https://blinkhop.com/docs/api#bulk).

## Bookmarklet

Shorten the page you're on with one click. Drag this button to your bookmarks bar:

<p><a class="bookmarklet" href="javascript:(async()=>{try{const r=await fetch('https://api.blinkhop.com/v1/links',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({url:location.href})});const d=await r.json();prompt(d.error?d.error.message:'Your short link:',d.short_url||'')}catch(e){alert('This site blocks outside requests. Paste the link on blinkhop.com instead.')}})();">Shorten with Blinkhop</a></p>

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](https://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/v1/links` |
| Header | `Content-Type: application/json` |
| 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](https://blinkhop.com/mcp) with a single URL.
