/api/v6/urlshortener/links/batchCreate short links in bulk
Up to 1,000 links in one request, with one result per link and a single charge for what was created.
Scope and limits
API key with the urlshortener service enabled and the urlshortener.write capability granted
35 requests per second
Supports Idempotency-Key
- The 35 requests per second are the same as single-link creation: both routes spend a single quota.
- Additionally, up to 2,100 links per minute per organization across all its batches. A batch that does not fit is rejected whole.
- Up to 1,000 links per request; the body, up to 3 MiB; each destination, up to 2048 characters.
- With a plan: the batch links count against the daily creation quota (100,000 per Colombia day).
Creates up to 1,000 links in one request. Each link in the batch takes the same four fields as creating a link and goes through exactly the same checks: destination, alias, domain and expiry.
An invalid link does not sink the batch: the response is 200 with one result per link, in the order of the body —created, replayed or failed—, and each failed one carries in error.code the same code that creating that link alone would return. What does belong to the whole batch is answered without creating anything: an invalid body or one with more than 1,000 links (400), the key used with another body (422), the balance or a spend limit (402), a missing price or currency (409) and the usage limits (429).
A single charge for what was created. The price of all the valid links is reserved from your balance at once, and only the links actually created are charged: if 998 out of 1,000 are created, 998 are charged. Without balance for all of them, 402 and none is created; send a smaller batch. With an active monthly URL shortener plan there is no charge, and the batch links count against the daily creation quota: a batch that does not fit whole is rejected whole with 429 URLSHORTENER_LINK_QUOTA_EXCEEDED, and the message says how many you have left today.
Retry without duplicates with `Idempotency-Key`. The key belongs to the batch: if a request is cut off and you repeat it with the same key and the same body, the links already created come back as replayed —the same ones, without creating others or charging twice, even while the first one is still being processed— and the failed ones are tried again. What was already created is never hidden: if what was missing runs into the balance, a limit or a failure on our side, the response is still 200 with the replayed links, and each pending link comes back failed with that rejection’s code. With the key and a different body, 422 IDEMPOTENCY_KEY_REUSED. Without a key, each retry creates and charges another batch.
The limit counts links, not requests. Besides the request quota, which it shares with single-link creation, your organization can create up to 2,100 links per minute in batches (35 per second, the same pace as single creation). Two batches of 1,000 fit back to back; a batch that does not fit is rejected whole with 429 RATE_TPS_EXCEEDED and Retry-After, without creating or charging anything. Single-link creation does not spend this limit.
Requires a key that can write
Besides the urlshortener service, the API key needs the urlshortener.write capability, which only an owner or an administrator of your organization can grant when creating the key. Without it, the key lists and reads links, statistics, the overview, the domains and the pricing, and gets 403 AUTH_CAPABILITY_NOT_ALLOWED here.
Headers
Idempotency-KeyA-Za-z0-9_-), unique per organization. If you repeat the batch with the same key and the same body, you get the links that were already created —replayed— without creating or charging them again, and whatever was not created the first time is tried again. With a different body, 422 IDEMPOTENCY_KEY_REUSED. It is independent from the single-link creation keys. See the idempotency guide.Request body
application/jsonOnly `links` is accepted, and in each link only its four fields. One that does not exist is rejected with `400` naming the field, and the batch is not processed.linksindex in the response.longUrldomaincodefailed with ALIAS_TAKEN.expiresAt-05:00).{
"links": [
{ "longUrl": "https://example.com/landing?utm_source=sms&c=1" },
{ "longUrl": "https://example.com/landing?utm_source=sms&c=2", "code": "promo-octubre" },
{ "longUrl": "https://example.com/landing?utm_source=sms&c=3", "expiresAt": "2026-12-31T23:59:59-05:00" }
]
}Responses
The batch was processed: the totals and one result per link, in the order of the body. With Idempotency-Key, the Idempotency-Status header says replayed if this request created nothing new and returned the earlier results, and created if it created something. When the key returns earlier links, whole-batch rejections (402, 409, 429, 5xx) are not answered as an error: they go in each pending link, with their code, and the replayed links arrive anyway.
{
"success": true,
"data": {
"created": 2,
"replayed": 0,
"failed": 1,
"items": [
{
"index": 0,
"status": "created",
"link": {
"domain": "h0b.co",
"code": "a1b2c3d",
"shortUrl": "https://h0b.co/a1b2c3d",
"longUrl": "https://example.com/landing?utm_source=sms&c=1",
"isAlias": false,
"status": "active",
"domainStatus": "active",
"expiresAt": null,
"createdAt": "2026-09-30T15:04:05Z",
"clicks": 0,
"uniqueClicks": 0,
"firstClickAt": null,
"lastClickAt": null
}
},
{
"index": 1,
"status": "failed",
"error": { "code": "ALIAS_TAKEN", "message": "Ese código ya se usó en el dominio y no se puede volver a usar." }
},
{
"index": 2,
"status": "created",
"link": {
"domain": "h0b.co",
"code": "k9x8w7v",
"shortUrl": "https://h0b.co/k9x8w7v",
"longUrl": "https://example.com/landing?utm_source=sms&c=3",
"isAlias": false,
"status": "active",
"domainStatus": "active",
"expiresAt": "2027-01-01T04:59:59Z",
"createdAt": "2026-09-30T15:04:05Z",
"clicks": 0,
"uniqueClicks": 0,
"firstClickAt": null,
"lastClickAt": null
}
}
]
},
"meta": {
"requestId": "8f0c0e2a4b1d4c8fae2b7a91e0c5d3f6",
"timestamp": "2026-09-23T18:30:00+00:00",
"responseTimeMs": 7.2
}
}The body cannot be read, has no links, has more than 1,000 (URLSHORTENER_BATCH_TOO_LARGE) or a field that does not exist, or the Idempotency-Key has another shape. Nothing was created.
Invalid or missing credentials.
Your organization has no balance for all the valid links of the batch (or no active billing account), or creating them would exceed a spend limit it configured itself. None was created.
The API key does not have the URL shortener enabled (or it is turned off for your organization), lacks the urlshortener.write capability to create and edit links, cannot be used from the request network, or the organization is not active.
The URL shortener has no price for your organization’s currency, or your organization does not have a currency yet. Retrying does not fix it.
The Idempotency-Key already created links with a different body. Use a new key for a new batch.
The request limit, the per-minute link limit of batches or —with a plan— the daily creation quota was exceeded. The whole batch is rejected without creating anything; Retry-After says how long to wait.
Internal error. Retry with the same Idempotency-Key: whatever was already created comes back as replayed.
Balance could not be checked right now. Nothing was created; you can retry (better with Idempotency-Key).
Possible errors
Codes this endpoint can return in error.code. The full detail lives in the catalog.
AUTH_REQUIREDNo Bearer token was sent, and every call requires one.401AUTH_INVALID_KEYThe API key is not recognized: wrong format, revoked or expired.403AUTH_SERVICE_NOT_ALLOWEDThe key is not allowed to use the service behind this endpoint.403AUTH_IP_NOT_ALLOWEDThe key only works from certain networks and your IP is not one of them.403ACCOUNT_NOT_ACTIVEYour organization is suspended or closed.403AUTH_CAPABILITY_NOT_ALLOWEDThe key has the service, but not the capability this endpoint requires.400VALIDATION_INVALID_PARAMETERA parameter or a body field is not valid.400URLSHORTENER_BATCH_TOO_LARGEThe batch has more links than one request accepts.400IDEMPOTENCY_KEY_INVALIDThe idempotency key does not match the format.422IDEMPOTENCY_KEY_REUSEDThe key already exists, but with a different body.400URL_INVALIDThe destination URL is malformed.400URL_SCHEME_NOT_ALLOWEDOnly http/https destinations are allowed.400URL_TOO_LONGThe destination URL exceeds the maximum length.400URL_BLOCKED_HOSTThe destination host is private or reserved.400ALIAS_INVALIDThe custom alias doesn't match the allowed format.409ALIAS_TAKENThe alias was already used on this domain.409ALIAS_RESERVEDThe alias is a reserved word.409ALIAS_RETIREDThe alias belongs to a link of yours that you deleted.400EXPIRES_AT_INVALIDexpiresAt must be a future ISO date-time.400DOMAIN_NOT_ALLOWEDThe chosen domain isn't available to your account.409DOMAIN_NOT_VERIFIEDYour domain is not verified yet.402URLSHORTENER_INSUFFICIENT_FUNDSYour organization has no balance to create the link.402URLSHORTENER_SPEND_LIMIT_REACHEDA spend limit your organization configured was reached.403ACCOUNT_CONFIG_NOT_FOUNDWe could not load the organization behind your key.409URLSHORTENER_NOT_PRICEDThe URL shortener has no price configured for your currency.409URLSHORTENER_CURRENCY_UNDEFINEDYour organization does not have a currency yet.429URLSHORTENER_LINK_QUOTA_EXCEEDEDYour organization reached its plan’s daily link quota.429RATE_TPS_EXCEEDEDYou exceeded your organization quota for this endpoint.500INTERNAL_SERVER_ERRORSomething went wrong on our side.503SERVICE_UNAVAILABLEGeneric 503: a service we depend on is not responding.