{
  "openapi": "3.1.0",
  "info": {
    "title": "Link in Bio API",
    "version": "1.0.0",
    "description": "One API for link-in-bio pages: read a Linktree, Lnk.Bio, AllMyLinks or solo.to page in full, list just its links, follow any link through its redirects to the retailer or network at the end, and identify which service an address belongs to — including the 26 services that are recognised but cannot be read, with the reason."
  },
  "servers": [
    {
      "url": "https://api.fetchlayer.dev/link-in-bio"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "Send your FetchLayer key as Authorization: Bearer ss-your-key."
      }
    }
  },
  "paths": {
    "/profile": {
      "post": {
        "operationId": "profile",
        "tags": [
          "Pages"
        ],
        "summary": "Get a link-in-bio page in full",
        "description": "One creator’s link page, by its address: who they are, how the page looks, what it sells, what stands in front of it, and every link on it. Read the response shape before anything else, because it is the one thing callers get wrong: **the links are at `profile.links[]` and the count at `profile.linkCount`, not at the root**, and the creator’s name is at `profile.identity.displayName`. `notes` and `pagesFetched` are the only fields at the top level worth reading. Alongside them `profile` carries provider, providerName, handle, url, status, identity, theme, monetization, gates, socialLinks and source. Pass `resolveDestinations` to follow every link through its redirects and fill in `destination` on each one. A page that is live but publishes nothing comes back as a normal 200 with `linkCount: 0` and a note saying so — and that genuinely means empty, because a page whose link list could not be read at all is a 502 instead. The two statuses are different on purpose, so a caller can alert on one and ignore the other. A page the service has taken down answers with `status: \"suspended\"` rather than an error. Billing: 1 credit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile": {
                    "type": "string",
                    "description": "The full page address — https://linktr.ee/spotify, or linktr.ee/spotify. Not a bare handle: \"spotify\" alone is a 400 saying handles are not unique across services. A bare handle works only when `provider` is given too."
                  },
                  "provider": {
                    "type": "string",
                    "description": "The service a bare handle belongs to (linktree, lnkbio, allmylinks, solo and 26 more). Required when `profile` is a handle rather than an address, and ignored when it is an address."
                  },
                  "resolveDestinations": {
                    "type": "boolean",
                    "description": "Follow every link through its redirects to where it really lands, filling in `destination`. Off by default: it turns one page fetch into one request per link, so a 68-link page is far slower than a 3-link one.",
                    "example": "false"
                  },
                  "format": {
                    "type": "string",
                    "description": "json or markdown. Markdown returns a rendered summary instead of the structured record.",
                    "example": "json"
                  },
                  "timeoutMs": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Time limit for the request, in milliseconds (max 600000)."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "profile"
                ]
              },
              "examples": {
                "default": {
                  "value": {
                    "profile": "https://linktr.ee/spotify"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transport": {
                      "type": "string",
                      "description": "The upstream source. Always \"link-in-bio-page\"."
                    },
                    "resultType": {
                      "type": "string",
                      "description": "Which route produced this record — profile, links, detect-provider, unwrap-link or resolve-url."
                    },
                    "requestedUrl": {
                      "type": "string",
                      "description": "The address this result corresponds to."
                    },
                    "scrapedAt": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of the read."
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "Always false on a successful response."
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Caveats you can act on — a page that is live but publishes no links, a service that publishes no theme or plan details, a destination that could not be reached. Read these: an empty result always arrives with one."
                    },
                    "pagesFetched": {
                      "type": "number",
                      "description": "Pages fetched, which is what the request costs: one credit per page. detect-provider reports 0 when it recognised the address from its shape alone, and resolve-url fetches nothing at all."
                    },
                    "profile": {
                      "type": "object",
                      "properties": {
                        "provider": {
                          "type": "string",
                          "description": "Short, stable id for the service (linktree, lnkbio, allmylinks, solo…). A service that rebrands keeps its id, so a stored value does not break."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "The service’s public name, for display."
                        },
                        "handle": {
                          "type": "string",
                          "description": "The creator’s handle on that service."
                        },
                        "url": {
                          "type": "string",
                          "description": "The page’s canonical public address."
                        },
                        "status": {
                          "type": "string",
                          "description": "active (live and readable), suspended (the page exists but the service took it down) or inactive."
                        },
                        "identity": {
                          "type": "object",
                          "properties": {
                            "displayName": {
                              "type": "string",
                              "description": "The name shown at the top of the page. This is where the creator’s name lives — not at the root."
                            },
                            "bio": {
                              "type": "string",
                              "description": "The bio under the name, or null."
                            },
                            "avatarUrl": {
                              "type": "string",
                              "description": "The avatar, or null."
                            },
                            "verified": {
                              "type": "boolean",
                              "description": "True where the service marks the account verified, null where it has no such concept."
                            },
                            "plan": {
                              "type": "string",
                              "description": "\"free\" or \"paid\" where the service publishes it — the best public signal that a page belongs to someone serious — or null."
                            },
                            "country": {
                              "type": "string",
                              "description": "ISO 3166-1 alpha-2, where published."
                            },
                            "createdAt": {
                              "type": "string",
                              "description": "When the page was created, ISO 8601, where published."
                            },
                            "unclaimed": {
                              "type": "boolean",
                              "description": "True where the service marks the page as never claimed by its owner."
                            }
                          },
                          "additionalProperties": false
                        },
                        "theme": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "The page’s colours and font, or null where the service publishes none."
                        },
                        "monetization": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Whether the page sells anything or takes tips."
                        },
                        "gates": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "description": "Gates standing in front of the whole page. Empty when it is freely readable."
                        },
                        "socialLinks": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "description": "The social icon row, separate from the button list."
                        },
                        "links": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true,
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "The service’s own id for the entry, stable across reads, or null."
                              },
                              "kind": {
                                "type": "string",
                                "description": "link, embed, product, social, heading or group. Coarse on purpose, so it stays stable as services change their own vocabularies."
                              },
                              "providerType": {
                                "type": "string",
                                "description": "The service’s own label for the entry, verbatim (\"classic\"). Free-form — do not switch on it."
                              },
                              "title": {
                                "type": "string",
                                "description": "The label shown on the button."
                              },
                              "description": {
                                "type": "string",
                                "description": "Supporting copy under the title, or null."
                              },
                              "url": {
                                "type": "string",
                                "description": "Where the page sends a visitor. Null on a heading, a group, or a gated link whose target is withheld."
                              },
                              "position": {
                                "type": "number",
                                "description": "0-based position in the page’s own order."
                              },
                              "parentId": {
                                "type": "string",
                                "description": "The id of the group or heading this sits under, or null at the top level."
                              },
                              "thumbnail": {
                                "type": "object",
                                "additionalProperties": true,
                                "description": "The image on the button, or null."
                              },
                              "tracked": {
                                "type": "boolean",
                                "description": "True when clicks are routed through the service’s own click tracker rather than straight to `url`."
                              },
                              "monetized": {
                                "type": "boolean",
                                "description": "True when the link earns the creator money — an affiliate link, a product, a paid unlock."
                              },
                              "product": {
                                "type": "object",
                                "additionalProperties": true,
                                "description": "Price and currency where the entry sells something, or null."
                              },
                              "gates": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "additionalProperties": true
                                },
                                "description": "Gates on this specific link — an age check, a payment, an email capture. Empty when it is freely clickable."
                              },
                              "destination": {
                                "type": "object",
                                "additionalProperties": true,
                                "description": "Where `url` actually lands, when destinations were resolved: url, host, status, hops, truncated, title, shortened and unresolvedReason. Null when they were not asked for — check `destinationsResolved` rather than reading null as \"goes nowhere\"."
                              }
                            }
                          },
                          "description": "Every entry on the page, in the page’s own order. This is the link list — not a root-level `links`."
                        },
                        "linkCount": {
                          "type": "number",
                          "description": "How many entries are in `profile.links`. 0 on a live page that publishes nothing, with a note saying so."
                        },
                        "source": {
                          "type": "string",
                          "description": "\"page-payload\" or \"page-markup\" — how completely the page could be read. A field absent under one may be present under the other, so this says which you got."
                        }
                      },
                      "additionalProperties": false
                    }
                  },
                  "additionalProperties": false
                },
                "examples": {
                  "default": {
                    "value": {
                      "blocked": false,
                      "requestedUrl": "https://linktr.ee/spotify",
                      "scrapedAt": "2026-09-16T20:41:12.804Z",
                      "transport": "link-in-bio-page",
                      "notes": [],
                      "resultType": "profile",
                      "pagesFetched": 1,
                      "profile": {
                        "provider": "linktree",
                        "providerName": "Linktree",
                        "handle": "spotify",
                        "url": "https://linktr.ee/spotify",
                        "status": "active",
                        "identity": {
                          "displayName": "@spotify",
                          "bio": null,
                          "avatarUrl": "https://ugc.production.linktr.ee/...",
                          "verified": null,
                          "plan": null,
                          "country": null,
                          "createdAt": null,
                          "unclaimed": null
                        },
                        "theme": null,
                        "monetization": {
                          "sellsProducts": false,
                          "acceptsTips": false
                        },
                        "gates": [],
                        "socialLinks": [],
                        "links": [
                          {
                            "id": "9964805",
                            "kind": "link",
                            "providerType": "classic",
                            "title": "Playlist 1",
                            "description": null,
                            "url": "https://open.spotify.com/user/0658h6ocit7uqryixhxt0uivc/playlist/4Zv9I6yJwjuPXZbB3e1Rx8?si=tQaQ38ioQRCrbS7k87rFhw",
                            "position": 0,
                            "parentId": null,
                            "thumbnail": null,
                            "tracked": false,
                            "monetized": false,
                            "product": null,
                            "gates": [],
                            "destination": null
                          }
                        ],
                        "linkCount": 6,
                        "source": "page-payload"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing Bearer token"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/links": {
      "post": {
        "operationId": "links",
        "tags": [
          "Pages"
        ],
        "summary": "List the links on a page",
        "description": "Just the link list for a page, optionally narrowed to one kind. This is the route where `links` sits at the top level — on /profile the same list is at `profile.links[]`, and confusing the two is the most common mistake with this API. Returns provider, handle, url, links, linkCount, totalLinks and destinationsResolved. `totalLinks` is how many entries the page has before `kind` and `limit` narrowed the list, so a filter that matches nothing is visibly a filter rather than an empty page. `destinationsResolved` says whether an absent `destination` means \"not asked for\" or \"could not be reached\". Pass `resolveDestinations` to follow every link through its redirects — that is how the retailer or affiliate network behind a shortened link is found, and it is the part almost nothing else does. Up to 500 links, 100 by default. A live page that publishes nothing is a 200 with `linkCount: 0` and a note; a page whose links could not be read at all is a 502. Billing: 1 credit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profile": {
                    "type": "string",
                    "description": "The full page address — https://linktr.ee/spotify, or linktr.ee/spotify. Not a bare handle: \"spotify\" alone is a 400 saying handles are not unique across services. A bare handle works only when `provider` is given too."
                  },
                  "provider": {
                    "type": "string",
                    "description": "The service a bare handle belongs to (linktree, lnkbio, allmylinks, solo and 26 more). Required when `profile` is a handle rather than an address, and ignored when it is an address."
                  },
                  "kind": {
                    "type": "string",
                    "description": "Return only entries of this kind: link, embed, product, social, heading or group."
                  },
                  "limit": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Maximum links returned, up to 500. Use -1 for the maximum.",
                    "example": "100"
                  },
                  "resolveDestinations": {
                    "type": "boolean",
                    "description": "Follow every link through its redirects to where it really lands, filling in `destination`. Off by default: it turns one page fetch into one request per link, so a 68-link page is far slower than a 3-link one.",
                    "example": "false"
                  },
                  "format": {
                    "type": "string",
                    "description": "json or markdown. Markdown returns a rendered summary instead of the structured record.",
                    "example": "json"
                  },
                  "timeoutMs": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Time limit for the request, in milliseconds (max 600000)."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "profile"
                ]
              },
              "examples": {
                "default": {
                  "value": {
                    "profile": "https://linktr.ee/spotify",
                    "resolveDestinations": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transport": {
                      "type": "string",
                      "description": "The upstream source. Always \"link-in-bio-page\"."
                    },
                    "resultType": {
                      "type": "string",
                      "description": "Which route produced this record — profile, links, detect-provider, unwrap-link or resolve-url."
                    },
                    "requestedUrl": {
                      "type": "string",
                      "description": "The address this result corresponds to."
                    },
                    "scrapedAt": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of the read."
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "Always false on a successful response."
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Caveats you can act on — a page that is live but publishes no links, a service that publishes no theme or plan details, a destination that could not be reached. Read these: an empty result always arrives with one."
                    },
                    "pagesFetched": {
                      "type": "number",
                      "description": "Pages fetched, which is what the request costs: one credit per page. detect-provider reports 0 when it recognised the address from its shape alone, and resolve-url fetches nothing at all."
                    },
                    "provider": {
                      "type": "string",
                      "description": "Short, stable id for the service."
                    },
                    "handle": {
                      "type": "string",
                      "description": "The creator’s handle on that service."
                    },
                    "url": {
                      "type": "string",
                      "description": "The page’s canonical public address."
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The service’s own id for the entry, stable across reads, or null."
                          },
                          "kind": {
                            "type": "string",
                            "description": "link, embed, product, social, heading or group. Coarse on purpose, so it stays stable as services change their own vocabularies."
                          },
                          "providerType": {
                            "type": "string",
                            "description": "The service’s own label for the entry, verbatim (\"classic\"). Free-form — do not switch on it."
                          },
                          "title": {
                            "type": "string",
                            "description": "The label shown on the button."
                          },
                          "description": {
                            "type": "string",
                            "description": "Supporting copy under the title, or null."
                          },
                          "url": {
                            "type": "string",
                            "description": "Where the page sends a visitor. Null on a heading, a group, or a gated link whose target is withheld."
                          },
                          "position": {
                            "type": "number",
                            "description": "0-based position in the page’s own order."
                          },
                          "parentId": {
                            "type": "string",
                            "description": "The id of the group or heading this sits under, or null at the top level."
                          },
                          "thumbnail": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "The image on the button, or null."
                          },
                          "tracked": {
                            "type": "boolean",
                            "description": "True when clicks are routed through the service’s own click tracker rather than straight to `url`."
                          },
                          "monetized": {
                            "type": "boolean",
                            "description": "True when the link earns the creator money — an affiliate link, a product, a paid unlock."
                          },
                          "product": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "Price and currency where the entry sells something, or null."
                          },
                          "gates": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "additionalProperties": true
                            },
                            "description": "Gates on this specific link — an age check, a payment, an email capture. Empty when it is freely clickable."
                          },
                          "destination": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "Where `url` actually lands, when destinations were resolved: url, host, status, hops, truncated, title, shortened and unresolvedReason. Null when they were not asked for — check `destinationsResolved` rather than reading null as \"goes nowhere\"."
                          }
                        }
                      },
                      "description": "The entries, in the page’s own order. On this route the list is at the top level."
                    },
                    "linkCount": {
                      "type": "number",
                      "description": "Links returned, after `kind` and `limit`."
                    },
                    "totalLinks": {
                      "type": "number",
                      "description": "Links on the page before `kind` and `limit` narrowed the list."
                    },
                    "destinationsResolved": {
                      "type": "boolean",
                      "description": "True when destinations were resolved for the returned links, so an absent `destination` is never ambiguous."
                    }
                  },
                  "additionalProperties": false
                },
                "examples": {
                  "default": {
                    "value": {
                      "blocked": false,
                      "requestedUrl": "https://linktr.ee/spotify",
                      "scrapedAt": "2026-09-16T20:41:44.119Z",
                      "transport": "link-in-bio-page",
                      "notes": [],
                      "resultType": "links",
                      "pagesFetched": 1,
                      "provider": "linktree",
                      "handle": "spotify",
                      "url": "https://linktr.ee/spotify",
                      "links": [
                        {
                          "id": "9964805",
                          "kind": "link",
                          "providerType": "classic",
                          "title": "Playlist 1",
                          "description": null,
                          "url": "https://open.spotify.com/user/0658h6ocit7uqryixhxt0uivc/playlist/4Zv9I6yJwjuPXZbB3e1Rx8?si=tQaQ38ioQRCrbS7k87rFhw",
                          "position": 0,
                          "parentId": null,
                          "thumbnail": null,
                          "tracked": false,
                          "monetized": false,
                          "product": null,
                          "gates": [],
                          "destination": {
                            "url": "https://open.spotify.com/playlist/4Zv9I6yJwjuPXZbB3e1Rx8?si=tQaQ38ioQRCrbS7k87rFhw",
                            "host": "open.spotify.com",
                            "status": 200,
                            "hops": [
                              "https://open.spotify.com/playlist/4Zv9I6yJwjuPXZbB3e1Rx8?si=tQaQ38ioQRCrbS7k87rFhw"
                            ],
                            "truncated": false,
                            "title": "Spotify",
                            "shortened": false,
                            "unresolvedReason": null
                          }
                        }
                      ],
                      "linkCount": 6,
                      "totalLinks": 6,
                      "destinationsResolved": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing Bearer token"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/unwrap-link": {
      "post": {
        "operationId": "unwrap-link",
        "tags": [
          "Destinations"
        ],
        "summary": "Follow one link to where it really goes",
        "description": "Follows a single link through its redirects and reports where it lands: the final url, its host and page title, every hop in order, whether the chain went through a link shortener or an affiliate redirector, and whether it hit the step limit and may continue. Use it on a shortened or campaign link when you want the retailer or network at the end rather than the wrapper at the start — a creator's page sends you to lnk.to, and lnk.to sends you to Spotify. Up to 20 hops, 10 by default. When the chain is still going, `truncated` is true and `url` is the furthest point reached rather than the end. When nothing could be established, `unresolvedReason` says why rather than leaving a null unexplained. Billing: 1 credit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "The link to follow to its real destination."
                  },
                  "maxHops": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "How many redirects to follow, up to 20.",
                    "example": "10"
                  },
                  "format": {
                    "type": "string",
                    "description": "json or markdown. Markdown returns a rendered summary instead of the structured record.",
                    "example": "json"
                  },
                  "timeoutMs": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Time limit for the request, in milliseconds (max 600000)."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "url"
                ]
              },
              "examples": {
                "default": {
                  "value": {
                    "url": "https://bennyblanco.lnk.to/TeOlvido"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transport": {
                      "type": "string",
                      "description": "The upstream source. Always \"link-in-bio-page\"."
                    },
                    "resultType": {
                      "type": "string",
                      "description": "Which route produced this record — profile, links, detect-provider, unwrap-link or resolve-url."
                    },
                    "requestedUrl": {
                      "type": "string",
                      "description": "The address this result corresponds to."
                    },
                    "scrapedAt": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of the read."
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "Always false on a successful response."
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Caveats you can act on — a page that is live but publishes no links, a service that publishes no theme or plan details, a destination that could not be reached. Read these: an empty result always arrives with one."
                    },
                    "pagesFetched": {
                      "type": "number",
                      "description": "Pages fetched, which is what the request costs: one credit per page. detect-provider reports 0 when it recognised the address from its shape alone, and resolve-url fetches nothing at all."
                    },
                    "url": {
                      "type": "string",
                      "description": "The link that was followed."
                    },
                    "destination": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "description": "The address the chain ended at."
                        },
                        "host": {
                          "type": "string",
                          "description": "Host of that address, so destinations can be grouped without re-parsing."
                        },
                        "status": {
                          "type": "number",
                          "description": "HTTP status at the end of the chain, or null when none was established."
                        },
                        "hops": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Each intermediate address, in order, excluding the starting one."
                        },
                        "truncated": {
                          "type": "boolean",
                          "description": "True when the chain hit the step limit and may continue further."
                        },
                        "title": {
                          "type": "string",
                          "description": "Page title at the destination, where one was readable."
                        },
                        "shortened": {
                          "type": "boolean",
                          "description": "True when the chain went through a known link shortener or affiliate redirector, anywhere along it."
                        },
                        "unresolvedReason": {
                          "type": "string",
                          "description": "Why no destination could be established, when status is null — the host did not answer, refused the request, and so on."
                        }
                      },
                      "additionalProperties": false
                    }
                  },
                  "additionalProperties": false
                },
                "examples": {
                  "default": {
                    "value": {
                      "blocked": false,
                      "requestedUrl": "https://bennyblanco.lnk.to/TeOlvido",
                      "scrapedAt": "2026-09-16T20:43:02.551Z",
                      "transport": "link-in-bio-page",
                      "notes": [],
                      "resultType": "unwrap-link",
                      "pagesFetched": 1,
                      "url": "https://bennyblanco.lnk.to/TeOlvido",
                      "destination": {
                        "url": "https://bennyblanco.lnk.to/TeOlvido",
                        "host": "bennyblanco.lnk.to",
                        "status": 200,
                        "hops": [],
                        "truncated": false,
                        "title": "benny blanco, Selena Gomez, Becky G - Te Olvido (La La)",
                        "shortened": true,
                        "unresolvedReason": null
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing Bearer token"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/detect-provider": {
      "post": {
        "operationId": "detect-provider",
        "tags": [
          "Utilities"
        ],
        "summary": "Identify which service an address belongs to",
        "description": "Which link-in-bio service hosts an address, whether its pages can be read here, the handle it names, and the evidence behind the answer. Thirty services are recognised and four of them are readable in this release — Linktree, Lnk.Bio, AllMyLinks and solo.to. The other twenty-six come back identified with the reason they are not, and that is the useful half: a note saying \"Bento has closed and its addresses now redirect to Linktree; use the creator’s Linktree page instead\", or \"Beacons pages are behind bot verification and cannot be read by this service\", or \"Komi pages load their content after the page opens\", or \"Carrd builds general one-page sites rather than link pages, so it has no link list to read\". A list of addresses from a dead service is answered rather than left to fail one page fetch at a time. An address that is not a link page at all gets an answer too, not a refusal. Set `checkCustomDomain` to fetch the page as well, so a link page served on the creator’s own domain is still identified — that costs a fetch, which is why it is off by default. Billing: 1 credit, and `pagesFetched` is 0 when the address was recognised from its shape alone.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Any address to identify."
                  },
                  "checkCustomDomain": {
                    "type": "boolean",
                    "description": "Also fetch the page, so a link page on the creator’s own domain is recognised. Costs a fetch.",
                    "example": "false"
                  },
                  "format": {
                    "type": "string",
                    "description": "json or markdown. Markdown returns a rendered summary instead of the structured record.",
                    "example": "json"
                  },
                  "timeoutMs": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Time limit for the request, in milliseconds (max 600000)."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "url"
                ]
              },
              "examples": {
                "default": {
                  "value": {
                    "url": "https://bento.me/someone"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transport": {
                      "type": "string",
                      "description": "The upstream source. Always \"link-in-bio-page\"."
                    },
                    "resultType": {
                      "type": "string",
                      "description": "Which route produced this record — profile, links, detect-provider, unwrap-link or resolve-url."
                    },
                    "requestedUrl": {
                      "type": "string",
                      "description": "The address this result corresponds to."
                    },
                    "scrapedAt": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of the read."
                    },
                    "blocked": {
                      "type": "boolean",
                      "description": "Always false on a successful response."
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Caveats you can act on — a page that is live but publishes no links, a service that publishes no theme or plan details, a destination that could not be reached. Read these: an empty result always arrives with one."
                    },
                    "pagesFetched": {
                      "type": "number",
                      "description": "Pages fetched, which is what the request costs: one credit per page. detect-provider reports 0 when it recognised the address from its shape alone, and resolve-url fetches nothing at all."
                    },
                    "input": {
                      "type": "string",
                      "description": "The address the caller asked about, verbatim."
                    },
                    "detection": {
                      "type": "object",
                      "properties": {
                        "provider": {
                          "type": "string",
                          "description": "Short, stable id for the service, or null when the address belongs to none of them."
                        },
                        "providerName": {
                          "type": "string",
                          "description": "The service’s public name, for display."
                        },
                        "supported": {
                          "type": "boolean",
                          "description": "Whether /profile and /links can actually read this page. False comes with a note saying why."
                        },
                        "handle": {
                          "type": "string",
                          "description": "The handle the address names, or null."
                        },
                        "evidence": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          },
                          "description": "What the answer was based on — the host, the path shape, or the page itself when checkCustomDomain was set."
                        }
                      },
                      "additionalProperties": false
                    }
                  },
                  "additionalProperties": false
                },
                "examples": {
                  "default": {
                    "value": {
                      "blocked": false,
                      "requestedUrl": "https://bento.me/someone",
                      "scrapedAt": "2026-09-16T20:42:31.010Z",
                      "transport": "link-in-bio-page",
                      "notes": [
                        "Bento has closed and its addresses now redirect to Linktree; use the creator's Linktree page instead"
                      ],
                      "resultType": "detect-provider",
                      "pagesFetched": 0,
                      "input": "https://bento.me/someone",
                      "detection": {
                        "provider": "bento",
                        "providerName": "Bento",
                        "supported": false,
                        "handle": "someone"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing Bearer token"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/resolve-url": {
      "post": {
        "operationId": "resolve-url",
        "tags": [
          "Utilities"
        ],
        "summary": "Parse a link-page address (free)",
        "description": "Turns any address into structured input for the other routes without fetching anything: which service it belongs to, whether it names one creator’s page or the service’s own site, the handle it carries, the canonical page address, and whether it can be read at all. The right first step for a list of pasted addresses — it separates the readable pages from the recognised-but-unreadable ones before a single page fetch is spent. Makes no request at all, so it answers in milliseconds and costs no credit. Billing: free.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Any address to parse."
                  },
                  "format": {
                    "type": "string",
                    "description": "json or markdown. Markdown returns a rendered summary instead of the structured record.",
                    "example": "json"
                  },
                  "timeoutMs": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Time limit for the request, in milliseconds (max 600000)."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "url"
                ]
              },
              "examples": {
                "default": {
                  "value": {
                    "url": "https://linktr.ee/nike"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "resultType": {
                      "type": "string",
                      "description": "Always \"resolve-url\"."
                    },
                    "url": {
                      "type": "string",
                      "description": "The address that was parsed."
                    },
                    "host": {
                      "type": "string",
                      "description": "Its host."
                    },
                    "kind": {
                      "type": "string",
                      "description": "profile (one creator’s page), provider-home (the service’s own site) or unknown."
                    },
                    "provider": {
                      "type": "string",
                      "description": "Short, stable id for the service, or null."
                    },
                    "providerName": {
                      "type": "string",
                      "description": "The service’s public name, or null."
                    },
                    "supported": {
                      "type": "boolean",
                      "description": "Whether /profile and /links can read this address. Check it before spending a page fetch."
                    },
                    "handle": {
                      "type": "string",
                      "description": "The handle the address carries, or null."
                    },
                    "profileUrl": {
                      "type": "string",
                      "description": "The canonical page address, when a handle was recognised."
                    }
                  },
                  "additionalProperties": false
                },
                "examples": {
                  "default": {
                    "value": {
                      "resultType": "resolve-url",
                      "url": "https://linktr.ee/nike",
                      "host": "linktr.ee",
                      "kind": "profile",
                      "provider": "linktree",
                      "providerName": "Linktree",
                      "supported": true,
                      "handle": "nike",
                      "profileUrl": "https://linktr.ee/nike"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing Bearer token"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    }
  }
}