Skip to content

Endpoints

Endpoints

Name

Update a short link

Change the destination, the status or the expiry. Domain and code do not change.

HTTP method and path

PATCH/api/v6/urlshortener/links/{domain}/{code}

https://developers.hablame.co/api/v6/urlshortener/links/{domain}/{code}

What happens when you run it

  • Changes your organization’s data.
  • The call is not charged.
  • If this change makes the link redirect again (you reactivate it, or extend or remove its expiry), every visit by a person is charged again (visits by bots and link previews are not).

What it does

Changes the destination URL (longUrl, revalidated as on creation), the status (status) or the expiry (expiresAt). Send only what you want to change; at least one field is required. Domain and code cannot change: that would break every short URL already handed out. Editing is free.

Every change is recorded with the previous value, the new one and who made it (the API key or the portal user). A link blocked by Hablame (status: blocked) cannot be edited: it returns 409 LINK_BLOCKED.

Availability and prerequisites

  • Published and available in the production API v6.
  • Every path starts at https://developers.hablame.co.
  • You need a Hablame API key to call it.

Create your API key

Authentication and permissions

  • Send your API key in the Authorization header with the Bearer scheme.

Who can call it: An API key with the urlshortener service enabled.

Limits and operational notes

Usage limit: 35 requests per second.

Path parameters

NameTypeDescription and rules
domainRequiredstring

Domain of the link, as the API returns it in domain. Compared in lowercase. It names the link that answers at that short URL today; for one on a domain that no longer belongs to your organization (domainStatus: released), add domainStatus=released.

Example:h0b.co

codeRequiredstring

Code or alias of the link. Compared in lowercase.

Example:a1b2c3d

Query parameters

NameTypeDescription and rules
domainStatusOptionalstring

With released, the link is the one on a domain that no longer belongs to your organization (the one the list returns with domainStatus: released), even if that name is today another domain with the same code. Without it, domain names the domain that has that name today. Any other value returns 400 VALIDATION_INVALID_PARAMETER.

Allowed values:released

HTTP headers

NameTypeDescription and rules
AuthorizationRequiredstring

Your API key with the Bearer scheme.

Example:Bearer hk_TU_API_KEY

Content-TypeRequiredstring

Type of the body you send.

Fixed value:application/json

Request body

Content type:application/jsonRequired

NameTypeDescription and rules
longUrlOptionalstring

New destination URL. Same rules as on creation.

Format:uri

statusOptionalstring

disabled stops redirecting right away (the visitor gets 404); active turns it back on.

Allowed values:active disabled

expiresAtOptionalstring

New expiry, always in the future. Without a time zone it is read in Colombia time (-05:00). null or an empty string clears it.

Format:date-time

Example
{
  "status": "disabled"
}

Successful responses

200

Link updated, as it ended up.

Response example
{
  "success": true,
  "data": {
    "domain": "h0b.co",
    "code": "a1b2c3d",
    "shortUrl": "https://h0b.co/a1b2c3d",
    "longUrl": "https://example.com/landing?utm_source=sms",
    "isAlias": false,
    "status": "active",
    "domainStatus": "active",
    "expiresAt": null,
    "createdAt": "2026-09-23T15:04:05Z",
    "clicks": 0,
    "uniqueClicks": 0,
    "firstClickAt": null,
    "lastClickAt": null
  },
  "meta": {
    "requestId": "8f0c0e2a4b1d4c8f",
    "clientIp": "203.0.113.45",
    "timestamp": "2026-09-23T18:30:00+00:00",
    "responseTimeMs": 7.2
  }
}

The example values are illustrative.

Response fields

NameTypeDescription and rules
successAlways presentboolean

dataAlways presentobject

data.domainAlways presentstring

Domain of the link, lowercase. If the domain no longer belongs to your organization (domainStatus: released), it is the name it had.

data.codeAlways presentstring

Link code, lowercase: 7 0-9a-z characters when the service generates it, or the alias chosen at creation. Unique per domain.

