Putting a long URL directly into a text message costs you twice: **it eats your byte budget**, and **you learn nothing about who clicked**.

```text
[Event] Autumn sale! https://shop.example.com/promotions/autumn-2026?utm_source=sms&utm_campaign=autumn
→ blows past 90 bytes into LMS pricing, and engagement is invisible.

[Event] Autumn sale! https://sendgo.io/s/k7Rm2xQ
→ fits in an SMS, and clicks are counted.
```

## Creating a short link

`POST /api/v2/short-urls`

| Field | Required | Notes |
| --- | --- | --- |
| `targetUrl` | ✅ | Original URL. `http`/`https` only, up to 2,048 characters |
| `title` | | A label for the management screen |
| `expiresAt` | | After this, `410 Gone`. `Y-m-d H:i:s` |
| `forceNew` | | `true` issues a new code even for a URL already shortened |

### Node.js / TypeScript

```typescript
const created = await sendgo.shortUrl.create({
  targetUrl: 'https://shop.example.com/promotions/autumn-2026',
  title: 'Autumn sale landing',
  expiresAt: '2026-09-30 23:59:59',
});

const { code, shortUrl } = created.data;

await sendgo.sms.sendSms({
  content: `[Event] Autumn sale! ${shortUrl}`,
  contacts: [{ contact: '01012345678' }],
});
```

### Python

```python
created = client.short_url.create(
    target_url="https://shop.example.com/promotions/autumn-2026",
    title="Autumn sale landing",
)
link = created["data"]["shortUrl"]

client.sms.send_sms(
    content=f"[Event] Autumn sale! {link}",
    contacts=[{"contact": "01012345678"}],
)
```

### PHP

```php
<?php

$short = $sendgo->shortUrl->create([
    'targetUrl' => 'https://shop.example.com/promotions/autumn-2026',
    'title'     => 'Autumn sale landing',
]);

$link = $short['data']['shortUrl'];

$sendgo->sms->sendSms([
    'content'  => "[Event] Autumn sale! {$link}",
    'contacts' => [['contact' => '01012345678']],
]);
```

## Reading click statistics

```typescript
const stats = await sendgo.shortUrl.stats(code, { from: '2026-09-01' });

await sendgo.shortUrl.list({ count: 10 });   // list
await sendgo.shortUrl.show(code);            // detail
await sendgo.shortUrl.deactivate(code);      // stop redirecting, keep the stats
```

```python
stats = client.short_url.stats(code, from_="2026-09-01")
client.short_url.list(count=10)
client.short_url.show(code)
```

```php
<?php

$stats = $sendgo->shortUrl->stats($code, ['from' => '2026-09-01']);
$sendgo->shortUrl->list(['count' => 10]);
$sendgo->shortUrl->show($code);
$sendgo->shortUrl->deactivate($code);
```

## Separate statistics per campaign

If several campaigns point at the same landing page, use `forceNew` to get distinct codes. Otherwise the numbers merge and you cannot tell which campaign worked.

```typescript
const augustLink = await sendgo.shortUrl.create({
  targetUrl: 'https://shop.example.com/sale',
  title: 'August sale - Alimtalk',
  forceNew: true,
});

const septemberLink = await sendgo.shortUrl.create({
  targetUrl: 'https://shop.example.com/sale',   // same destination
  title: 'September sale - SMS',
  forceNew: true,                                // different code
});
```

## Easy to get wrong

- **Put the link in a template variable, not the Alimtalk template body.** Hard-coding a URL in the template means re-review for every campaign. Pass the short link through `#{var3}` instead.
- **Set an expiry.** A live link to a finished event sends late clickers to a dead page.
- **Do not put short links in your sitemap.** For some links the unguessable code *is* the access control.

## Next

- [Send SMS, LMS and MMS](/en/cookbook/send-sms)
- [Advertising message rules](/en/cookbook/ad-message-rules)