---
title: Endpoints de organização, QR e ciclo de vida
description: Referência A4a com parâmetros e exemplos de request e response.
---

Estas 29 operações estão em homologação em `https://api.staging.agilink.io/v1`. Exemplos usam recursos fictícios. A referência interativa contém os schemas completos de cada campo, inclusive objetos internos. Leia também o [guia da integração](/api/organizacao-ciclo-de-vida/) e a [migração de tokens](/api/migracao-tokens/).

Todas as requisições usam `Authorization: Bearer <credencial>`. Sessão humana e chave limitada são indicadas por operação. OAuth depende da Tarefa 2. Mutações exigem Idempotency-Key; atualizações e exclusões exigem If-Match. QR/download devolvem bytes PNG ou SVG, não JSON. Nunca envie credenciais em query strings.

## GET /links/{linkId}/history

Histórico administrativo sanitizado de alterações.

Permissão: `link_history:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `linkId` | path | sim | LinkId |
| `limit` | query | não | integer |
| `cursor` | query | não | Cursor |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/links/go.example.com~-ofertas~-tenis/history' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": [
    {
      "id": "90000000-0000-4000-8000-000000000002",
      "linkId": "go.example.com~-ofertas~-tenis",
      "appId": "app_loja",
      "action": "update",
      "fields": [
        "management"
      ],
      "revision": "20000000-0000-4000-8000-000000000001",
      "createdAt": "2026-10-19T20:00:00Z"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /links/{linkId}/tags

Ler/substituir associação de tags do mesmo app.

Permissão: `tags:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `linkId` | path | sim | LinkId |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/links/go.example.com~-ofertas~-tenis/tags' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "linkId": "go.example.com~-ofertas~-tenis",
    "appId": "app_loja",
    "revision": "20000000-0000-4000-8000-000000000001",
    "tagIds": []
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## PUT /links/{linkId}/tags

Ler/substituir associação de tags do mesmo app.

Permissão: `tags:update`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `linkId` | path | sim | LinkId |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `tagIds` | array | sim | Consulte o schema para restrições e campos internos |

```json
{
  "tagIds": [
    "90000000-0000-4000-8000-000000000001"
  ]
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request PUT 'https://api.staging.agilink.io/v1/links/go.example.com~-ofertas~-tenis/tags' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"' \
  --header 'Content-Type: application/json' \
  --data '{"tagIds":["90000000-0000-4000-8000-000000000001"]}'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "linkId": "go.example.com~-ofertas~-tenis",
    "appId": "app_loja",
    "revision": "20000000-0000-4000-8000-000000000001",
    "tagIds": []
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `415`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /links/{linkId}/routing-rules

Ler/alterar regras avançadas previstas no pacote de expansão.

Permissão: `routing_rules:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `linkId` | path | sim | LinkId |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/links/go.example.com~-ofertas~-tenis/routing-rules' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "linkId": "go.example.com~-ofertas~-tenis",
    "appId": "app_loja",
    "revision": "20000000-0000-4000-8000-000000000001",
    "rules": [
      {
        "id": "br",
        "platform": "desktop",
        "country": "BR",
        "startsAt": null,
        "expiresAt": null,
        "destinationUrl": "https://shop.example.com/br",
        "utm": {}
      }
    ]
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## PUT /links/{linkId}/routing-rules

Ler/alterar regras avançadas previstas no pacote de expansão.

Permissão: `routing_rules:update`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `linkId` | path | sim | LinkId |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `rules` | array | sim | Consulte o schema para restrições e campos internos |

