Error catalog
Every error response carries a stable code in error.. Your client should decide by that code: look it up here, filter by topic or open any row for the full explanation and how to fix it.
67 documented codes
Showing 67 of 67
401AUTH_REQUIREDNo Bearer token was sent, and every call requires one.
We did not see a Bearer token in your request. Every API v6 call needs an API key in the Authorization header: without it we cannot tell which organization is calling.
How to fix it
Send Authorization: on every request. Bearer is the only accepted scheme: the old styles that sent the key in the URL or the body are no longer accepted.
40002#auth-required401AUTH_INVALID_KEYThe API key is not recognized: wrong format, revoked or expired.
The API key you sent is not recognized. Three situations produce this code: a key with the wrong format, a key that was rotated or revoked, or a key past its expiration date.
How to fix it
Check that your client is using exactly the value shown when the key was created: keys are shown only once. If you rotated keys recently, make sure you are using the new one. If the key expired, issue a new one from the customer portal.
40003#auth-invalid-key401AUTH_COST_CENTER_DISABLEDThe cost center bound to the key is disabled.
Every API key is bound to a cost center so usage can be billed and reported correctly. The cost center for this key is disabled.
How to fix it
Re-enable the cost center from the customer portal, or issue a new key bound to an active one.
403AUTH_SERVICE_NOT_ALLOWEDThe key is not allowed to use the service behind this endpoint.
This key is not allowed to call the service behind this endpoint. Keys are restricted to specific services so that a leaked or misused key can only do what it was allowed to. Each service is granted in full: with the URL shortener, the key also creates and deletes links; with Storage, it also views and downloads the files. Without the service, the key cannot use any of its endpoints.
How to fix it
Use a key that already has the service, or ask the owner of your organization for a new one that includes it: only the owner creates keys. Diagnostic endpoints under / are always available regardless of the key scope.
403AUTH_CAPABILITY_NOT_ALLOWEDThe key lacks the account capability this endpoint requires.
The account and organization endpoints require an explicitly granted capability: account (balance and billing) or directory (organization data, cost centers and users). They are the only capabilities: within a service there are no partial permissions, because the service is granted in full.
How to fix it
Capabilities are set when the key is created and cannot be added later: use a key that has it, or ask the owner of your organization for a new one that includes it (only the owner creates keys, in Cloud → API keys) and revoke the old one.
403AUTH_IP_NOT_ALLOWEDThe key only works from certain networks and your IP is not one of them.
This key has a list of allowed networks (single IPs or CIDR blocks, IPv4 or IPv6) and the request came from an IP that is in none of them. The key is valid and your organization is active: the only thing that does not match is the origin. The IP we saw you calling from comes in meta. of the same response.
How to fix it
Compare meta. with the key networks: if you call from behind a NAT, a proxy or a cloud, the egress IP is often not the one you expect. Call from an allowed network, or use a key that allows that IP. The list is set when the key is created, so changing it means issuing a new key.
400AUTH_SOURCE_IP_UNKNOWNReserved: kept only as a bridge from v5.
Reserved code, kept as a bridge for callers migrating from v5. API v6 does not use the source IP override mechanism that produced this error, so you should not see it on v6 traffic.
40015#auth-source-ip-unknown403ACCOUNT_NOT_ACTIVEYour organization is suspended or closed.
Your organization is not in an active state, usually because it was suspended or closed. While that lasts, every endpoint rejects calls, including the diagnostic ones.
How to fix it
Contact support to review the situation and restore the organization. The state cannot be lifted through the API.
403ACCOUNT_BLOCKEDA full block is active: every call is rejected.
Your organization is under a full block. Every call is rejected, including read-only ones, until the block is lifted.
How to fix it
Open a support ticket so we can review the case. Blocks are lifted once the underlying reason is resolved.
403ACCOUNT_READ_ONLYRead-only mode: only GET, HEAD and OPTIONS pass.
Your organization is in read-only mode. Requests that only read information (GET, HEAD, OPTIONS) keep working, but any call that creates or modifies data is rejected.
How to fix it
Until the block is lifted, pause any code that modifies data. Contact support to find out why it is active and what is needed to remove it.
403ACCOUNT_CONFIG_NOT_FOUNDWe could not load the organization behind your key.
Your API key authenticated correctly, but we could not load the organization it points to. This is a data problem on our side, not in your request.
How to fix it
Contact support and include the meta. from the response: with that id we can trace the exact query that failed.
4002#account-config-not-found429RATE_DDOS_EXCEEDEDUnusually high volume from your source IP.
The per-source-IP guard fired, for one of two reasons. First: your IP produced an unusually high volume of requests in the last minute; legitimate integrations rarely get close to the limit. Second: 60 different API keys that do not authenticate arrived from your IP within one minute (keys that do not exist, or were revoked or expired), which is the footprint of someone guessing keys; the IP is then cut off for 15 minutes, and during that time it gets this 429 even if the key you send is valid. Both count IPv6 addresses by their /64 block: every address in the same /64 shares the limit and the cut-off.
How to fix it
Wait the seconds reported in Retry-After before retrying: in the cut-off for keys that do not authenticate, they are what is left of the 15 minutes. If your integration rotates between several keys, check that none is miscopied or revoked: every distinct invalid key counts. If you are a legitimate caller behind a shared IP and hit this consistently, contact support so we can review your traffic pattern.
40001#rate-ddos-exceeded429RATE_TPS_EXCEEDEDYou exceeded your organization quota for this endpoint.
You sent more requests to this endpoint than your organization quota allows in the current window. Each endpoint has its own quota: hitting the wall on one does not affect the others. The URL shortener overview and statistics also have a cost quota: each query spends units according to the days and sections it asks for, and the overview is computed at most twice at once per organization. And URL shortener bulk creation has a per-link limit (2,100 per minute per organization): a batch that does not fit is rejected whole, without creating or charging anything.
How to fix it
Pause your client for the seconds reported in Retry-After and start again. To avoid hitting it at all, read the RateLimit-Remaining and RateLimit-Reset headers present on every response and pace yourself. The usage limits guide covers it in detail.
40001#rate-tps-exceeded400IDEMPOTENCY_KEY_INVALIDThe idempotency key does not match the format.
The Idempotency-Key is too long or contains characters outside the allowed set. It accepts 1 to 255 characters from A-Z a-z 0-9 _ -. Nothing was done: nothing was created or charged.
How to fix it
Generate the key with a UUID v4 or any random value within the allowed set. See the idempotency guide.
409IDEMPOTENCY_IN_PROGRESSThe first request with that key is still in progress.
You sent the same idempotency key while the original request is still being processed. It does not run twice: the second one waits.
How to fix it
Wait the time reported in Retry-After and retry with the same key.
422IDEMPOTENCY_KEY_REUSEDThe key already exists, but with a different body.
You used an idempotency key your organization already used, with a different body. Nothing new was created or charged. It is almost always a client bug: one key identifies one operation, not several.
How to fix it
Use a new key for the new operation. Do not retry in a loop: the result will not change.
400URL_INVALIDThe destination URL is malformed.
The destination URL isn't a valid absolute URL (we couldn't parse a scheme and host), or it carries something that would make a reader see a destination other than the real one: a user or password before the domain (https:), a domain with accents, ñ or letters from other alphabets (also written as xn--), or invisible characters. The message says which one it was.
How to fix it
Send an absolute http/https URL including the host, e.g. https:, copied from the address bar, with no user before the domain and the domain written only with unaccented letters, digits and hyphens.
400URL_SCHEME_NOT_ALLOWEDOnly http/https destinations are allowed.
The destination uses a scheme we don't shorten (e.g. javascript:, data:, ftp:, file:).
How to fix it
Only http and https destinations are accepted.
400URL_TOO_LONGThe destination URL exceeds the maximum length.
The destination URL is longer than the 2048-character maximum.
How to fix it
Shorten the destination (drop unnecessary query parameters) so it fits within 2048 characters.
400URL_BLOCKED_HOSTThe destination host is private or reserved.
The destination points at a private/reserved address or an internal hostname (e.g. 127., 10., localhost), or it already is a short link: one of our domains or a shortener such as bit.ly, tinyurl.com or t.co. We block these so short links can't be used to reach internal endpoints or to hide the final destination behind a chain of hops.
How to fix it
Point the link at a publicly reachable host and at the final address you want to take people to.
400ALIAS_INVALIDThe custom alias doesn't match the allowed format.
The alias isn't 3-32 characters of lowercase letters, digits, hyphen or underscore.
How to fix it
Use a value matching ^[a-z0-9_-]{3,, or omit alias to let the API generate a code.
409ALIAS_TAKENThe alias was already used on this domain.
Another link on the same domain already used that alias, whether it still exists or not: links deleted or expired 90 or more days ago are archived, and their code stays reserved forever. Codes are unique per domain and are never released.
How to fix it
Pick a different alias, use a different domain, or omit alias for an auto-generated code.
409ALIAS_RESERVEDThe alias is a reserved word.
The alias collides with a reserved word (e.g. api, stats, admin, docs), or (on a platform domain, which every organization shares) it looks like the name of a brand, a bank, a payment method or a public entity (bancolombia-seguro, pago-pse, dian). A single impersonation link on a shared domain makes security filters flag it, and then everyone’s links stop opening.
How to fix it
Choose a non-reserved alias. If the brand is yours, use your own verified domain.
400EXPIRES_AT_INVALIDexpiresAt must be a future ISO date-time.
expiresAt couldn't be parsed as an ISO-8601 date-time, or it is in the past.
How to fix it
Send a future ISO-8601 value, e.g. 2026-12-31T23:, or omit it for a link that never expires.
404LINK_NOT_FOUNDNo link with that domain and code.
No link with that domain and code belongs to your account. For privacy we return 404 for links owned by other accounts too, so we don't disclose their existence.
How to fix it
Check the domain and code. Deleted links also return 404.
400NOTHING_TO_UPDATENo updatable fields were sent.
The PATCH body had none of the updatable fields (longUrl, status, expiresAt).
How to fix it
Send at least one updatable field.
500CODE_GENERATION_FAILEDCould not allocate a unique code.
We couldn't allocate a unique random code after several attempts. This is rare.
How to fix it
Retry the request. If it persists, quote the meta. in a support ticket.
400STATS_RANGE_INVALIDThe stats range or granularity is invalid.
The statistics window is not valid: from or to are not YYYY-MM-DD, from is after to, the window exceeds the cap (366 days with day, 31 days with hour) or the granularity is neither day nor hour.
How to fix it
Send from and to as YYYY-MM-DD days (Colombia time) with from on or before to, and keep hourly queries within 31 days.
400DOMAIN_NOT_ALLOWEDThe chosen domain isn't available to your account.
The domain you requested isn't a platform-global domain nor one owned by your account (or your account has no default domain configured).
How to fix it
Call GET / to see the domains you can use, or omit domain to use your default.
409DOMAIN_NOT_VERIFIEDYour domain is not verified yet.
The domain is one of your organization’s own, but it is not verified yet. Until it is, it cannot be used to create links: it might not point to the platform yet, and the link would be born broken.
How to fix it
Use another domain from GET /, or omit domain to use the default. To verify yours, contact us.
409ALIAS_RETIREDThe alias belongs to a link of yours that you deleted.
You already used that alias on a link you deleted. The code of a deleted link is never released (a short URL you already handed out cannot reappear with another destination), so no other link can be created with it. But that link can be restored for 90 days after you deleted it; after that it is archived and the alias returns ALIAS_TAKEN.
How to fix it
Restore it with POST / and, if needed, change its destination. Or pick another alias.
409LINK_BLOCKEDThe link is blocked for security.
Hablame blocked this link (status:), for example after an impersonation report. A blocked link does not redirect and cannot be edited, deleted or restored through the API.
How to fix it
If you think it is a mistake, contact us quoting the link and the meta.. Do not retry: the response will not change on its own.
429URLSHORTENER_LINK_QUOTA_EXCEEDEDYour organization reached its plan’s daily link quota.
With an active URL shortener plan, creating links is not charged, and that is why there is a creation quota per Colombia day (100,000, unless you agreed another one). Your organization already used it today, or the batch you sent does not fit in what is left: in bulk creation every link counts, and a batch that does not fit whole is rejected whole, without creating any. Without a plan there is no daily quota: what stops it is the balance.
How to fix it
Wait for Retry-After, which is the time left until midnight in Colombia. If it was a batch, the message says how many links you have left today: you can send a batch of that size. If your operation needs more, contact us.
400URLSHORTENER_BATCH_TOO_LARGEThe batch has more links than one request accepts.
Bulk creation accepts up to 1,000 links per request, and the one you sent has more. None was created and nothing was charged.
How to fix it
Split the batch into requests of 1,000 links or fewer, each with its own Idempotency-Key.
402URLSHORTENER_INSUFFICIENT_FUNDSYour organization has no balance to create the link.
Creating a link is charged on creation, and your organization has no available balance to cover it (or it reached a spend limit it configured itself). The link was not created. In bulk creation the price of all the valid links is reserved at once: without balance for all of them, none is created.
How to fix it
Top up your balance or review your spend limits in the customer portal and try again. Check the price with GET /.
402URLSHORTENER_SPEND_LIMIT_REACHEDA spend limit your organization configured was reached.
Your organization has balance, but creating this link would exceed a spend limit it configured itself: for the whole organization, for the URL shortener, for a cost center, for a user or for this API key. The link was not created.
How to fix it
Review your organization's spend limits in the customer portal and adjust the one that applies. Topping up does not fix it: the limit is yours, not your balance's.
409URLSHORTENER_NOT_PRICEDThe URL shortener has no price configured for your currency.
We found no URL shortener price for your organization’s currency, so we cannot charge the operation and we do not perform it. It is a configuration problem on our side, not in your request.
How to fix it
Do not retry: the response will not change on its own. Contact support and include the meta. from the response.
409URLSHORTENER_CURRENCY_UNDEFINEDYour organization does not have a currency yet.
An organization’s currency is chosen once, when its setup is finished, and everything it consumes is charged in it. Until it has one, we cannot price the operation and we do not perform it.
How to fix it
Finish setting up the organization in the customer portal and try again.
404STORAGE_OBJECT_NOT_FOUNDThe file does not exist for your organization.
There is no file with that id your organization can see. It is the SAME answer, on purpose, for a file that never existed, one from another organization, one already deleted or being deleted, and a malformed id: that way nobody can find out which files exist by trying identifiers.
How to fix it
Take the id from the file list. If the file expired under its retention time, it was deleted and cannot be recovered.
400INVALID_CURSORThe page cursor no longer works.
The cursor was altered, belongs to another organization, was requested with other filters or is more than 24 hours old. A cursor only works to continue the SAME list, with the same filters, for a short time.
How to fix it
Go back to the first page (without cursor) and follow the next values that arrive, without changing the filters between pages.
400INVALID_FILTERA query parameter is not valid.
A service or file type that does not exist, a scope without service, a date that cannot be read, a reversed or too long range (up to 400 days per day or month, up to 7 days per hour), a group other than day, month or hour, a limit outside 1 to 200 or minutes outside 1 to 60. The message says which, in Spanish, with the internal name of the parameter (desde is from, hasta is to, agrupar is group, limite is limit).
How to fix it
Fix the parameter according to the endpoint reference. Retrying as is does not change the result.
400CALLBLASTING_INVALID_NUMBERThe destination number does not have between 7 and 18 digits.
We strip everything that is not a digit from the number (spaces, hyphens or the + sign) and count what is left: there must be between 7 and 18 digits. Outside that range we do not place the call and we charge nothing. The automated calls service is not open in the public reference yet; the code is documented so that its error. link leads to this explanation.
How to fix it
Send the full number, with the country code and no letters. Do not retry with the same value: the response will not change.
400CALLBLASTING_OTP_CODE_REQUIREDThe code to read out in the call is missing.
You generate the verification code, and Hablame does not make one up: it must come in the request, because it is the same one your system will later compare with what the person types. Without it no call is placed and nothing is charged.
How to fix it
Send the code in the code field of the request.
400CALLBLASTING_OTP_CODE_INVALIDThe code is not 1 to 10 digits.
The code read out in the call only accepts digits, up to 10. A letter, a space or a longer code is rejected before calling.
How to fix it
Generate a numeric code of 1 to 10 digits and send it without spaces.
400CALLBLASTING_OTP_MULTIPLE_MARKERSThe message has more than one {otp}.
In the message, {otp} marks the place where the code is read out. With two markers there is no way to know which one you meant, and reading the code twice is worse than not calling, so we reject the message.
How to fix it
Leave a single {otp} in the message, or none if you want the code read at the end.
400CALLBLASTING_OTP_MESSAGE_REQUIREDThe message is empty or over 4,000 characters.
The voice needs a text to say, from 1 to 4,000 characters. An empty or longer message is rejected before calling.
How to fix it
Write a message of up to 4,000 characters.
402CALLBLASTING_TTS_INSUFFICIENT_BALANCEThere is not enough balance for the call.
Before calling we reserve what the call may cost. If your organization has no available balance, or no active billing account, the call is not placed and nothing is charged. The name includes TTS because it is the same code that already existed for the balance missing when generating the voice of a call.
How to fix it
Top up your organization’s balance from Cloud and try again.
503CALLBLASTING_NOT_PRICEDWe found no rate for that destination.
We do not dial without knowing the cost. If there is no rate for the destination of the call, it is not placed and nothing is charged. It is a configuration problem on our side, not in your request.
How to fix it
Do not retry in a loop: the response does not change on its own. Contact support and include the meta. from the response.
503CALLBLASTING_RATE_CURRENCY_MISMATCHThe destination rate is in a different currency than your organization’s.
The balance is reserved in one currency and charged in the same one. If the destination rate is in a currency different from your organization’s, we reject the call instead of converting between currencies. The call is not placed and nothing is charged.
How to fix it
Do not retry: the response does not change on its own. Contact support and include the meta. from the response.
404COUNTRY_NOT_FOUNDNo country exists with that code.
The code sent to GET / does not match any country in the catalog. The parameter expects a two-letter ISO 3166-1 alpha-2 code.
How to fix it
Check the code against GET /, which returns the full catalog.
503INFRA_DB_CONNECTION_ERRORAn internal service was momentarily unreachable.
One of the services we depend on was temporarily unreachable when your request arrived. It is a problem on our side, not with what you sent.
How to fix it
Retry after the seconds reported in Retry-After, ideally with a small random jitter. If it lasts more than a couple of minutes, check the status page or open a support ticket.
40011#infra-db-connection-error504INFRA_DB_QUERY_TIMEOUTAn internal query took too long and was cut off.
An internal query took longer than we allow before returning a response, so we cut it off instead of leaving your client waiting indefinitely. In the URL shortener (the link list, its statistics and the overview) the database itself cuts it, and it happens with very large queries for organizations with many links: a long range, many sections or a broad search.
How to fix it
If the query asks for a lot, narrow it (fewer days, fewer sections, more filters): repeating it as is does not help. If it happens with small queries, open a support ticket quoting the meta..
400VALIDATION_INVALID_PARAMETERA parameter or a body field is not valid.
A query parameter has a value that does not exist, or the body carries an unknown field, a wrong type or is not JSON. The message says which one and what it accepts.
How to fix it
Fix the parameter or field named in the message, using the values documented in the endpoint reference.
400BAD_REQUESTWe could not parse your request.
We could not parse your request. The most common causes are malformed JSON in the body, a Content-Type header that does not match the payload, or a path with invalid characters.
How to fix it
Inspect the raw payload your client is sending. Validating the JSON locally before the call usually reveals the problem right away.
403FORBIDDENGeneric 403: fallback when no ACCOUNT_* applies.
The request authenticated correctly but is not allowed to access this resource. When the cause is a known organization state you get an ACCOUNT_* code instead; this generic one is the fallback.
404NOT_FOUNDThe path you requested does not exist in this API.
The path you requested does not exist in this API. We also return this code, deliberately indistinguishable from a normal 404, for requests whose Host header is not on our allowed list, so the API surface cannot be probed by guessing hostnames.
How to fix it
Compare the path against the reference. Watch out for trailing slashes and casing: paths are case-sensitive.
405METHOD_NOT_ALLOWEDThe path exists but does not accept this HTTP method.
The path exists but does not accept the HTTP method you used, for example a POST to a read-only endpoint. The response includes an Allow header with the valid methods.
409CONFLICTGeneric 409: you get it when the response carries no more specific code.
The service handling the route answered 409 Conflict without a code of its own, so the response carries this generic one. The conflicts we know about have their specific code, such as ALIAS_TAKEN or DOMAIN_NOT_VERIFIED: branch on those when present. The message carries the service explanation when it sends one; otherwise, a general text that points to this page.
422UNPROCESSABLE_ENTITYGeneric 422: you get it when the response carries no more specific code.
The service handling the route answered 422 Unprocessable Entity without a code of its own, so the response carries this generic one. The cases we know about have their specific code, such as IDEMPOTENCY_KEY_REUSED: branch on those when present. The message carries the service explanation when it sends one; otherwise, a general text that points to this page.
429TOO_MANY_REQUESTSGeneric 429: prefer the RATE_* codes when present.
Generic 429. When the limit you hit is one of ours we return RATE_DDOS_EXCEEDED or RATE_TPS_EXCEEDED instead, which carry more context. Branch on the specific ones when present.
501NOT_IMPLEMENTEDThat route exists, but it is not available yet.
The route is reserved in the API, but no service behind it can serve it yet. The message in the response says why. It is neither a temporary failure nor an error in your request.
How to fix it
Do not retry: the response will not change. Use only the endpoints in the reference, which are the ones that work today.
500INTERNAL_SERVER_ERRORSomething went wrong on our side.
Something went unexpectedly wrong while processing your request. The full trace is stored against the same meta. we returned, so we can investigate without you having to reproduce the failure.
How to fix it
Retry once with a small backoff. If you keep seeing it, open a support ticket and include the requestId.
502BAD_GATEWAYGeneric 502: a service we depend on answered with an error.
The service handling the route answered 502 Bad Gateway without a code of its own, so the response carries this generic one. The failure is on our side, not in your request. The message carries the service explanation when it sends one; otherwise, a general text that points to this page.
How to fix it
If you keep seeing it, open a support ticket and include the requestId from the response.
504GATEWAY_TIMEOUTGeneric 504: a service we depend on took too long.
A service we depend on took too long to respond. When the slow component was the database you will see INFRA_DB_QUERY_TIMEOUT instead, which means the same with more context.
How to fix it
Retry with exponential backoff. Several in a row usually indicate a wider degradation: open a support ticket with the requestId.
Other HTTP statuses
If a service answers with an error that has no code of its own and a status other than the generic ones in this catalog, error. is HTTP_ followed by the status (for example, HTTP_405) and error. points to this section. Branch on the HTTP status and read the message: it carries the service’s explanation or a general text.
How the numeric code is structured
Every error. is a six-digit number: the first two identify the error topic and the remaining four the specific condition. It only appears when a bridge from v5 exists; codes introduced in v6 do not carry it.
| Prefix | Topic | Covers |
|---|---|---|
01xxxx | AUTH | API key, tokens, source IP, identity. |
02xxxx | RATE | Per-IP guard and per-endpoint limits. |
03xxxx | VALIDATION | Request shape, JSON, parameters, types. |
04xxxx | ACCOUNT | Organization information, state, blocks. |
05xxxx | BILLING | Balance, payments, currency, exchange rate. |
06xxxx | SMS | SMS service specific errors. |
07xxxx | WhatsApp service. | |
08xxxx | Email service. | |
09xxxx | CALLBLASTING | Calling service. |
10xxxx | URL_SHORTENER | URL Shortener. |
11xxxx | UTILITIES | Ping and other diagnostic endpoints. |
12xxxx | TOOLS | Catalogs and utilities. |
90xxxx | INFRA | Internal dependencies and availability. |
99xxxx | INTERNAL | Unhandled exceptions. |
Prefixes 13xxxx through 89xxxx are reserved for future services, to avoid renumbering.