data.shortUrlAlways presentstring

The full short URL: always https://{domain}/{code}.

Format:uri

data.longUrlAlways presentstring

Destination URL.

Format:uri

data.isAliasAlways presentboolean

true when the code was chosen by whoever created the link (the code field on creation); false when the service generated it.

data.statusAlways presentstring

active, disabled or blocked (and deleted, only in the case below). Expired is not a status: an active link whose expiresAt has passed no longer redirects, but keeps active. blocked is a link Hablame blocked for security: it does not redirect and cannot be edited, deleted or reactivated through the API; if you think it is a mistake, contact us. Deleted links do not appear in responses, except in the replay of a creation with Idempotency-Key whose link was deleted afterwards: it comes as it is, with deleted.

Allowed values:active disabled blocked deleted

data.domainStatusstring

Whether the domain lets the link open, apart from its own status. active: it does. suspended: the domain is suspended; released: the domain no longer belongs to your organization; pending: it is an own domain that is not verified yet. With those three the link does not redirect (the visitor gets 404) even if its status is active. It comes in the list, when getting a link and when creating, editing or restoring it; if it does not come, treat the link as before the field existed. New values may appear: one you do not know does not mean the link does not open.

Allowed values:active pending suspended released

data.expiresAtAlways presentstring

Expiry in UTC, or null if it never expires.

May come as null.

Format:date-time

data.createdAtAlways presentstring

Creation date, in UTC.

Format:date-time

data.clicksAlways presentinteger

Lifetime visits of the link. A background process consolidates them: a visit can take from seconds to a few minutes to show up. Bots and the previews generated by social networks and chat apps are not counted.

data.uniqueClicksAlways presentinteger

Sum of each day’s unique visits: the first visit of the day from each browser. Not distinct people over the life of the link.

data.firstClickAtAlways presentstring

First visit, in UTC. null if it never received one.

May come as null.

Format:date-time

data.lastClickAtAlways presentstring

Last visit, in UTC. null if it never received one.

May come as null.

Format:date-time

metaAlways presentobject

Response metadata.

meta.requestIdAlways presentstring

Unique request identifier (16 hexadecimal characters). It matches the X-Request-Id header. Quote it when contacting support.

Example:b9b1704baffab211

meta.clientIpAlways presentstring

IP the API saw your request come from. Useful if your API key only accepts certain networks.

Example:203.0.113.45

meta.timestampAlways presentstring

Date and time the response was built (ISO 8601 with offset).

Format:date-timeExample:2026-06-04T19:43:59+00:00

meta.responseTimeMsAlways presentnumber

Time (ms) the server took to process the request.

Example:4.24

Error codes

Every error response has the same shape: success set to false and an error object whose code says what happened. They are grouped here by kind, with the codes this endpoint can return.

Shape of an error response
NameTypeDescription and rules
successAlways presentboolean

Fixed value:false

metaAlways presentobject

Response metadata.

meta.requestIdAlways presentstring

Unique request identifier (16 hexadecimal characters). It matches the X-Request-Id header. Quote it when contacting support.

Example:b9b1704baffab211

meta.clientIpAlways presentstring

IP the API saw your request come from. Useful if your API key only accepts certain networks.

Example:203.0.113.45

meta.timestampAlways presentstring

Date and time the response was built (ISO 8601 with offset).

Format:date-timeExample:2026-06-04T19:43:59+00:00

meta.responseTimeMsAlways presentnumber

Time (ms) the server took to process the request.

Example:4.24

errorAlways presentobject

error.codeAlways presentstring

Stable UPPER_SNAKE_CASE identifier. Clients branch on this value.

Example:AUTH_REQUIRED

error.legacyCodeinteger

Legacy v5 numeric code, only when a bridge exists. Omitted for codes born in v6.

Example:40002

error.typeAlways presentstring

URL to the error documentation.

Format:uriExample:https://developers.hablame.co/docs/v6/errors/auth-required

error.messageAlways presentstring

