← Back to Blog
·9 min read

API URL Shortener: How to Shorten Links Programmatically


Need to create short links from your app, script, or automation workflow? A URL shortener API lets you programmatically create, manage, and track short links. In this guide, we'll show you how to integrate URL shortening into your code.


Why Use a URL Shortener API?


Manual link shortening works fine for one-off links. But when you need to:


  • Generate links dynamically: Create unique short links for each user, email, or transaction
  • Automate workflows: Shorten URLs as part of a larger automation pipeline
  • Build integrations: Add link shortening to your app or service
  • Process in bulk: Create hundreds or thousands of links at once
  • Track programmatically: Pull analytics data into your own dashboards

You need an API.


Getting Started with y.hn API


Step 1: Get Your API Key


1. Sign up at y.hn and upgrade to Pro ($4.99/mo for 1,000 API req/mo) or Business (unlimited)

2. Go to Settings

3. Click "Generate API Key"

4. Save your key securely (it starts with yhn_)


Step 2: Make Your First Request


Create a short link with a simple POST request:



curl -X POST https://y.hn/api/links \


  -H "Authorization: Bearer yhn_your_api_key" \


  -H "Content-Type: application/json" \


  -d '{"url": "https://example.com/very/long/url"}'



Response:


{


  "shortUrl": "https://y.hn/abc123",


  "slug": "abc123",


  "targetUrl": "https://example.com/very/long/url",


  "id": "clx..."


}



Step 3: Use Custom Slugs



curl -X POST https://y.hn/api/links \


  -H "Authorization: Bearer yhn_your_api_key" \


  -H "Content-Type: application/json" \


  -d '{"url": "https://example.com", "customSlug": "my-link"}'



Code Examples


JavaScript/Node.js



async function shortenUrl(url, customSlug) {


  const response = await fetch('https://y.hn/api/links', {


    method: 'POST',


    headers: {


      'Authorization': 'Bearer yhn_your_api_key',


      'Content-Type': 'application/json',


    },


    body: JSON.stringify({ url, customSlug }),


  });


  


  const data = await response.json();


  return data.shortUrl;


}





// Usage


const shortUrl = await shortenUrl('https://example.com/long-url');


console.log(shortUrl); // https://y.hn/abc123



Python



import requests





def shorten_url(url, custom_slug=None):


    response = requests.post(


        'https://y.hn/api/links',


        headers={


            'Authorization': 'Bearer yhn_your_api_key',


            'Content-Type': 'application/json',


        },


        json={


            'url': url,


            'customSlug': custom_slug,


        }


    )


    return response.json()['shortUrl']





# Usage


short_url = shorten_url('https://example.com/long-url')


print(short_url)  # https://y.hn/abc123



PHP



function shortenUrl($url, $customSlug = null) {


    $ch = curl_init('https://y.hn/api/links');


    curl_setopt($ch, CURLOPT_POST, true);


    curl_setopt($ch, CURLOPT_HTTPHEADER, [


        'Authorization: Bearer yhn_your_api_key',


        'Content-Type: application/json',


    ]);


    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([


        'url' => $url,


        'customSlug' => $customSlug,


    ]));


    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);


    


    $response = json_decode(curl_exec($ch), true);


    curl_close($ch);


    


    return $response['shortUrl'];


}





// Usage


$shortUrl = shortenUrl('https://example.com/long-url');


echo $shortUrl; // https://y.hn/abc123



Ruby



require 'net/http'


require 'json'





def shorten_url(url, custom_slug: nil)


  uri = URI('https://y.hn/api/links')


  http = Net::HTTP.new(uri.host, uri.port)


  http.use_ssl = true


  


  request = Net::HTTP::Post.new(uri)


  request['Authorization'] = 'Bearer yhn_your_api_key'


  request['Content-Type'] = 'application/json'


  request.body = { url: url, customSlug: custom_slug }.to_json


  


  response = http.request(request)


  JSON.parse(response.body)['shortUrl']


