Shortens a target URL into a short link you can then use in a message text or in the BulkGate Portal.

## API URL

The URL used to send the HTTP requests:

```url
https://portal.bulkgate.com/api/1.0/shortener/shorten
```

> [!NOTE]
> If the request does not reach its destination, repeat it on the [backup server](https://www.bulkgate.com/en/docs/api-administration-tokens/api-backup-server/) `backup1.bulkgate.com`.

## Supported HTTP methods

- `POST` - `application/json`

```http
POST /api/1.0/shortener/shorten HTTP/1.1
Host: portal.bulkgate.com
Content-Type: application/json
```

> [!NOTE]
> The API has a quota of `20` requests per minute.

## Parameters table

| PARAMETER NAME    | VALUE                                                                           | MANDATORY | DEFAULT VALUE |
|:------------------|:--------------------------------------------------------------------------------|:----------|:--------------|
| application_id    | [Application ID](https://www.bulkgate.com/en/docs/api-administration-tokens/api-administration/)                                   | **Yes**   | -             | 
| application_token | [Application authentication token](https://www.bulkgate.com/en/docs/api-administration-tokens/api-tokens/)	                       | **Yes**   | -             |
| target_url        | Url to be shortened	                                                            | **Yes**   | -             |
| url_type          | Domain of the short link, see [Supported domains](#supported-domains)           | No        | `ur7.wf`      |

### Supported domains

The `url_type` values are instance configuration and do change — the current list for your account is returned by the [`domains` endpoint](https://www.bulkgate.com/en/docs/shortener/shortener-domains/). At the time of writing:

| DOMAIN              | TARGET ADDRESS RESTRICTION                               |
|:--------------------|:----------------------------------------------------------|
| `ur7.wf`            | No restriction. Default value.                            |
| `ms6.fr`            | No restriction.                                           |
| `ur7.yt`            | Whitelisted target domains only.                          |
| `ur7.tf`            | Whitelisted target domains only.                          |
| `ms6.wf`            | Whitelisted target domains only.                          |
| `ms6.tf`            | Whitelisted target domains only.                          |
| `track-message.com` | Whitelisted target domains only.                          |

For the restricted domains the target address must be on your account's whitelist, otherwise the request fails with `domain_is_not_white_listed`. A handful of public services (Google, YouTube, Facebook, GitHub and others) are always whitelisted.

## Request example

```http-json
POST /api/1.0/shortener/shorten HTTP/1.1
Host: portal.bulkgate.com
Content-Type: application/json

{
  "application_id": 451,
  "application_token": "NKN02TWE6NfBkfl-your-secret-token-Wf05GaqLIWLW4aBj",
  "target_url": "www.bulkgate.com",
  "url_type": "ur7.wf"
}
```

## Response

**In case of success:**

```json
{
    "data": {
        "short_url": "http://ur7.wf/W",
        "target_url": "http://www.bulkgate.com/",
        "final_url": "http://www.bulkgate.com",
        "title": "SMS & other channels for business communication | BulkGate",
        "expiration": "2026-10-10T09:00:00+02:00"
    }
}
```

Links created through the API are valid for **30 days** — `expiration` carries the expiry date in ISO 8601.

The three URL fields are not the same thing:

| FIELD        | VALUE                                                                                                  |
|:-------------|:---------------------------------------------------------------------------------------------------------|
| `short_url`  | The shortened link itself, built from `url_type` and the generated key                                 |
| `target_url` | The address as it was stored — the scheme is added when missing and the URL is normalised, so `www.bulkgate.com` becomes `http://www.bulkgate.com/` |
| `final_url`  | The address you sent, only with the scheme added. **Redirects are not followed**, so this is not the page the visitor ends up on |
| `title`      | Title read from the target page                                                                        |


**In case of error:**

```json
{
    "type": "url_is_not_valid",
    "code": 400,
    "error": "Url is not valid",
    "detail": null
}
```

```json
{
    "type": "the_per_minute_quota_has_been_exceeded",
    "code": 400,
    "error": "The per minute quota has been exceeded",
    "detail": null
}
```

Where:

- **type** and **error** (description of the error) can be found in the [error types table](https://www.bulkgate.com/en/docs/api-administration-tokens/api-error-types/)
- **code** is the HTTP error code
- **detail** is additional information about the error

### Shortener API error types

Besides the [general types](https://www.bulkgate.com/en/docs/api-administration-tokens/api-error-types/), the Shortener API returns its own:

| TYPE                                    | WHEN IT HAPPENS                                                        |
|:----------------------------------------|:-----------------------------------------------------------------------|
| `url_is_not_valid`                      | `target_url` could not be parsed.                                      |
| `url_type_is_incorrect`                 | `url_type` is not in the account's domain list.                        |
| `domain_is_not_white_listed`            | The target domain is not whitelisted (for restricted domains).         |
| `url_is_not_allowed`                    | The target address points to a local/internal address.                 |
| `url_can_not_be_redirected_out_of_target_domain` | The target address redirects outside its own domain.          |
| `url_can_not_be_created`                | The link could not be created.                                         |
| `the_per_minute_quota_has_been_exceeded`| The quota of 20 requests per minute is used up.                        |