Human readable text, in English. It is for the developer log, not the end user: do not parse it.

error.detailsAlways presentarray<object>

Structured context (validation issues, affected resource). Empty array when there is no extra context.

Validation

  • 400Nothing to change was sent, a field has the wrong type, or a value is invalid.
  • 400NOTHING_TO_UPDATE

    No updatable fields were sent.

    Message the API returns: No updatable fields were provided.

  • 400VALIDATION_INVALID_PARAMETER

    A parameter or a body field is not valid.

  • 400URL_INVALID

    The destination URL is malformed.

    Message the API returns: The destination URL is not valid. Provide an absolute `http`/`https` URL with a host.

  • 400URL_SCHEME_NOT_ALLOWED

    Only http/https destinations are allowed.

    Message the API returns: Only `http` and `https` destination URLs are allowed.

  • 400URL_TOO_LONG

    The destination URL exceeds the maximum length.

    Message the API returns: The destination URL exceeds the maximum allowed length.

  • 400URL_BLOCKED_HOST

    The destination host is private or reserved.

    Message the API returns: The destination host is not allowed (private, reserved, or loopback addresses are blocked).

  • 400EXPIRES_AT_INVALID

    expiresAt must be a future ISO date-time.

    Message the API returns: `expiresAt` must be a future ISO-8601 date-time.

Authentication

  • 401Invalid or missing credentials.
  • 401AUTH_REQUIRED

    No Bearer token was sent, and every call requires one.

    Message the API returns: Authentication is required. Send your API key as `Authorization: Bearer <token>`.

  • 401AUTH_INVALID_KEY

    The API key is not recognized: wrong format, revoked or expired.

    Message the API returns: The provided API key is invalid or has expired. Please verify the value sent in the `Authorization: Bearer` header.

Permissions

  • 403The API key does not have the URL shortener enabled (or it is turned off for your organization), the key cannot be used from the request network, or the organization is not active.
  • 403AUTH_SERVICE_NOT_ALLOWED

    The key is not allowed to use the service behind this endpoint.

    Message the API returns: This API key is not authorized to use the requested service.

  • 403AUTH_IP_NOT_ALLOWED

    The key only works from certain networks and your IP is not one of them.

    Message the API returns: This API key cannot be used from this IP address. The address we saw is in `meta.clientIp`: call from one of the networks allowed for the key, or use a key that allows this one.

  • 403ACCOUNT_NOT_ACTIVE

    Your organization is suspended or closed.

    Message the API returns: The organization associated with this API key is not active. Please contact support.

Usage limits

  • 429Request limit exceeded.
  • 429RATE_TPS_EXCEEDED

    You exceeded your organization quota for this endpoint.

    Message the API returns: You have exceeded the allowed request rate for this endpoint. Please wait before retrying.

Resource not found

  • 404No link of your organization with that domain and code (or it was deleted). A link from another organization also returns 404: its existence is not disclosed.
  • 404LINK_NOT_FOUND

    No link with that domain and code.

    Message the API returns: No short link was found for that domain and code.

Internal errors and availability

This endpoint does not declare responses of this kind.

Other responses

  • 409The link is blocked by Hablame and cannot be changed.

See it in the error catalog

Special considerations

Keys it does not recognize are ignored: a body like {"active": false} (from the previous contract) changes nothing and returns 400 NOTHING_TO_UPDATE. To disable, send {"status": "disabled"}.

A key with the URL shortener also creates and deletes

The urlshortener service grants the whole URL shortener: with it, the API key lists and reads links, and also creates them (each creation is charged), edits, deletes and restores them. There are no read-only keys. Only the owner of your organization creates keys: if one must not create links, do not give it this service. Without it, the key gets 403 AUTH_SERVICE_NOT_ALLOWED.

Related documentation

Need help?

Was this page helpful?

See all support channels

Ask for help about this: this endpoint

We build a message with the details that help us look into your case. Read it, complete it and send it yourself: nothing is sent on its own.

The message never carries your API key or passwords.