Skip to content

Endpoints

Endpoints

Name

List short links

Your links, paginated, with search, filters, sorting and their visit counters.

HTTP method and path

GET/api/v6/urlshortener/links

https://developers.hablame.co/api/v6/urlshortener/links

What happens when you run it

  • Read only: it does not change your organization’s data.
  • The call is not charged.

What it does

Lists your organization’s links (never deleted ones) with their counters already consolidated. By default, newest first. Every filter is optional and they combine with each other.

To walk through many links, paginate with cursor. Each response carries nextCursor while there are more: pass it in the next request, with the same filters, sort and order, and the page starts right after the last link of the previous one. page keeps working as always, but only up to link 10,000 (with perPage=100, up to page 100); beyond that it returns 400 and you continue with cursor, which has no cap.

total is exact up to 10,000. If more links match the filters, total comes as 10000 and totalIsExact as false: “more than 10,000”. hasMore always tells, without error, whether there is another page.

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: 30 requests per minute.

  • Up to 100 items per page; a larger value is capped at 100.
  • total is exact up to 10,000; above that, totalIsExact is false.
  • With page you reach up to link 10,000; to go further, cursor.
  • A search or a sort too expensive for a very large organization is stopped after a few seconds with 504.

Path parameters

This endpoint has no path parameters.

Query parameters

NameTypeDescription and rules
pageOptionalinteger

1-based page number. It reaches up to link 10,000: the page must start, at the latest, at link 10,000. Ignored with cursor.

Default value:1Minimum:1

perPageOptionalinteger

Items per page (max 100).

Default value:20Minimum:1Maximum:100

cursorOptionalstring

The nextCursor of the previous response, as is. The page starts right after the last link of that response. It must go with the same sort and order; a cursor that is not from this organization or this order returns 400.

searchOptionalstring

Searches the code and the destination URL, by fragment and ignoring case and accents (minimum 2 characters; shorter is ignored). If you paste a full short URL (h0b.co/a1b2c3d or https://h0b.co/a1b2c3d), it returns exactly that link, also if its domain no longer belongs to your organization (domainStatus: released).

Minimum length:2

domainOptionalstring

Only links on this domain. Those on a domain that no longer belongs to your organization (domainStatus: released) are not included even if they have the same name: to find one, paste its short URL in search.

stateOptionalstring

Status as a visitor experiences it: active (active and not expired), expired (active with its expiry already past: it no longer redirects), disabled or blocked (blocked by Hablame).

Allowed values:active expired disabled blocked

statusOptionalstring

Stored status. active includes expired links. Kept for compatibility; prefer state.

Allowed values:active disabled blocked

kindOptionalstring

Links with a chosen alias, or with a generated code.

Allowed values:alias generated

trafficOptionalstring

none: links that never received a visit. some: links that received at least one.

Allowed values:none some

createdFromOptionalstring

Created from this day on (YYYY-MM-DD, Colombia time), inclusive.

Format:dateExample:2026-09-01

createdToOptionalstring

Created up to this day (YYYY-MM-DD, Colombia time), inclusive.

Format:dateExample:2026-09-23

sortOptionalstring

Order: by creation date, by lifetime visits, by last visit or by expiry. With lastClick and expires, links without that value go last in both directions.

Allowed values:created clicks lastClick expiresDefault value:created

orderOptionalstring

Sort direction.

Allowed values:desc ascDefault value:desc

HTTP headers

NameTypeDescription and rules
AuthorizationRequiredstring

Your API key with the Bearer scheme.

Example:Bearer hk_TU_API_KEY

Request body

This endpoint takes no request body.

Successful responses

200

Page of links.

Response example
{
  "success": true,
  "data": {
    "items": [
      {
        "domain": "h0b.co",
        "code": "a1b2c3d",
        "shortUrl": "https://h0b.co/a1b2c3d",
        "longUrl": "https://example.com/landing",
        "isAlias": false,
        "status": "active",
        "domainStatus": "active",
        "expiresAt": null,
        "createdAt": "2026-09-20T15:04:05Z",
        "clicks": 128,
        "uniqueClicks": 96,
        "firstClickAt": "2026-09-20T15:31:40Z",
        "lastClickAt": "2026-09-23T18:22:10Z"
      }
    ],
    "page": 1,
    "perPage": 20,
    "total": 1,
    "totalIsExact": true,
    "hasMore": false,
    "nextCursor": 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.itemsAlways presentarray<object>

data.items[].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.items[].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.items[].shortUrlAlways presentstring

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

Format:uri

data.items[].longUrlAlways presentstring

Destination URL.

Format:uri

data.items[].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.items[].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.items[].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.items[].expiresAtAlways presentstring

Expiry in UTC, or null if it never expires.

May come as null.

Format:date-time

data.items[].createdAtAlways presentstring

Creation date, in UTC.

Format:date-time

data.items[].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.items[].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.items[].firstClickAtAlways presentstring

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

May come as null.

Format:date-time

data.items[].lastClickAtAlways presentstring

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

May come as null.

Format:date-time

data.pageAlways presentinteger

The requested page, or 0 if requested with cursor.

data.perPageAlways presentinteger

data.totalAlways presentinteger

Links matching the filters, exact up to 10,000. If there are more, it comes as 10000 and totalIsExact is false.

data.totalIsExactAlways presentboolean

false when there are more than 10,000 and total is the cap.

data.hasMoreAlways presentboolean

true if there are more pages.

data.nextCursorAlways presentstring

To request the next page with cursor, or null if there are no more.

May come as null.

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

  • 400A filter carries a value that does not exist (the message says which one and what it accepts), a date that is not YYYY-MM-DD, a page beyond link 10,000 or a cursor that is not valid.

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

This endpoint does not declare responses of this kind.

Internal errors and availability

  • 504The query took too long and we stopped it. It happens with very large queries for organizations with many links: narrow it (fewer days, fewer sections, more filters). Repeating it as is does not help.

Other responses

This endpoint does not declare responses of this kind.

See it in the error catalog

Special considerations

status keeps its original meaning: active includes expired links, because expiring does not change the stored status. To separate current links from expired ones use state.

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.