{
  "openapi": "3.1.0",
  "info": {
    "title": "Arvore Link Shortener API",
    "version": "1.0.0"
  },
  "tags": [
    {
      "name": "public-api",
      "description": "Supported for third-party use, documented at /docs"
    }
  ],
  "servers": [
    {
      "url": "https://api.arvore.link",
      "description": "Production"
    },
    {
      "url": "https://api.{stage}.arvore.link",
      "description": "Development",
      "variables": {
        "stage": {
          "default": "rafael"
        }
      }
    }
  ],
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API token, created at /links/conta and prefixed `arv_`. It does not\nexpire; revoke it when you are done with it. This is the scheme to use\nfrom anything that is not a browser.\n\nA token can do what its owner can to links, árvores and analytics, but\nnot administer the account: changing the email, deleting the account,\nrevoking sessions and creating further tokens all answer 403\nSESSION_REQUIRED and need a real sign-in. That way revoking a token\nactually ends its access.\n\nOn the free plan an account can have **one live token at a time** and\nmake **100 requests per hour**, counted per token. Revoking frees the\nslot, so rotating is revoke-then-create.\n"
      },
      "session": {
        "type": "apiKey",
        "in": "cookie",
        "name": "arvore_session",
        "description": "How the arvore.link app itself authenticates — an httpOnly cookie set by\nPOST /auth/verify. Documented for completeness; a browser sends it\nautomatically and nothing else can.\n"
      }
    },
    "responses": {
      "SessionRequired": {
        "description": "SESSION_REQUIRED — this endpoint administers the account, so an API token is refused and a signed-in session is required. Keeping token creation and account changes behind a real sign-in is what makes revoking a token actually end its access.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "RATE_LIMITED — too many requests in the current window. The Retry-After header carries the seconds until it resets.\n",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds until the window resets"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "parameters": {
      "From": {
        "name": "from",
        "in": "query",
        "required": false,
        "description": "Start of time range (Unix timestamp in milliseconds, inclusive)",
        "schema": {
          "type": "string",
          "example": "1771849500000"
        }
      },
      "To": {
        "name": "to",
        "in": "query",
        "required": false,
        "description": "End of time range (Unix timestamp in milliseconds, inclusive)",
        "schema": {
          "type": "string",
          "example": "1771849600000"
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "`error` is always a string — a stable code, never an object. Validation failures add `fields` with the per-input detail, and set `error` to the specific code when the schema has one (`INVALID_TAG`, `INVALID_LINK_ID`) or `VALIDATION_FAILED` when it does not.\n",
        "properties": {
          "error": {
            "type": "string",
            "example": "VALIDATION_FAILED"
          },
          "fields": {
            "type": "object",
            "description": "Present on 400s. Maps each input to what was wrong with it.",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "example": {
              "url": [
                "Invalid URL"
              ]
            }
          }
        }
      },
      "Link": {
        "type": "object",
        "properties": {
          "tags": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "string",
              "pattern": "^[0-9a-z-]{1,24}$"
            },
            "description": "For grouping links so they can be found later. Lowercase, digits and hyphens, at most 10 per link. Always present on read, `[]` for an untagged link.\n",
            "example": [
              "campanha-verao",
              "instagram"
            ]
          },
          "id": {
            "type": "string",
            "description": "Internal link id, 8 characters",
            "example": "a1b2c3d4"
          },
          "slug": {
            "type": "string",
            "description": "Path on the redirect domain",
            "example": "a1b2"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://example.com"
          },
          "short_url": {
            "type": "string",
            "format": "uri",
            "example": "https://arvr.ink/a1b2"
          },
          "redirect_domain": {
            "type": "string",
            "example": "arvr.ink"
          },
          "created_at": {
            "type": "integer",
            "description": "Unix timestamp in milliseconds",
            "example": 1739111400000
          },
          "updated_at": {
            "type": "integer",
            "description": "Unix timestamp in milliseconds",
            "example": 1739111400000
          },
          "deleted_at": {
            "type": "integer",
            "nullable": true,
            "example": null
          }
        }
      },
      "Linktree": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "k9fx2n1a"
          },
          "slug": {
            "type": "string",
            "description": "Path on the redirect domain, 1-50 chars of [0-9a-z-]",
            "example": "meu-perfil"
          },
          "title": {
            "type": "string",
            "example": "minha página"
          },
          "bio": {
            "type": "string",
            "nullable": true,
            "example": "links que importam"
          },
          "avatar_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "example": "https://example.com/foto.jpg"
          },
          "published": {
            "type": "boolean",
            "description": "Unpublished árvores 404 on the public page",
            "example": false
          },
          "created_at": {
            "type": "integer",
            "example": 1739111400000
          },
          "updated_at": {
            "type": "integer",
            "example": 1739111400000
          }
        }
      },
      "LinktreeItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "p3qr7s2t"
          },
          "title": {
            "type": "string",
            "example": "instagram"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Final destination",
            "example": "https://instagram.com/perfil"
          },
          "short_url": {
            "type": "string",
            "format": "uri",
            "description": "Short link the public page points at, so clicks are counted",
            "example": "https://arvr.ink/x7y8"
          },
          "position": {
            "type": "integer",
            "description": "Ascending order on the public page",
            "example": 0
          },
          "active": {
            "type": "boolean",
            "description": "Inactive items are hidden from the public page",
            "example": true
          },
          "created_at": {
            "type": "integer",
            "example": 1739111400000
          },
          "updated_at": {
            "type": "integer",
            "example": 1739111400000
          }
        }
      },
      "LinktreeAnalytics": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "k9fx2n1a"
          },
          "slug": {
            "type": "string",
            "example": "meu-perfil"
          },
          "title": {
            "type": "string",
            "example": "minha página"
          },
          "published": {
            "type": "boolean",
            "example": true
          },
          "views": {
            "type": "integer",
            "description": "Visits to the public page in the range",
            "example": 128
          },
          "clicks": {
            "type": "integer",
            "description": "Sum of item clicks in the range",
            "example": 41
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "example": "p3qr7s2t"
                },
                "title": {
                  "type": "string",
                  "example": "instagram"
                },
                "short_url": {
                  "type": "string",
                  "format": "uri",
                  "nullable": true,
                  "example": "https://arvr.ink/x7y8"
                },
                "active": {
                  "type": "boolean",
                  "example": true
                },
                "count": {
                  "type": "integer",
                  "example": 22
                }
              }
            }
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "example": "a1b2c3d4"
              },
              "email": {
                "type": "string",
                "format": "email",
                "example": "voce@exemplo.com"
              },
              "name": {
                "type": "string",
                "nullable": true,
                "example": "Rafael"
              },
              "avatar_url": {
                "type": "string",
                "format": "uri",
                "nullable": true,
                "example": "https://assets.arvore.link/avatars/w1/user-a1b2c3d4-k9fx2n1a.webp"
              },
              "created_at": {
                "type": "integer",
                "example": 1739111400000
              }
            }
          },
          "workspace": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "example": "w1x2y3z4"
              },
              "name": {
                "type": "string",
                "nullable": true,
                "example": "Pessoal"
              }
            }
          }
        }
      },
      "ApiToken": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Identifies the token for revocation — not the token itself",
            "example": "tk8f2c1a"
          },
          "name": {
            "type": "string",
            "example": "deploy da CI"
          },
          "prefix": {
            "type": "string",
            "description": "The first characters of the real token, to recognise it by",
            "example": "arv_9f2c…"
          },
          "created_at": {
            "type": "integer",
            "example": 1785000000000
          },
          "last_used_at": {
            "type": "integer",
            "nullable": true,
            "description": "Updated at most once every five minutes, so it is accurate to within that, not to the request. Null until first used.\n",
            "example": 1785003600000
          },
          "revoked_at": {
            "type": "integer",
            "nullable": true,
            "description": "When it was revoked, or null while it still works. A revoked token keeps its row so the list can show that it existed and when it stopped being trusted.\n",
            "example": 1785007200000
          }
        }
      },
      "Session": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Last six characters of the token — never the token itself",
            "example": "7s2t9x"
          },
          "created_at": {
            "type": "integer",
            "example": 1739111400000
          },
          "expires_at": {
            "type": "integer",
            "example": 1741703400000
          },
          "current": {
            "type": "boolean",
            "description": "True for the session making the request",
            "example": true
          },
          "device": {
            "type": "string",
            "nullable": true,
            "enum": [
              "desktop",
              "mobile",
              "tablet",
              "smarttv",
              null
            ],
            "description": "From the CloudFront device hints, falling back to the User-Agent",
            "example": "mobile"
          },
          "browser": {
            "type": "string",
            "nullable": true,
            "example": "Chrome 145"
          },
          "platform": {
            "type": "string",
            "nullable": true,
            "example": "iOS"
          },
          "country": {
            "type": "string",
            "nullable": true,
            "description": "From the CloudFront viewer headers, when present",
            "example": "BR"
          },
          "region_name": {
            "type": "string",
            "nullable": true,
            "example": "São Paulo"
          },
          "city": {
            "type": "string",
            "nullable": true,
            "example": "São Paulo"
          }
        }
      },
      "ClickEvent": {
        "type": "object",
        "properties": {
          "ts": {
            "type": "string",
            "description": "Sort key in the format \"{timestamp_ms}#{random}\"",
            "example": "1771849585571#k9fx2n1a"
          },
          "timestamp": {
            "type": "integer",
            "description": "Unix timestamp in milliseconds",
            "example": 1771849585571
          },
          "country": {
            "type": "string",
            "nullable": true,
            "example": "BR"
          },
          "region": {
            "type": "string",
            "nullable": true,
            "example": "SP"
          },
          "region_name": {
            "type": "string",
            "nullable": true,
            "example": "São Paulo"
          },
          "timezone": {
            "type": "string",
            "nullable": true,
            "example": "America/Sao_Paulo"
          },
          "lat": {
            "type": "number",
            "nullable": true,
            "example": -23.673
          },
          "lng": {
            "type": "number",
            "nullable": true,
            "example": -46.5302
          },
          "device": {
            "type": "string",
            "enum": [
              "mobile",
              "tablet",
              "smarttv",
              "desktop"
            ],
            "example": "desktop"
          },
          "platform": {
            "type": "string",
            "nullable": true,
            "example": "macOS"
          },
          "browser": {
            "type": "string",
            "nullable": true,
            "example": "Chrome 145"
          },
          "referer": {
            "type": "string",
            "nullable": true,
            "example": "https://twitter.com"
          }
        }
      }
    }
  },
  "paths": {
    "/account": {
      "get": {
        "summary": "Get the signed-in user and workspace",
        "tags": [
          "public-api"
        ],
        "x-pt": "descobrir de quem é o token e qual workspace ele acessa",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/links": {
      "get": {
        "summary": "List short links",
        "tags": [
          "public-api"
        ],
        "x-pt": "listar seus links curtos",
        "description": "Links in the caller's workspace, newest first. Deleted links and\nlinktree-owned links are excluded — an árvore and each of its items own\na link record, and those are reported through /linktrees.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Links",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "links": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Link"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create short link",
        "tags": [
          "public-api"
        ],
        "x-pt": "criar um link curto",
        "description": "Creates a short link for the given URL. Authentication is optional —\nauthenticated links are scoped to the user's workspace, unauthenticated\nlinks are stored under \"public\". A slug is generated when omitted.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "example": "https://example.com"
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[0-9a-z-]{1,50}$",
                    "example": "meu-link"
                  },
                  "tags": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string",
                      "pattern": "^[0-9a-z-]{1,24}$"
                    },
                    "description": "Lowercase, digits and hyphens, at most 10 per link. Deduplicated and sorted on write. Send `[]` to clear them; omit the field to leave them untouched.\n",
                    "example": [
                      "campanha-verao",
                      "instagram"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Link created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Link"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "LINK_ID_ALREADY_IN_USE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/links/{id}": {
      "patch": {
        "summary": "Update a short link",
        "tags": [
          "public-api"
        ],
        "x-pt": "editar o destino, o id ou as tags de um link",
        "description": "Changes the destination URL, the slug, or both. Linktree-owned links are\nrejected: writing through here would rebuild the `slug:` record as a\nplain short link and make the árvore unreachable.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "a1b2c3d4"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "minProperties": 1,
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[0-9a-z-]{1,50}$"
                  },
                  "tags": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string",
                      "pattern": "^[0-9a-z-]{1,24}$"
                    },
                    "description": "Lowercase, digits and hyphens, at most 10 per link. Deduplicated and sorted on write. Send `[]` to clear them; omit the field to leave them untouched.\n",
                    "example": [
                      "campanha-verao",
                      "instagram"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Link updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Link"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Link not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "LINK_ID_ALREADY_IN_USE or LINKTREE_LINK_NOT_EDITABLE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/links/{id}/analytics": {
      "get": {
        "summary": "Get click analytics for a link",
        "tags": [
          "public-api"
        ],
        "x-pt": "ver os cliques de um link",
        "description": "Click events for one short link, newest first, capped at 500.",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "a1b2c3d4"
            }
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Analytics data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "example": 42
                    },
                    "clicks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ClickEvent"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Link not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/analytics": {
      "get": {
        "summary": "Get click analytics across links",
        "tags": [
          "public-api"
        ],
        "x-pt": "ver os cliques de todos os seus links",
        "description": "Click events for every short link in the workspace, or one link when\nlink_id is given, capped at 500 per link. Linktree-owned links are\nexcluded, matching GET /links.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "link_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "example": "a1b2c3d4"
            }
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Analytics data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "example": 128
                    },
                    "clicks": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/ClickEvent"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "link_id": {
                                "type": "string",
                                "example": "a1b2c3d4"
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Link not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/linktrees": {
      "get": {
        "summary": "List árvores",
        "tags": [
          "public-api"
        ],
        "x-pt": "listar suas árvores",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "responses": {
          "200": {
            "description": "Linktrees",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "linktrees": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Linktree"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create an árvore",
        "tags": [
          "public-api"
        ],
        "x-pt": "criar uma árvore",
        "description": "Reserves the slug and creates the profile, unpublished. A link record is\ncreated alongside it so page views can be counted.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "slug",
                  "title"
                ],
                "properties": {
                  "slug": {
                    "type": "string",
                    "pattern": "^[0-9a-z-]{1,50}$",
                    "example": "meu-perfil"
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "bio": {
                    "type": "string",
                    "maxLength": 300
                  },
                  "avatar_url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Linktree created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Linktree"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "SLUG_ALREADY_IN_USE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/linktrees/{id}": {
      "get": {
        "summary": "Get an árvore with its items",
        "tags": [
          "public-api"
        ],
        "x-pt": "ver uma árvore com seus itens",
        "description": "Includes inactive items, ordered by position.",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Linktree with items",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Linktree"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/LinktreeItem"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update an árvore",
        "tags": [
          "public-api"
        ],
        "x-pt": "editar o perfil, o slug ou publicar uma árvore",
        "description": "Renaming the slug moves the reservation and rewrites the short_url on the\nárvore's link record.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "minProperties": 1,
                "properties": {
                  "slug": {
                    "type": "string",
                    "pattern": "^[0-9a-z-]{1,50}$"
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "bio": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 300
                  },
                  "avatar_url": {
                    "type": "string",
                    "format": "uri",
                    "nullable": true
                  },
                  "published": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Linktree updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Linktree"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "SLUG_ALREADY_IN_USE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete an árvore",
        "tags": [
          "public-api"
        ],
        "x-pt": "apagar uma árvore",
        "description": "Removes the profile, its items, the slug reservation and the link records\ncreated for the page and its items. Click events are left in place.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/linktrees/{id}/analytics": {
      "get": {
        "summary": "Get analytics for one árvore",
        "tags": [
          "public-api"
        ],
        "x-pt": "ver as visitas e os cliques de uma árvore",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Analytics data",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinktreeAnalytics"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/linktrees/{id}/items": {
      "post": {
        "summary": "Add an item to an árvore",
        "tags": [
          "public-api"
        ],
        "x-pt": "adicionar um item na árvore",
        "description": "Creates a short link for the destination URL and points the item at it,\nso clicks are counted. Position defaults to the end of the list.\n",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "url"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 100,
                    "example": "instagram"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "example": "https://instagram.com/perfil"
                  },
                  "position": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Item created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinktreeItem"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Linktree not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/linktrees/{id}/items/{itemId}": {
      "patch": {
        "summary": "Update an item",
        "tags": [
          "public-api"
        ],
        "x-pt": "editar um item da árvore",
        "description": "Changing the URL repoints the item's short link at the new destination.",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "p3qr7s2t"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "minProperties": 1,
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "position": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Item updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinktreeItem"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Linktree or item not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete an item",
        "tags": [
          "public-api"
        ],
        "x-pt": "apagar um item da árvore",
        "description": "Removes the item along with the short link created for it.",
        "security": [
          {
            "bearer": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "k9fx2n1a"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "p3qr7s2t"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Linktree or item not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  }
}
