> ## Documentation Index
> Fetch the complete documentation index at: https://docs.teasy.link/api-v1/llms.txt
> Use this file to discover all available pages before exploring further.

# Response shapes

> Five body forms, and the field rules that hold across all of them.

Whatever you call, the body is one of five shapes. Learn them once and the rest of the API reads
the same way.

## A single resource is unwrapped

```json theme={null}
{
  "id": "rdr_9f2c5a...",
  "object": "redirect",
  "name": "Promo",
  "url": "https://teasy.link/promo",
  "target_url": "https://get.teasy.link",
  "is_active": true,
  "note": null,
  "domain": "teasy.link",
  "group_id": "grp_1a2b3...",
  "created_at": "2026-08-14T10:00:00Z",
  "updated_at": "2026-08-14T10:00:00Z"
}
```

No `data` envelope, but always an `object` discriminator.

## A list

```json theme={null}
{
  "object": "list",
  "data": [],
  "pagination": { "has_more": true, "next_cursor": "eyJ0Ijoi..." }
}
```

Each element carries its own `object`, so an item lifted out of `data` still says what it is. See
[Pagination](/api-v1/api-v1/pagination).

## A deletion receipt

```json theme={null}
{
  "id": "dom_c47b1...",
  "object": "domain",
  "deleted": true,
  "message": "Domain deleted. 12 links were moved to the system domain and deactivated.",
  "deactivated_links": 12
}
```

Two things are worth knowing before you write the handler:

* **`deleted` is always `true`.** A failed deletion is an error status with an error body, never a
  receipt with `deleted: false`, so a branch on `if (!res.deleted)` will never run.
* **`message` is for humans.** Show it, log it, but do not parse or compare it — the wording may
  change, and that is not a breaking change.

## An error

```json theme={null}
{ "error": { "code": "...", "message": "...", "request_id": "..." } }
```

The only wrapped form. See [Errors](/api-v1/api-v1/errors).

## A bulk result

The only body where successes and failures sit together, and therefore the only one where the HTTP
status does not describe the outcome. See [Bulk operations](/api-v1/api-v1/bulk-operations).

## null and omission in a PATCH

`PATCH` accepts the same fields as `POST`, all optional. Leaving a field out and sending it as
`null` mean different things:

| What you send | What happens                |
| ------------- | --------------------------- |
| Field omitted | Current value is left alone |
| `null`        | Value is cleared            |
| A value       | Value is written            |

So an update that should only rename a link carries `name` and nothing else — sending the full
object back with unchanged fields works too, but any field you set to `null` along the way will be
cleared.

On a link, two of those `null`s move the link rather than empty it:

```json theme={null}
{ "domain": null }  // back to the system domain
{ "slug": null }    // to the root of its custom domain if possible
```
