From Bitly
Bitly’s strength is brand recognition and a long-running v4 API. Elido trades that for EU residency, predictable pricing without overage cliffs, and a redirect tier you can self-host. The migration is mostly a CSV import and a CNAME flip — both can be done while Bitly stays live, so traffic doesn’t drop on cutover.
What you need before you start
| Item | Where |
|---|---|
| Bitly Group ID + Personal Access Token | Bitly → Profile Settings → API |
| CSV export of links | Bitly → Bitlinks → Export |
| DNS access for any custom Bitly domain | Your registrar |
| Elido workspace + Personal Access Token | app.elido.app → Settings → API Tokens |
The Bitly export is per-Group and arrives as a .csv with these
columns: long_url, custom_bitlink, title, archived, tags,
created_at. Note that custom_bitlink includes the host
(bit.ly/abc123) — you only want the slug.
Import links in bulk
Elido’s bulk endpoint accepts up to 100 links per request.
#!/usr/bin/env bash
WS=1
TOKEN="$ELIDO_TOKEN"
# Skip header, batch by 100 lines
tail -n +2 bitly-export.csv | split -l 100 - batch_
for f in batch_*; do
payload=$(awk -F',' '{
gsub("\"","",$1); gsub("\"","",$2); gsub("\"","",$5);
slug = $2; sub("^[^/]+/", "", slug);
printf "{\"destination_url\":\"%s\",\"slug\":\"%s\",\"tags\":\"%s\"},\n", $1, slug, $5
}' "$f" | sed '$ s/,$//')
curl -sS -X POST "https://api.elido.app/v1/workspaces/$WS/links/bulk" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"links\":[$payload]}"
done
rm batch_*A few caveats:
- Slug collisions return
409 slug_takenper row in the response. The whole batch still applies; only the conflicting rows fail. Re-run those withslugomitted to auto-generate. - Tags import as a comma-separated string — Elido splits on
,and trims whitespace. - Archived links in Bitly become
archived: truein Elido. They don’t redirect until un-archived.
Cut over the custom domain
Elido uses Caddy on-demand TLS, so you don’t manage certs. The flow keeps Bitly serving traffic until Elido is verified:
- Add the domain in Elido — Settings → Domains → Add, enter the hostname.
- Add the verification TXT at your registrar:
_elido-verify.go.example.com. TXT "verify=<token-from-dashboard>" - Wait for
verified— Elido polls every 30s. Bitly is still serving, the TXT is invisible to it. - Flip the CNAME:
# Before go.example.com. CNAME bsr.bitly.net. # After go.example.com. CNAME edge.elido.me. - First request triggers a Let’s Encrypt cert (typically under
30s). Status moves from
verified→active.
If anything goes sideways, flip the CNAME back — Bitly stays authoritative, no data lost.
API mapping
Elido scopes everything to a workspace; the Bitly Group is the closest analogue.
| Bitly | Elido |
|---|---|
POST /v4/shorten | POST /v1/workspaces/{ws}/links |
GET /v4/bitlinks/{id} | GET /v1/workspaces/{ws}/links/{id} |
PATCH /v4/bitlinks/{id} | PATCH /v1/workspaces/{ws}/links/{id} |
GET /v4/bitlinks (paginated list) | GET /v1/workspaces/{ws}/links |
GET /v4/bitlinks/{id}/clicks | GET /v1/analytics/workspaces/{ws}/timeseries?link_id=... |
GET /v4/bitlinks/{id}/countries | Use the dimensions=country query on timeseries |
GET /v4/groups/{id}/qr-codes/... | POST /v1/qr/generate (see QR codes) |
POST /v4/groups/{id}/webhooks | POST /v1/webhooks/workspaces/{ws}/webhooks (see Webhooks) |
| OAuth2 app authorization | OAuth2 with PKCE (see Authentication) |
The auth header in both APIs is Authorization: Bearer <token>. Token
formats differ — Elido PATs are prefixed pat_, workspace keys
wsk_.
Click history
The Bitly export ships aggregated daily counts per link, not the raw event stream. Elido starts collecting click events at cutover, so don’t expect history to “merge” — keep the Bitly CSV around for retrospective reports.
If you need pre-cutover totals in Elido analytics, request a one-time
backfill from support and provide the CSV. We won’t synthesize per-IP
records; the import lands as a single imported row per link per day.
Pricing parity
| Tier | Bitly | Elido |
|---|---|---|
| Free | 10 links / 1k clicks per month | 50 links / 5k clicks per month |
| Paid (entry) | Bitly Core $8/mo (3 custom links/mo) | Pro €9/mo (5k links, 1 custom domain) |
| Paid (team) | Bitly Growth $35/mo | Business €29/mo |
| Enterprise | Quote-based | Quote-based, EU-resident contract |
Bitly meters “branded” links separately from short links; Elido doesn’t — every link in your workspace counts the same regardless of which custom domain it sits on.
After cutover
- Update SDK base URLs in any backend code (
api-ssl.bitly.com→api.elido.app). - Re-issue webhook secrets — the HMAC algorithm is the same
(
HMAC-SHA256(secret, ts.body)), only the secret value changes. - Archive Bitly’s account but keep the export CSV — it’s the only record of pre-cutover history.