```json
{
  "rules": [
    {
      "id": "br",
      "platform": "desktop",
      "country": "BR",
      "startsAt": null,
      "expiresAt": null,
      "destinationUrl": "https://shop.example.com/br",
      "utm": {}
    }
  ]
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request PUT 'https://api.staging.agilink.io/v1/links/go.example.com~-ofertas~-tenis/routing-rules' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"' \
  --header 'Content-Type: application/json' \
  --data '{"rules":[{"id":"br","platform":"desktop","country":"BR","startsAt":null,"expiresAt":null,"destinationUrl":"https://shop.example.com/br","utm":{}}]}'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "linkId": "go.example.com~-ofertas~-tenis",
    "appId": "app_loja",
    "revision": "20000000-0000-4000-8000-000000000001",
    "rules": [
      {
        "id": "br",
        "platform": "desktop",
        "country": "BR",
        "startsAt": null,
        "expiresAt": null,
        "destinationUrl": "https://shop.example.com/br",
        "utm": {}
      }
    ]
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `415`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /tags

Listar/criar etiquetas por app.

Permissão: `tags:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `appId` | query | sim | AppId |
| `q` | query | não | SearchText |
| `archived` | query | não | all / true / false |
| `limit` | query | não | integer |
| `cursor` | query | não | Cursor |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/tags?appId=app_loja' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": [
    {
      "id": "90000000-0000-4000-8000-000000000001",
      "appId": "app_loja",
      "kind": "tags",
      "name": "Verão",
      "description": "Campanha de verão",
      "archived": false,
      "utm": {},
      "revision": "20000000-0000-4000-8000-000000000001",
      "createdAt": "2026-10-19T20:00:00Z",
      "updatedAt": "2026-10-19T20:00:00Z"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## POST /tags

Listar/criar etiquetas por app.

Permissão: `tags:create`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `appId` | AppId | sim | Consulte o schema para restrições e campos internos |
| `name` | string | sim | Máximo 100 caracteres |
| `description` | string | não | Máximo 1000 caracteres |
| `archived` | boolean | não | Consulte o schema para restrições e campos internos |
| `utm` | UtmParameters | não | Consulte o schema para restrições e campos internos |

```json
{
  "appId": "app_loja",
  "name": "Verão"
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request POST 'https://api.staging.agilink.io/v1/tags' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'Content-Type: application/json' \
  --data '{"appId":"app_loja","name":"Verão"}'
```

Resposta: `201`. Criado. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |
| `Location` | Recurso criado. | /v1/tags/90000000-0000-4000-8000-000000000001 |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "tags",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {},
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `413`, `415`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /tags/{tagId}

Consultar/renomear/remover etiqueta.

Permissão: `tags:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `tagId` | path | sim | Revision |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/tags/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "tags",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {},
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## PATCH /tags/{tagId}

Consultar/renomear/remover etiqueta.

Permissão: `tags:update`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `tagId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `name` | string | não | Máximo 100 caracteres |
| `description` | string | não | Máximo 1000 caracteres |
| `archived` | boolean | não | Consulte o schema para restrições e campos internos |
| `utm` | UtmParameters | não | Consulte o schema para restrições e campos internos |

```json
{
  "name": "Verão 2027"
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request PATCH 'https://api.staging.agilink.io/v1/tags/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Verão 2027"}'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "tags",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {},
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `415`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## DELETE /tags/{tagId}

Consultar/renomear/remover etiqueta.

Permissão: `tags:delete`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `tagId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request DELETE 'https://api.staging.agilink.io/v1/tags/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"'
```

Resposta: `204`. Removido. Corpo vazio; publicação da remoção acompanha outbox.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

Sem corpo de resposta.

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /folders

Listar/criar pastas.

Permissão: `folders:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `appId` | query | sim | AppId |
| `q` | query | não | SearchText |
| `archived` | query | não | all / true / false |
| `limit` | query | não | integer |
| `cursor` | query | não | Cursor |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/folders?appId=app_loja' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": [
    {
      "id": "90000000-0000-4000-8000-000000000001",
      "appId": "app_loja",
      "kind": "folders",
      "name": "Verão",
      "description": "Campanha de verão",
      "archived": false,
      "utm": {},
      "revision": "20000000-0000-4000-8000-000000000001",
      "createdAt": "2026-10-19T20:00:00Z",
      "updatedAt": "2026-10-19T20:00:00Z"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## POST /folders

Listar/criar pastas.

Permissão: `folders:create`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `appId` | AppId | sim | Consulte o schema para restrições e campos internos |
| `name` | string | sim | Máximo 100 caracteres |
| `description` | string | não | Máximo 1000 caracteres |
| `archived` | boolean | não | Consulte o schema para restrições e campos internos |
| `utm` | UtmParameters | não | Consulte o schema para restrições e campos internos |

```json
{
  "appId": "app_loja",
  "name": "Verão"
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request POST 'https://api.staging.agilink.io/v1/folders' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'Content-Type: application/json' \
  --data '{"appId":"app_loja","name":"Verão"}'
```

Resposta: `201`. Criado. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |
| `Location` | Recurso criado. | /v1/folders/90000000-0000-4000-8000-000000000001 |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "folders",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {},
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `413`, `415`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /folders/{folderId}

Gerir pasta e restrições de remoção.

Permissão: `folders:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `folderId` | path | sim | Revision |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/folders/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "folders",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {},
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## PATCH /folders/{folderId}

Gerir pasta e restrições de remoção.

Permissão: `folders:update`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `folderId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `name` | string | não | Máximo 100 caracteres |
| `description` | string | não | Máximo 1000 caracteres |
| `archived` | boolean | não | Consulte o schema para restrições e campos internos |
| `utm` | UtmParameters | não | Consulte o schema para restrições e campos internos |

```json
{
  "name": "Verão 2027"
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request PATCH 'https://api.staging.agilink.io/v1/folders/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Verão 2027"}'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "folders",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {},
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `415`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## DELETE /folders/{folderId}

Gerir pasta e restrições de remoção.

Permissão: `folders:delete`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `folderId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request DELETE 'https://api.staging.agilink.io/v1/folders/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"'
```

Resposta: `204`. Removido. Corpo vazio; publicação da remoção acompanha outbox.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

Sem corpo de resposta.

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /campaigns

Listar/criar campanhas.

Permissão: `campaigns:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `appId` | query | sim | AppId |
| `q` | query | não | SearchText |
| `archived` | query | não | all / true / false |
| `limit` | query | não | integer |
| `cursor` | query | não | Cursor |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/campaigns?appId=app_loja' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": [
    {
      "id": "90000000-0000-4000-8000-000000000001",
      "appId": "app_loja",
      "kind": "campaigns",
      "name": "Verão",
      "description": "Campanha de verão",
      "archived": false,
      "utm": {
        "utm_source": "newsletter",
        "utm_campaign": "verao"
      },
      "revision": "20000000-0000-4000-8000-000000000001",
      "createdAt": "2026-10-19T20:00:00Z",
      "updatedAt": "2026-10-19T20:00:00Z"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## POST /campaigns

Listar/criar campanhas.

Permissão: `campaigns:create`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `appId` | AppId | sim | Consulte o schema para restrições e campos internos |
| `name` | string | sim | Máximo 100 caracteres |
| `description` | string | não | Máximo 1000 caracteres |
| `archived` | boolean | não | Consulte o schema para restrições e campos internos |
| `utm` | UtmParameters | não | Consulte o schema para restrições e campos internos |

```json
{
  "appId": "app_loja",
  "name": "Verão",
  "utm": {
    "utm_source": "newsletter",
    "utm_campaign": "verao"
  }
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request POST 'https://api.staging.agilink.io/v1/campaigns' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'Content-Type: application/json' \
  --data '{"appId":"app_loja","name":"Verão","utm":{"utm_source":"newsletter","utm_campaign":"verao"}}'
```

Resposta: `201`. Criado. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |
| `Location` | Recurso criado. | /v1/campaigns/90000000-0000-4000-8000-000000000001 |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "campaigns",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {
      "utm_source": "newsletter",
      "utm_campaign": "verao"
    },
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `413`, `415`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /campaigns/{campaignId}

Gerir metadados, UTMs padrão e arquivamento.

Permissão: `campaigns:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `campaignId` | path | sim | Revision |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/campaigns/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "campaigns",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {
      "utm_source": "newsletter",
      "utm_campaign": "verao"
    },
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## PATCH /campaigns/{campaignId}

Gerir metadados, UTMs padrão e arquivamento.

Permissão: `campaigns:update`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `campaignId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `name` | string | não | Máximo 100 caracteres |
| `description` | string | não | Máximo 1000 caracteres |
| `archived` | boolean | não | Consulte o schema para restrições e campos internos |
| `utm` | UtmParameters | não | Consulte o schema para restrições e campos internos |

```json
{
  "name": "Verão 2027"
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request PATCH 'https://api.staging.agilink.io/v1/campaigns/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Verão 2027"}'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000001",
    "appId": "app_loja",
    "kind": "campaigns",
    "name": "Verão",
    "description": "Campanha de verão",
    "archived": false,
    "utm": {
      "utm_source": "newsletter",
      "utm_campaign": "verao"
    },
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `415`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## DELETE /campaigns/{campaignId}

Gerir metadados, UTMs padrão e arquivamento.

Permissão: `campaigns:delete`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `campaignId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request DELETE 'https://api.staging.agilink.io/v1/campaigns/90000000-0000-4000-8000-000000000001' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"'
```

Resposta: `204`. Removido. Corpo vazio; publicação da remoção acompanha outbox.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

Sem corpo de resposta.

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /campaigns/{campaignId}/links

Links vinculados, paginados.

Permissão: `campaigns:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `campaignId` | path | sim | Revision |
| `limit` | query | não | integer |
| `cursor` | query | não | Cursor |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/campaigns/90000000-0000-4000-8000-000000000001/links' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": [
    {
      "id": "go.example.com~-ofertas~-tenis",
      "appId": "app_loja",
      "domain": "go.example.com",
      "prefix": "ofertas",
      "slug": "tenis",
      "url": "https://go.example.com/ofertas/tenis",
      "title": "Tênis da campanha",
      "description": null,
      "imageUrl": null,
      "desktopUrl": "https://shop.example.com/produtos/tenis",
      "appPath": "produtos/tenis",
      "parameters": {},
      "webOnly": false,
      "behavior": "manual",
      "group": "operational",
      "origin": "api",
      "revision": "20000000-0000-4000-8000-000000000001",
      "createdAt": "2026-10-19T20:00:00Z",
      "updatedAt": "2026-10-19T20:00:00Z",
      "publication": {
        "status": "pending",
        "desiredRevision": "20000000-0000-4000-8000-000000000001",
        "confirmedRevision": null,
        "updatedAt": "2026-10-19T20:00:00Z"
      }
    }
  ],
  "pagination": {
    "nextCursor": null,
    "hasMore": false
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /analytics/campaigns/{campaignId}

Métricas vinculadas à campanha.

Permissão: `analytics:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `campaignId` | path | sim | Revision |
| `start` | query | sim | AnalyticsInstant |
| `end` | query | sim | AnalyticsInstant |
| `timezone` | query | não | string |
| `group` | query | não | all / main / operational |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/analytics/campaigns/90000000-0000-4000-8000-000000000001?start=2026-10-01T00%3A00%3A00Z&end=2026-10-02T00%3A00%3A00Z' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": {
    "appId": "app_loja",
    "period": {
      "start": "2026-10-01T00:00:00Z",
      "end": "2026-10-02T00:00:00Z",
      "timezone": "America/Sao_Paulo",
      "startInclusive": true,
      "endExclusive": true
    },
    "filters": {
      "campaignId": "90000000-0000-4000-8000-000000000001",
      "folderId": null,
      "tagId": null,
      "group": "all",
      "linkId": null,
      "domain": null,
      "prefix": null,
      "device": null,
      "source": null,
      "country": null,
      "eventType": "all"
    },
    "generatedAt": "2026-10-02T12:00:00Z",
    "coverage": {
      "source": "event_rows",
      "grouping": "current_link_group",
      "deletedLinks": "excluded",
      "historicalAggregates": "not_merged",
      "uniqueVisitors": "distinct_click_hash_estimate",
      "nativeTrust": "client_reported",
      "completenessGuaranteed": false,
      "limitations": [
        "Totais calculados das linhas disponíveis; agregados históricos não são somados.",
        "Abertura não comprova instalação."
      ]
    },
    "totals": {
      "clicks": 3,
      "uniqueVisitors": 1,
      "identifiedClicks": 2,
      "appOpens": 2,
      "contentViews": 1,
      "legacyContentLoads": 0,
      "activeLinks": 1,
      "firstEventAt": "2026-10-01T01:00:00Z",
      "lastEventAt": "2026-10-01T02:00:00Z"
    }
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /links/{linkId}/qr

Gerar QR do endereço público do link em PNG/SVG com opções limitadas.

Permissão: `qr_codes:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `linkId` | path | sim | LinkId |
| `format` | query | não | png / svg |
| `size` | query | não | integer |
| `margin` | query | não | integer |
| `errorCorrectionLevel` | query | não | M / Q / H |
| `dark` | query | não | #000000 / #0f172a |
| `light` | query | não | "#ffffff" |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/links/go.example.com~-ofertas~-tenis/qr' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. QR do endereço público; não é uma contagem de scans.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

Resposta binária PNG ou SVG. Use `--output agilink-qr.png` no cURL (ou `?format=svg` e extensão SVG). Content-Type indica o formato; o endereço codificado é o URL HTTPS estável do link.

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /qr-codes

Listar/criar configurações persistidas de QR.

Permissão: `qr_codes:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `appId` | query | sim | AppId |
| `q` | query | não | SearchText |
| `limit` | query | não | integer |
| `cursor` | query | não | Cursor |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/qr-codes?appId=app_loja' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

```json
{
  "data": [
    {
      "id": "90000000-0000-4000-8000-000000000002",
      "appId": "app_loja",
      "linkId": "go.example.com~-ofertas~-tenis",
      "url": "https://go.example.com/ofertas/tenis",
      "name": "Vitrine",
      "style": {
        "size": 512,
        "margin": 4,
        "errorCorrectionLevel": "M",
        "dark": "#0f172a",
        "light": "#ffffff"
      },
      "revision": "20000000-0000-4000-8000-000000000001",
      "createdAt": "2026-10-19T20:00:00Z",
      "updatedAt": "2026-10-19T20:00:00Z"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## POST /qr-codes

Listar/criar configurações persistidas de QR.

Permissão: `qr_codes:create`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `appId` | AppId | sim | Consulte o schema para restrições e campos internos |
| `linkId` | LinkId | sim | Consulte o schema para restrições e campos internos |
| `name` | string | sim | Máximo 100 caracteres |
| `style` | QrStyle | não | Consulte o schema para restrições e campos internos |

```json
{
  "appId": "app_loja",
  "linkId": "go.example.com~-ofertas~-tenis",
  "name": "Vitrine",
  "style": {
    "size": 512,
    "margin": 4,
    "errorCorrectionLevel": "M",
    "dark": "#0f172a",
    "light": "#ffffff"
  }
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request POST 'https://api.staging.agilink.io/v1/qr-codes' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'Content-Type: application/json' \
  --data '{"appId":"app_loja","linkId":"go.example.com~-ofertas~-tenis","name":"Vitrine","style":{"size":512,"margin":4,"errorCorrectionLevel":"M","dark":"#0f172a","light":"#ffffff"}}'
```

Resposta: `201`. Criado. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |
| `Location` | Recurso criado. | /v1/qr-codes/90000000-0000-4000-8000-000000000002 |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000002",
    "appId": "app_loja",
    "linkId": "go.example.com~-ofertas~-tenis",
    "url": "https://go.example.com/ofertas/tenis",
    "name": "Vitrine",
    "style": {
      "size": 512,
      "margin": 4,
      "errorCorrectionLevel": "M",
      "dark": "#0f172a",
      "light": "#ffffff"
    },
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `413`, `415`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /qr-codes/{qrId}

Consultar QR e estilo salvo.

Permissão: `qr_codes:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `qrId` | path | sim | Revision |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/qr-codes/90000000-0000-4000-8000-000000000002' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000002",
    "appId": "app_loja",
    "linkId": "go.example.com~-ofertas~-tenis",
    "url": "https://go.example.com/ofertas/tenis",
    "name": "Vitrine",
    "style": {
      "size": 512,
      "margin": 4,
      "errorCorrectionLevel": "M",
      "dark": "#0f172a",
      "light": "#ffffff"
    },
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## PATCH /qr-codes/{qrId}

Atualizar nome e estilo do QR; vínculo imutável.

Permissão: `qr_codes:update`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `qrId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Corpo: `application/json`. Campos desconhecidos são rejeitados.

| Campo | Tipo | Obrigatório | Restrição |
| --- | --- | --- | --- |
| `name` | string | não | Máximo 100 caracteres |
| `style` | QrStyle | não | Consulte o schema para restrições e campos internos |

```json
{
  "name": "Vitrine principal"
}
```

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request PATCH 'https://api.staging.agilink.io/v1/qr-codes/90000000-0000-4000-8000-000000000002' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"' \
  --header 'Content-Type: application/json' \
  --data '{"name":"Vitrine principal"}'
```

Resposta: `200`. Sucesso. Exemplo fictício.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |
| `ETag` | Revisão forte, a enviar em If-Match na alteração. | "20000000-0000-4000-8000-000000000001" |

```json
{
  "data": {
    "id": "90000000-0000-4000-8000-000000000002",
    "appId": "app_loja",
    "linkId": "go.example.com~-ofertas~-tenis",
    "url": "https://go.example.com/ofertas/tenis",
    "name": "Vitrine",
    "style": {
      "size": 512,
      "margin": 4,
      "errorCorrectionLevel": "M",
      "dark": "#0f172a",
      "light": "#ffffff"
    },
    "revision": "20000000-0000-4000-8000-000000000001",
    "createdAt": "2026-10-19T20:00:00Z",
    "updatedAt": "2026-10-19T20:00:00Z"
  },
  "meta": {
    "requestId": "req_00000000000040008000000000000001"
  }
}
```

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `415`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## DELETE /qr-codes/{qrId}

Excluir configuração do QR; imagens distribuídas continuam válidas.

Permissão: `qr_codes:delete`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `qrId` | path | sim | Revision |
| `Idempotency-Key` | header | sim | UUID v4 por intenção. Recibo por 24h. Mudança de payload/precondição retorna 409. Segredo de chave não é reexibido. |
| `If-Match` | header | sim | ETag forte obtido em consulta. Ausência 428; revisão antiga 412. |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request DELETE 'https://api.staging.agilink.io/v1/qr-codes/90000000-0000-4000-8000-000000000002' \
  --header 'Authorization: Bearer <credencial>' \
  --header 'Idempotency-Key: 10000000-0000-4000-8000-000000000001' \
  --header 'If-Match: "20000000-0000-4000-8000-000000000001"'
```

Resposta: `204`. Removido. Corpo vazio; publicação da remoção acompanha outbox.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

Sem corpo de resposta.

Erros previstos: `400`, `401`, `403`, `404`, `409`, `412`, `413`, `422`, `428`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).

## GET /qr-codes/{qrId}/download

Baixar arquivo no formato/tamanho permitido.

Permissão: `qr_codes:read`. Credencial: sessão humana ou chave de API com acesso ao aplicativo.

| Parâmetro | Local | Obrigatório | Significado |
| --- | --- | --- | --- |
| `qrId` | path | sim | Revision |
| `format` | query | não | png / svg |

Sem corpo de requisição.

Exemplo completo de requisição (substitua os identificadores fictícios):

```sh
curl --request GET 'https://api.staging.agilink.io/v1/qr-codes/90000000-0000-4000-8000-000000000002/download' \
  --header 'Authorization: Bearer <credencial>'
```

Resposta: `200`. QR do endereço público; não é uma contagem de scans.

| Header | Significado | Exemplo |
| --- | --- | --- |
| `X-Request-Id` | Identificador gerado pelo servidor, inclusive para falhas e replays. | — |
| `Cache-Control` | Respostas administrativas não podem ser armazenadas. | no-store, no-transform |

Resposta binária PNG ou SVG. Use `--output agilink-qr.png` no cURL (ou `?format=svg` e extensão SVG). Content-Type indica o formato; o endereço codificado é o URL HTTPS estável do link.

Erros previstos: `400`, `401`, `403`, `404`, `422`, `429`, `500`, `503`. Veja [códigos e repetição](/api/errors/).
