Import & Export
Trelay supports importing links from CSV or JSON (including from other URL shorteners) and exporting links or per-link stats to CSV or JSON.
Export links
Export all links (or filtered by folder) as CSV or JSON. Requires authentication (X-API-Key or Authorization: Bearer <token>).
Endpoint
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/export | Export links. Query: format=csv or format=json, optional folder_id. |
Example
curl -H "X-API-Key: YOUR_API_KEY" \
"http://localhost:8080/api/v1/export?format=json" -o links.json
curl -H "X-API-Key: YOUR_API_KEY" \
"http://localhost:8080/api/v1/export?format=csv&folder_id=1" -o folder1.csv Export stats
Export click statistics for a single link as CSV or JSON via the stats endpoint.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/stats/{slug}?export=csv | Download stats as CSV. |
| GET | /api/v1/stats/{slug}?export=json | Download stats as JSON. |
Import from CSV
Upload a CSV file to create many links at once. The API accepts a multipart form with file and optional format and skip_duplicates.
Endpoint
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/import | Import from CSV. Form: file (required), format (generic, yourls, shlink, bitly), skip_duplicates (true/false). Optional query: folder_id. |
CSV formats
generic— Generic CSV: columns likeurl,slug,tags, etc. Header row is auto-detected; column names can vary (e.g.url,long_url,destination).yourls— YOURLS-style export.shlink— Shlink-style export.bitly— Bitly-style export.
When skip_duplicates is true, links with a slug that already exists are skipped instead of causing an error.
Example (generic CSV)
# CSV with header: url, slug, tags, ...
url,slug,tags
https://example.com/page1,page1,"blog,docs"
https://example.com/page2,page2,"blog" curl -X POST -H "X-API-Key: YOUR_API_KEY" \
-F "file=@links.csv" \
-F "format=generic" \
-F "skip_duplicates=true" \
http://localhost:8080/api/v1/import Import from JSON
Send a JSON body with an array of link objects. Each object must have url; other fields are optional.
Endpoint
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/import/json | Import from JSON. Body: {"links": [...], "skip_duplicates": true}. Each link: url (required), slug, tags, password, ttl_hours, folder_id. |
Example
{
"links": [
{ "url": "https://example.com/a", "slug": "link-a", "tags": ["blog"] },
{ "url": "https://example.com/b", "slug": "link-b" }
],
"skip_duplicates": true
} curl -X POST -H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"links":[{"url":"https://example.com/a","slug":"link-a"}],"skip_duplicates":true}' \
http://localhost:8080/api/v1/import/json Import response
Import endpoints return a result object:
{
"success": true,
"data": {
"total": 10,
"imported": 8,
"skipped": 1,
"failed": 1,
"errors": [
{ "row": 5, "url": "https://...", "slug": "x", "message": "slug already exists" }
]
}
} total is the number of rows/items processed; imported, skipped, and failed sum to total. errors lists failed rows with reason.