# TNY API

> Programmatic access to TNY links, analytics, and domains. Authenticate with an API key from your dashboard using `Authorization: Bearer <key>`. Scopes: links:read, links:write, analytics:read, domains:read.

- Base URL: `https://tny.co.in/api/v1`
- OpenAPI spec: https://tny.co.in/api/v1/openapi.json
- Human docs: https://tny.co.in/docs/api
- Version: 1.0.0

## Authentication

All requests require an API key created in your TNY dashboard. Send it as a Bearer token:

```
Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx
```

Keys are prefixed `tny_live_` and are shown only once at creation. A key is scoped: each request must be made with a key that holds the scope listed on the endpoint below.

## Scopes

| Scope | Grants |
| --- | --- |
| `links:read` | Read links and their click counts |
| `links:write` | Create, edit, and delete links |
| `analytics:read` | Read detailed analytics |
| `domains:read` | Read branded domains |

## Rate limits

Per API key: 120 read requests/min and 60 write requests/min. Over the limit returns `429` with a `Retry-After` header (seconds).

## Errors

Errors return the matching HTTP status with a JSON body `{ "error": "..." }`. Common statuses: `400` invalid request, `401` missing/invalid key, `403` missing scope or plan, `404` not found, `429` rate limited.

## Endpoints

### GET /links

List links

Requires the `links:read` scope.

Parameters:

- `limit` — query · integer

Responses:

- `200` — A page of links
- `401` — Error
- `403` — Error
- `429` — Error

Example:

```bash
curl -X GET https://tny.co.in/api/v1/links \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx"
```

### POST /links

Create a link

Requires the `links:write` scope.

Request body (JSON):

- `url` · string <uri> (required)
- `isQr` · boolean
- `title` · string
- `code` · string — Custom slug (Pro/Team only).

Responses:

- `201` — Created link
- `400` — Error
- `401` — Error
- `403` — Error
- `429` — Error

Example:

```bash
curl -X POST https://tny.co.in/api/v1/links \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/page"}'
```

### GET /links/{id}

Get a link

Requires the `links:read` scope.

Parameters:

- `id` — path · string (required)

Responses:

- `200` — Link
- `401` — Error
- `404` — Error

Example:

```bash
curl -X GET https://tny.co.in/api/v1/links/:id \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx"
```

### PATCH /links/{id}

Update a link

Requires the `links:write` scope. Provide any of destination, title, active.

Parameters:

- `id` — path · string (required)

Request body (JSON):

- `destination` · string <uri>
- `title` · string
- `active` · boolean

Responses:

- `200` — Updated link
- `400` — Error
- `401` — Error
- `404` — Error

Example:

```bash
curl -X PATCH https://tny.co.in/api/v1/links/:id \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"destination":"https://example.com/page"}'
```

### DELETE /links/{id}

Delete a link

Requires the `links:write` scope.

Parameters:

- `id` — path · string (required)

Responses:

- `204` — Deleted
- `401` — Error
- `404` — Error

Example:

```bash
curl -X DELETE https://tny.co.in/api/v1/links/:id \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx"
```

### GET /links/{id}/analytics

Get link analytics

Device/geo/referrer breakdown + 14-day trend. Requires the `analytics:read` scope and a Pro or Team plan.

Parameters:

- `id` — path · string (required)

Responses:

- `200` — Analytics
- `401` — Error
- `403` — Error
- `404` — Error

Example:

```bash
curl -X GET https://tny.co.in/api/v1/links/:id/analytics \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx"
```

### GET /domains

List branded domains

Requires the `domains:read` scope.

Responses:

- `200` — Domains
- `401` — Error
- `403` — Error

Example:

```bash
curl -X GET https://tny.co.in/api/v1/domains \
  -H "Authorization: Bearer tny_live_xxxxxxxxxxxxxxxxxxxxxxxx"
```

## Schemas

### Link

- `id` · string
- `code` · string
- `shortUrl` · string <uri>
- `destination` · string <uri>
- `domain` · string | null
- `title` · string | null
- `isQr` · boolean
- `clicks` · integer
- `active` · boolean
- `createdAt` · string <date-time>

### CreateLink

- `url` · string <uri> (required)
- `isQr` · boolean
- `title` · string
- `code` · string — Custom slug (Pro/Team only).

### UpdateLink

- `destination` · string <uri>
- `title` · string
- `active` · boolean

### AnalyticsRow

- `label` · string
- `count` · integer

### LinkAnalytics

- `total` · integer
- `last7Days` · integer
- `devices` · AnalyticsRow[]
- `countries` · AnalyticsRow[]
- `referrers` · AnalyticsRow[]
- `trend` · object[]

### Domain

- `id` · string
- `host` · string
- `verified` · boolean
- `createdAt` · string <date-time>