end





# Usage


short_url = shorten_url('https://example.com/long-url')


puts short_url # https://y.hn/abc123



API Endpoints


Create a Short Link


POST /api/links


Body: { "url": "...", "customSlug": "..." (optional) }



List Your Links


GET /api/links?page=1&limit=20&search=keyword



Get Link Details


GET /api/links/{linkId}



Get Link Analytics


GET /api/links/{linkId}/stats



Delete a Link


DELETE /api/links/{linkId}



Authentication


All API requests require a Bearer token in the Authorization header:



Authorization: Bearer yhn_your_api_key



Keep your API key secret. Don't expose it in client-side code or public repositories.


Rate Limits


PlanRate Limit
Pro1,000 requests/month
BusinessUnlimited

If you exceed your rate limit, the API returns a 429 status code. Upgrade to Business for unlimited requests.


Common Use Cases


Email Marketing


Automatically shorten all links in your email campaigns:



// Before sending each email


const links = extractLinks(emailBody);


for (const link of links) {


  const shortUrl = await shortenUrl(link, `email-${campaignId}`);


  emailBody = emailBody.replace(link, shortUrl);


}



E-Commerce


Create unique short links for each product:



for product in products:


    short_url = shorten_url(


        product.url,


        custom_slug=f"shop-{product.sku}"


    )


    product.short_url = short_url



SaaS Applications


Generate share links for your users:



app.post('/share', async (req, res) => {


  const shareUrl = `https://myapp.com/shared/${req.body.documentId}`;


  const shortUrl = await shortenUrl(shareUrl);


  res.json({ shareUrl: shortUrl });


});



CI/CD Pipelines


Create short links for deployment previews:



PREVIEW_URL=$(get_preview_url)


SHORT_URL=$(curl -s -X POST https://y.hn/api/links \


  -H "Authorization: Bearer $YHN_API_KEY" \


  -H "Content-Type: application/json" \


  -d "{\"url\": \"$PREVIEW_URL\"}" | jq -r '.shortUrl')


echo "Preview: $SHORT_URL"



Error Handling


The API returns standard HTTP status codes:


CodeMeaning
200Success
400Bad request (invalid URL, invalid slug format)
401Unauthorized (invalid or missing API key)
409Conflict (slug already taken)
429Rate limit exceeded
500Server error

Always handle errors in your code:



async function shortenUrl(url) {


  const response = await fetch('https://y.hn/api/links', {


    method: 'POST',


    headers: {


      'Authorization': 'Bearer yhn_your_api_key',


      'Content-Type': 'application/json',


    },


    body: JSON.stringify({ url }),


  });


  


  if (!response.ok) {


    const error = await response.json();


    throw new Error(error.error || 'Failed to shorten URL');


  }


  


  return response.json();


}



Webhooks (Business Plan)


Business plan users can set up webhooks to receive real-time notifications when links are clicked:



{


  "event": "link.clicked",


  "data": {


    "linkId": "clx...",


    "slug": "abc123",


    "clickedAt": "2026-02-10T12:00:00Z",


    "country": "US",


    "device": "Mobile"


  }


}



FAQ


Q: Is the API free?

A: API access is included in Pro ($4.99/mo, 1,000 req/mo) and Business ($19.99/mo, unlimited) plans.


Q: Can I use the API in client-side code?

A: No. Your API key would be exposed. Always call the API from your server.


Q: What's the rate limit?

A: Pro: 1,000 requests/month. Business: unlimited. Requests are counted per calendar month.


Q: Can I create links without authentication?

A: No. All API requests require a valid API key.


Q: Is there a sandbox/test environment?

A: Not currently. Use your real API key but test with harmless URLs.


---


Start building with the y.hn API today. Get your API key and create your first link in under a minute.

Ready to try the shortest links on earth?

Create your first short link in seconds. No signup required.

Try y.hn Free →