Skip to content

Endpoints

Endpoints

Name

Link statistics

Range totals, a daily or hourly series and breakdowns by country, device, OS, browser or source.

HTTP method and path

GET/api/v6/urlshortener/links/{domain}/{code}/stats

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

What happens when you run it

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

What it does

Analytics for one link over a window of days: the range totals, a daily or hourly series and the values with the most visits for each dimension. Days and hours are Colombia’s (America/Bogota).

  • totals.clicks and totals.uniqueClicks are the range’s; firstClickAt and lastClickAt, the link’s lifetime.
  • The series is sparse: days or hours without visits are omitted. Fill them with zero if you are going to chart it.
  • Each dimension returns the top values with the most visits and, if there is a remainder, an __other row. A visit with no value for a dimension (no country, or no source) does not appear in it: its rows can add up to less than the total.
  • referrer is only the source domain (www.facebook.com), without the path. Direct visits have no row: they are totals.clicks minus the sum of referrer.
  • device is mobile, tablet or desktop; os, Android, iOS, Windows, macOS, Linux, ChromeOS or Other; browser, Chrome, Safari, Firefox, Edge, Opera, Samsung Internet, UC Browser or Other. country is the ISO code (CO).

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

  • Windows of up to 366 days by day, and up to 31 days by hour.
  • Up to 100 values per dimension.
  • On top of that, each query spends units from a quota of 120 per minute for your organization, according to its cost: 2 for the query and 3 for every 31 days of the range. 30 days spend 5; a year, 38. Without units, 429 with Retry-After.

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

fromOptionalstring

First day of the window, YYYY-MM-DD in Colombia time, inclusive. Defaults to 29 days before to (a 30-day window).

Format:dateExample:2026-09-01

toOptionalstring

Last day of the window, YYYY-MM-DD in Colombia time, inclusive. Defaults to today.

Format:dateExample:2026-09-23

granularityOptionalstring

Size of each point of the series. day allows windows of up to 366 days; hour, up to 31.

Allowed values:day hourDefault value:day

dimensionsOptionalstring

Comma-separated breakdown dimensions: country, subdivision, city, device, os, browser, referrer. Defaults to country,device,os,browser,referrer. Unknown names are ignored.

Example:country,device,referrer

topOptionalinteger

How many values each dimension (and each ranking) returns. Max 100.

Default value:10Minimum:1Maximum:100

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

Link analytics.

Response example
{
  "success": true,
  "data": {
    "domain": "h0b.co",
    "code": "a1b2c3d",
    "shortUrl": "https://h0b.co/a1b2c3d",
    "range": { "from": "2026-08-25", "to": "2026-09-23", "granularity": "day", "timezone": "America/Bogota" },
    "totals": {
      "clicks": 128,
      "uniqueClicks": 96,
      "firstClickAt": "2026-09-20T15:31:40Z",
      "lastClickAt": "2026-09-23T18:22:10Z"
    },
    "series": [
      { "at": "2026-09-20", "clicks": 40, "uniqueClicks": 31 },
      { "at": "2026-09-23", "clicks": 88, "uniqueClicks": 65 }
    ],
    "dimensions": {
      "country": [{ "value": "CO", "clicks": 110 }, { "value": "__other", "clicks": 12 }],
      "device": [{ "value": "mobile", "clicks": 101 }, { "value": "desktop", "clicks": 27 }]
    }
  },
  "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

data.codeAlways presentstring

data.shortUrlAlways presentstring

Format:uri

data.rangeAlways presentobject

The queried window, already resolved.

data.range.fromAlways presentstring

Format:date

data.range.toAlways presentstring

Format:date

data.range.granularityAlways presentstring

Allowed values:day hour

data.range.timezoneAlways presentstring

Example:America/Bogota

data.totalsAlways presentobject

data.totals.clicksAlways presentinteger

Visits in the range.

data.totals.uniqueClicksAlways presentinteger

Range uniques (daily sum).

data.totals.firstClickAtAlways presentstring

May come as null.

Format:date-time

data.totals.lastClickAtAlways presentstring

May come as null.

Format:date-time

data.seriesAlways presentarray<object>

data.series[].atAlways presentstring

YYYY-MM-DD with day granularity; YYYY-MM-DDTHH:00:00 (Colombia time, no zone) with hour.

Example:2026-09-22

data.series[].clicksAlways presentinteger

data.series[].uniqueClicksAlways presentinteger

data.dimensionsAlways presentobject

One array per requested dimension.

data.dimensions.{any key}array<object>

data.dimensions.{any key}[].valueAlways presentstring

The value as recorded (CO, mobile, Chrome, www.facebook.com…), or __other for the sum of everything outside the top.

data.dimensions.{any key}[].clicksAlways presentinteger

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 date that is not YYYY-MM-DD, from after to, a window above the limit or an unknown granularity.
  • 400STATS_RANGE_INVALID

    The stats range or granularity is invalid.

    Message the API returns: The requested statistics range or granularity is invalid.

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

  • 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

uniqueClicks counts the first visit of the day from each browser. Over a multi-day range it is the sum of each day, not distinct people. Responses can be up to one minute old (X-Cache header).

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.