← Back to blog
· bah.is Team

How to Build a Link Shortener Integration with the bah.is API

Shorten links programmatically, build Slack bots, automate your workflows — here's a practical guide to the bah.is API with real code examples.

Manually creating short links in a dashboard is fine for occasional use. But if you’re shortening links as part of a publishing workflow, a CRM integration, an internal tool, or any kind of automation, the bah.is API lets you do it programmatically. Here’s everything you need to get started.

Getting Your bah.is API Key

All API requests to bah.is are authenticated with an API key. To get yours:

  1. Log in at bah.is and go to Settings → API.
  2. Click Generate API Key.
  3. Copy and store it somewhere secure — you won’t be able to view it again after leaving the page.

Your API key should be treated like a password. Don’t commit it to version control, don’t hardcode it in client-side code, and don’t share it. Use environment variables.

The core endpoint is POST /links. Here’s how to call it.

curl Example

curl -X POST https://api.bah.is/v1/links \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://yoursite.com/landing-page?utm_source=api&utm_medium=automation",
    "slug": "spring-api",
    "domain": "bah.is"
  }'

The response will look like:

{
  "id": "lnk_abc123",
  "short_url": "https://bah.is/spring-api",
  "original_url": "https://yoursite.com/landing-page?utm_source=api&utm_medium=automation",
  "slug": "spring-api",
  "created_at": "2026-04-29T09:00:00Z",
  "clicks": 0
}

JavaScript (Node.js / fetch)

const response = await fetch('https://api.bah.is/v1/links', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.BAHIS_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://yoursite.com/landing-page',
    slug: 'spring-api',
  }),
});

const link = await response.json();
console.log(link.short_url); // https://bah.is/spring-api

Python

import os
import requests

response = requests.post(
    'https://api.bah.is/v1/links',
    headers={
        'Authorization': f'Bearer {os.environ["BAHIS_API_KEY"]}',
        'Content-Type': 'application/json',
    },
    json={
        'url': 'https://yoursite.com/landing-page',
        'slug': 'spring-api',
    }
)

link = response.json()
print(link['short_url'])  # https://bah.is/spring-api

Omit the slug field and bah.is will generate one automatically. Pass a domain field to use a custom short domain you’ve configured.

One of the most useful quick-win integrations is a Slack bot that shortens any URL you paste into it. This is especially useful for team link management. Here’s a minimal Node.js implementation using the Slack Bolt SDK:

const { App } = require('@slack/bolt');

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
});

// Listen for messages containing URLs
app.message(/https?:\/\/\S+/, async ({ message, say }) => {
  const urlMatch = message.text.match(/https?:\/\/\S+/);
  if (!urlMatch) return;

  const url = urlMatch[0];

  const res = await fetch('https://api.bah.is/v1/links', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.BAHIS_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ url }),
  });

  const link = await res.json();

  await say({
    text: `Short link: ${link.short_url}`,
    thread_ts: message.ts,
  });
});

(async () => {
  await app.start(process.env.PORT || 3000);
  console.log('bah.is Slack bot running');
})();

Deploy this to a small server or a serverless function, configure your Slack app with a bot token and signing secret, set your BAHIS_API_KEY, and every URL posted in a channel will get a short link reply in the thread. For best practices, follow the Slack Bolt SDK documentation.

To pull click data for a link:

curl https://api.bah.is/v1/links/lnk_abc123/analytics \
  -H "Authorization: Bearer YOUR_API_KEY"

This returns click counts, geographic breakdowns, device types, and referrer data — the same data visible in your link analytics dashboard, accessible programmatically for reporting pipelines or custom dashboards.

API Rate Limits and Best Practices

The bah.is API is rate-limited to protect service quality. Current limits:

  • Free tier: 60 requests per minute
  • Pro tier: 600 requests per minute

If you hit the rate limit, the API returns a 429 Too Many Requests response with a Retry-After header indicating when to retry. Implement exponential backoff in any production integration.

Caching and Slug Best Practices

Cache short links where possible. If you’re shortening the same destination URL repeatedly, store the result rather than creating a new link for each request. Duplicate short links are wasteful and clutter your dashboard.

Use meaningful slugs when you can. Autogenerated slugs are fine for bulk operations, but for any link that will be shared publicly, a descriptive slug is worth the extra API parameter. Pair them with UTM parameters for full attribution.

Use webhooks for async workflows. The bah.is API supports webhooks for click events — rather than polling the analytics endpoint, register a webhook URL and receive click data in real time. This is more efficient and more responsive for automation pipelines.

Keep your API key out of client-side code. API requests should always originate from a server you control. Exposing your API key in browser JavaScript means anyone who views your source can use your account.

The full API reference is at api.bah.is/docs, including endpoint schemas, error codes, and the webhooks specification.


The bah.is API is designed to stay out of your way. Authentication is a single header, the request body is minimal, and the response gives you exactly what you need. Whether you’re automating a publishing workflow, building internal tooling, or wiring up a Slack bot, link shortening should be a five-minute integration, not a project.

Start shortening URLs for free →