Skip to content
YAS.SH
URL Shortening

Bulk Link Creation with CSV: Import Hundreds of Links Safely

How to create links in bulk from CSV exports — rate limits, idempotency, alias collisions, and verification patterns.

yas-team5 min readcsvbulkapi
Bulk Link Creation with CSV: Import Hundreds of Links Safely
Featured imageBulk Link Creation with CSV: Import Hundreds of Links Safely

Manual link creation has a ceiling: around 30 links an hour with full attention. Teams that need hundreds of links — product feeds, print campaigns, migrations — hit that ceiling fast. The answer is the API and a disciplined batch script. This guide covers the pattern that works: rate limits, idempotency, collision handling, and verification.

The batch pattern

Every bulk job is the same loop:

read rows → build payloads → POST with rate-limit delay → collect results → report failures

With the yas.sh API, the safe rate is 60 creations per minute per user. A 1-second delay between calls keeps you under the limit even with retries:

#!/usr/bin/env bash
# links.csv: originalUrl,customAlias,title
while IFS=, read -r url alias title; do
  curl -s -X POST https://yas.sh/api/v1/links \
    -H "Authorization: Bearer yas_live_..." -H "Content-Type: application/json" \
    -d "{\"originalUrl\":\"$url\",\"customAlias\":\"$alias\",\"title\":\"$title\"}"
  sleep 1
done < links.csv

In Node.js, the same loop with fetch and a small delay library is a 30-line script; TypeScript example in the API reference.

Idempotency: retries without duplicates

Network failures happen mid-batch. Without protection, a retry creates a duplicate link. The API supports an Idempotency-Key header per row — typically the row number or a content hash:

curl -X POST https://yas.sh/api/v1/links \
  -H "Authorization: Bearer yas_live_..." -H "Content-Type: application/json" \
  -H "Idempotency-Key: row-0042" \
  -d '{"originalUrl":"https://example.com/42"}'

On retry with the same key, the API returns the existing link (200) instead of creating a second one. Your script treats both responses as success — the batch is naturally resumable.

Alias collisions: expect them, handle them

In a fresh namespace collisions are rare; in a migration or a shared workspace they're guaranteed. The API returns 409 Conflict with suggestions (launch-1, launch-2026). The batch script should:

  1. Record the collision with the row reference.
  2. Decide by policy: skip (destination already covered?) or retry with a deterministic suffix (e.g. -2, -3).
  3. Write the final mapping (row → short link) to an output CSV — that file is your inventory.

Verification: prove the batch before you ship it

A batch isn't done when the last 201 arrives. Verification closes the loop:

# 1. Count check — exported links should match input rows
curl -H "Authorization: Bearer yas_live_..." "https://yas.sh/api/v1/links?limit=100" | jq '.data | length'

# 2. Spot-check redirects — a sample of codes must 302 correctly
curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" https://yas.sh/launch

# 3. Full export for the record
curl -H "Authorization: Bearer yas_live_..." "https://yas.sh/api/v1/links/export.csv" -o inventory.csv

Spot-checking 5% of codes plus the export count catches the failure modes that matter: rows that silently failed, aliases that collided, and destinations that were wrong in the source data.

The migration angle

Bulk creation is the core of every migration. The Bitly migration guide and Short.io migration guide apply this same pattern with the export formats of those platforms, plus 301 forwarding so old links keep working during the transition window.

Operational checklist

  • CSV is UTF-8, headers verified, formula-injection escaped (the export already is)
  • Delay ≥1s between POSTs (60/min budget with headroom)
  • Idempotency-Key per row
  • Collision policy decided before the run
  • Output mapping CSV written and committed
  • 5% spot-check + export count verification

Preparing your source CSV correctly

Most bulk-job failures are source-data failures, not API failures. Before the first request, clean the file:

  • UTF-8 encoding. Non-ASCII characters in titles or aliases (accents, CJK, emoji) fail or corrupt if the file is not UTF-8. Save the CSV as UTF-8 and validate it before running.
  • Header row and field order. A consistent header (originalUrl,customAlias,title) and known column order prevent mis-mapping rows. If the export came from a spreadsheet, watch for extra whitespace, hidden characters, and line-ending inconsistencies.
  • Formula-injection escaping. Fields that begin with =, +, -, or @ can be interpreted as formulas when the output CSV is reopened in a spreadsheet. Escape leading special characters so the inventory file is safe to share.
  • Deduplicate destination URLs. If the same original URL appears many times, decide whether you want one link with many aliases or many links; the answer affects how you build the payloads.

A clean input file is the cheapest insurance a bulk job can have.

Handling failures without restarting

Batches over thousands of rows will hit transient failures — a timeout, a rate limit, a bad row. The pattern that survives this is resumable by design:

  • Write a per-row result as you go, not only at the end.
  • Use the Idempotency-Key (row number or content hash) so a retry returns the existing link instead of a duplicate.
  • On 429, sleep retryAfter and continue; on a 422 or 409, log the row and move on.
  • Keep an output mapping CSV (row → shortLink → status) that is your source of truth and your resume point.

If the process crashes at row 3,000, you should be able to start again and have already-created links recognized via idempotency, not created a second time.

Post-run verification and handoff

A bulk job is complete only when verified. Re-check the exported count against the input rows, spot-check a sample of the short links resolve to the right destination, and confirm the mapping CSV is committed where the team can find it. That handoff artifact — the inventory — is what makes a bulk run useful to the rest of the business, because it answers "which short link belongs to which campaign row" without anyone having to re-derive it.

Consider a product feed with 500 items needing a unique tracking link each. The script reads the CSV, assigns an alias per row (item id), sends one POST per second with an Idempotency-Key per row, logs any 409 collision, and writes a mapping CSV. At 500 rows the whole run finishes in under ten minutes, stays well inside the rate budget, and produces an inventory the team can use in reporting. The same script, with a different source, is exactly what powers a migration or a large print campaign — the pattern does not change with the input.

The discipline of source-data validation, resumable processing, idempotent retries, and a verified inventory is what separates a bulk import you trust from one you fear to run. Applied once, the same batch script becomes a reusable tool your team can point at any new export.

Conclusion

Bulk link creation is a solved problem when you script it: rate-limit-aware loops, idempotent retries, explicit collision policy, and post-run verification. The API reference has the full contract — the same endpoints power the dashboard, so what you script and what you click behave identically.

Frequently asked questions

How fast can I create links in bulk?

The API allows 60 creations per minute per user (120 per minute per IP). A batch of 1,000 links takes about 17 minutes with a 1-second delay — comfortably within limits.

What happens if an alias is already taken?

The API returns 409 Conflict with a suggestion list. Your script should catch it, record the collision, and either skip or retry with a suffixed alias.

Can I retry safely after a network error?

Yes — send an Idempotency-Key header per row. A retry then returns the existing link instead of creating a duplicate.

What's the CSV export format?

GET /api/v1/links/export.csv returns shortCode, originalUrl, title, clicks, createdAt — formula-injection escaped so spreadsheet import is safe.

Was this helpful? Share
Ask YAS AI
🍪 Cookies & privacy. Essential cookies keep you signed in and remember language and theme. Google AdSense and reCAPTCHA are Google technologies: AdSense runs only after Accept All; reCAPTCHA loads on sign-in and contact forms. See how Google uses data: https://policies.google.com/technologies/partner-sites cookie policy · privacy policy.
Settings