{
    "openapi": "3.1.0",
    "info": {
        "title": "WebsiteRedirect API",
        "version": "1.0.0",
        "summary": "Beheer redirects, domeinen en analytics van je WebsiteRedirect-account.",
        "description": "Met de API beheer je je redirects vanuit je eigen scripts, deploy-pipeline of klantbeheer. Alles wat je in het portaal doet, kan hier ook.\n\n## Authenticatie\n\nMaak een token aan onder **API-tokens** in het portaal en stuur hem mee als bearer token:\n\n```http\nAuthorization: Bearer 12|wr_...\n```\n\nEen token wordt maar één keer getoond. Bewaar hem in een secret manager, niet in je code. Het geheime deel begint met `wr_`, zodat secret scanners een gelekte token herkennen. Stuur de token altijd in zijn geheel, inclusief het nummer en het `|`-teken. Trek een token in zodra je hem niet meer nodig hebt.\n\n## Rechten (abilities)\n\nElke token krijgt alleen de rechten die je aanvinkt. Elk endpoint vermeldt welk recht het nodig heeft (`x-required-ability`).\n\n| Ability | Wat het toestaat |\n| --- | --- |\n| `account:read` | Account en abonnement lezen |\n| `redirects:read` | Redirects lezen |\n| `redirects:write` | Redirects aanmaken, wijzigen en verwijderen |\n| `domains:read` | Domeinen en DNS-status lezen |\n| `domains:write` | DNS-verificatie opnieuw uitvoeren |\n| `analytics:read` | Analytics lezen |\n\n## Fouten\n\nFouten volgen [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) (`application/problem+json`) met een vaste `code` om op te programmeren:\n\n| Status | `code` | Betekenis |\n| --- | --- | --- |\n| 401 | `unauthenticated` | Geen of ongeldige token. |\n| 402 | `redirect_limit_reached` | Het gratis plan (5 redirects) is vol. Start een abonnement. |\n| 403 | `insufficient_scope` | De token mist het benodigde recht. |\n| 404 | `not_found` | Bestaat niet, of hoort niet bij jouw account. |\n| 422 | `validation_failed` | Ongeldige velden; zie `errors`. |\n| 429 | `rate_limited` | Te veel verzoeken; wacht tot `Retry-After`. |\n\nElk antwoord heeft een `X-Request-Id`. Noem die als je contact met ons opneemt.\n\n## Limieten\n\n120 verzoeken per minuut per token, waarvan maximaal 30 wijzigingen per minuut per account. De headers `X-RateLimit-Limit` en `X-RateLimit-Remaining` laten zien waar je staat.\n\n## Paginering\n\nLijsten geven `data`, `links` (`first`, `last`, `prev`, `next`) en `meta` (`current_page`, `per_page`, `total`). Gebruik `?page=` en `?per_page=` (maximaal 100).\n\n## Publiceren\n\nEen wijziging staat binnen enkele seconden op de edge. Een nieuw domein gaat live zodra het DNS-record naar ons wijst en geverifieerd is; daarna volgt het SSL-certificaat automatisch.",
        "contact": {
            "name": "PC Patrol",
            "email": "helpdesk@pcpatrol.nl",
            "url": "https://websiteredirect.nl"
        },
        "termsOfService": "https://websiteredirect.nl/voorwaarden"
    },
    "servers": [
        {
            "url": "https://app.websiteredirect.nl/api/v1",
            "description": "Productie"
        }
    ],
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "tags": [
        {
            "name": "Account",
            "description": "Het account achter de token."
        },
        {
            "name": "Redirects",
            "description": "Redirects met hun domeinen en bestemming."
        },
        {
            "name": "Domains",
            "description": "Brondomeinen met DNS-, SSL- en eigendomsstatus. Domeinen voeg je toe of verwijder je via hun redirect."
        },
        {
            "name": "Analytics",
            "description": "Hits per dag."
        }
    ],
    "paths": {
        "/account": {
            "get": {
                "operationId": "getAccount",
                "tags": [
                    "Account"
                ],
                "summary": "Account en plan",
                "description": "Het account achter de token, het plan met de redirect-limiet en de rechten van de token.\n\nVereist recht: `account:read`.",
                "x-required-ability": "account:read",
                "responses": {
                    "200": {
                        "description": "Het account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Account"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/redirects": {
            "get": {
                "operationId": "listRedirects",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirects ophalen",
                "description": "Alle redirects van het account, nieuwste eerst.\n\nVereist recht: `redirects:read`.",
                "x-required-ability": "redirects:read",
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "default": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 25
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "description": "Zoek in naam, domeinen en bestemming.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "active",
                                "paused"
                            ]
                        }
                    },
                    {
                        "name": "domain",
                        "in": "query",
                        "description": "Alleen de redirect met dit exacte domein.",
                        "schema": {
                            "type": "string",
                            "example": "oud-merk.nl"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Een pagina redirects.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Redirect"
                                            }
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PaginationLinks"
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PaginationMeta"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "operationId": "createRedirect",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirect aanmaken",
                "description": "Maakt een redirect met een of meer domeinen. Op het gratis plan geeft de redirect boven de limiet `402`.\n\nVereist recht: `redirects:write`.",
                "x-required-ability": "redirects:write",
                "requestBody": {
                    "$ref": "#/components/requestBodies/CreateRedirect"
                },
                "responses": {
                    "201": {
                        "description": "Aangemaakt. De `Location`-header wijst naar de nieuwe redirect.",
                        "headers": {
                            "Location": {
                                "schema": {
                                    "type": "string",
                                    "format": "uri"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Redirect"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "402": {
                        "$ref": "#/components/responses/LimitReached"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/redirects/{redirect}": {
            "parameters": [
                {
                    "name": "redirect",
                    "in": "path",
                    "required": true,
                    "description": "Id van de redirect.",
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "get": {
                "operationId": "getRedirect",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirect ophalen",
                "description": "Eén redirect met domeinen.\n\nVereist recht: `redirects:read`.",
                "x-required-ability": "redirects:read",
                "responses": {
                    "200": {
                        "description": "De redirect.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Redirect"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "operationId": "updateRedirect",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirect wijzigen",
                "description": "Alleen de velden die je meestuurt veranderen. Stuur je `domains` mee, dan vervangt die lijst de huidige domeinen; bestaande domeinen houden hun verificatie en certificaat.\n\nVereist recht: `redirects:write`.",
                "x-required-ability": "redirects:write",
                "requestBody": {
                    "$ref": "#/components/requestBodies/UpdateRedirect"
                },
                "responses": {
                    "200": {
                        "description": "De gewijzigde redirect.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Redirect"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "operationId": "deleteRedirect",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirect verwijderen",
                "description": "Verwijdert de redirect en geeft de domeinen vrij.\n\nVereist recht: `redirects:write`.",
                "x-required-ability": "redirects:write",
                "responses": {
                    "204": {
                        "description": "Verwijderd."
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/redirects/{redirect}/pause": {
            "parameters": [
                {
                    "name": "redirect",
                    "in": "path",
                    "required": true,
                    "description": "Id van de redirect.",
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "operationId": "pauseRedirect",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirect pauzeren",
                "description": "De domeinen sturen niet meer door tot je de redirect hervat.\n\nVereist recht: `redirects:write`.",
                "x-required-ability": "redirects:write",
                "responses": {
                    "200": {
                        "description": "De gepauzeerde redirect.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Redirect"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/redirects/{redirect}/resume": {
            "parameters": [
                {
                    "name": "redirect",
                    "in": "path",
                    "required": true,
                    "description": "Id van de redirect.",
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "operationId": "resumeRedirect",
                "tags": [
                    "Redirects"
                ],
                "summary": "Redirect hervatten",
                "description": "Zet een gepauzeerde redirect weer aan. Een redirect die is gepauzeerd omdat het abonnement verliep (`paused_reason: billing`), hervat pas met een actief abonnement.\n\nVereist recht: `redirects:write`.",
                "x-required-ability": "redirects:write",
                "responses": {
                    "200": {
                        "description": "De hervatte redirect.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Redirect"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "402": {
                        "$ref": "#/components/responses/LimitReached"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/redirects/{redirect}/analytics": {
            "parameters": [
                {
                    "name": "redirect",
                    "in": "path",
                    "required": true,
                    "description": "Id van de redirect.",
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "get": {
                "operationId": "getRedirectAnalytics",
                "tags": [
                    "Analytics"
                ],
                "summary": "Hits per dag",
                "description": "Hits per dag en per domein. Dagen zonder hits staan erin met 0. Standaard de laatste 30 dagen, maximaal 366 dagen.\n\nVereist recht: `analytics:read`.",
                "x-required-ability": "analytics:read",
                "parameters": [
                    {
                        "name": "from",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "date",
                            "example": "2026-09-01"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "format": "date",
                            "example": "2026-09-30"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "De reeks.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Analytics"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/domains": {
            "get": {
                "operationId": "listDomains",
                "tags": [
                    "Domains"
                ],
                "summary": "Domeinen ophalen",
                "description": "Alle brondomeinen van het account, alfabetisch.\n\nVereist recht: `domains:read`.",
                "x-required-ability": "domains:read",
                "parameters": [
                    {
                        "name": "page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "default": 1
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 50
                        }
                    },
                    {
                        "name": "verified",
                        "in": "query",
                        "description": "Alleen (niet) geverifieerde domeinen.",
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Een pagina domeinen.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "links",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Domain"
                                            }
                                        },
                                        "links": {
                                            "$ref": "#/components/schemas/PaginationLinks"
                                        },
                                        "meta": {
                                            "$ref": "#/components/schemas/PaginationMeta"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/domains/{domain}": {
            "parameters": [
                {
                    "name": "domain",
                    "in": "path",
                    "required": true,
                    "description": "Id van het domein.",
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "get": {
                "operationId": "getDomain",
                "tags": [
                    "Domains"
                ],
                "summary": "Domein ophalen",
                "description": "Eén domein met het DNS-record dat het nodig heeft.\n\nVereist recht: `domains:read`.",
                "x-required-ability": "domains:read",
                "responses": {
                    "200": {
                        "description": "Het domein.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Domain"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/domains/{domain}/verify": {
            "parameters": [
                {
                    "name": "domain",
                    "in": "path",
                    "required": true,
                    "description": "Id van het domein.",
                    "schema": {
                        "type": "integer",
                        "minimum": 1
                    }
                }
            ],
            "post": {
                "operationId": "verifyDomain",
                "tags": [
                    "Domains"
                ],
                "summary": "DNS nu controleren",
                "description": "Controleert het DNS-record direct, in plaats van te wachten op de volgende automatische controle (elke 15 minuten).\n\nVereist recht: `domains:write`.",
                "x-required-ability": "domains:write",
                "responses": {
                    "200": {
                        "description": "Het domein na de controle.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "$ref": "#/components/schemas/Domain"
                                        },
                                        "meta": {
                                            "type": "object",
                                            "properties": {
                                                "verified": {
                                                    "type": "boolean"
                                                },
                                                "message": {
                                                    "type": "string"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthenticated"
                    },
                    "403": {
                        "$ref": "#/components/responses/InsufficientScope"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "{id}|wr_{secret} personal access token",
                "description": "Maak een token aan onder API-tokens in het portaal."
            }
        },
        "requestBodies": {
            "CreateRedirect": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "required": [
                                "destination_url",
                                "domains"
                            ],
                            "additionalProperties": false,
                            "properties": {
                                "name": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "maxLength": 255,
                                    "description": "Eigen label.",
                                    "example": "Oude webshop"
                                },
                                "destination_url": {
                                    "type": "string",
                                    "format": "uri",
                                    "maxLength": 2048,
                                    "description": "Waar bezoekers heen gaan, inclusief http(s)://.",
                                    "example": "https://nieuw-merk.nl"
                                },
                                "status_code": {
                                    "type": "integer",
                                    "enum": [
                                        301,
                                        302,
                                        307,
                                        308
                                    ],
                                    "default": 301,
                                    "description": "301/308 permanent, 302/307 tijdelijk. 307 en 308 behouden de HTTP-methode."
                                },
                                "masked": {
                                    "type": "boolean",
                                    "default": false,
                                    "description": "Domain masking: de bestemming in een frame, het brondomein blijft in de adresbalk."
                                },
                                "forward_path": {
                                    "type": "boolean",
                                    "default": true,
                                    "description": "Neem het pad mee: `/contact` komt uit op `bestemming/contact`."
                                },
                                "forward_query": {
                                    "type": "boolean",
                                    "default": true,
                                    "description": "Neem de querystring mee, zoals UTM-tags."
                                },
                                "prevent_embedding": {
                                    "type": "boolean",
                                    "default": false,
                                    "description": "Voorkom dat anderen de redirect in een frame laden."
                                },
                                "tracking_enabled": {
                                    "type": "boolean",
                                    "default": true,
                                    "description": "Tel hits voor analytics."
                                },
                                "paused": {
                                    "type": "boolean",
                                    "default": false
                                },
                                "domains": {
                                    "type": "array",
                                    "minItems": 1,
                                    "maxItems": 100,
                                    "uniqueItems": true,
                                    "items": {
                                        "type": "string",
                                        "format": "hostname",
                                        "example": "oud-merk.nl"
                                    },
                                    "description": "Brondomeinen. Een domein kan binnen je account maar bij één redirect horen."
                                }
                            }
                        },
                        "example": {
                            "name": "Oude webshop",
                            "destination_url": "https://nieuw-merk.nl",
                            "status_code": 301,
                            "domains": [
                                "oud-merk.nl",
                                "www.oud-merk.nl"
                            ],
                            "forward_path": true
                        }
                    }
                }
            },
            "UpdateRedirect": {
                "required": true,
                "content": {
                    "application/json": {
                        "schema": {
                            "type": "object",
                            "minProperties": 1,
                            "additionalProperties": false,
                            "properties": {
                                "name": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "maxLength": 255,
                                    "description": "Eigen label.",
                                    "example": "Oude webshop"
                                },
                                "destination_url": {
                                    "type": "string",
                                    "format": "uri",
                                    "maxLength": 2048,
                                    "description": "Waar bezoekers heen gaan, inclusief http(s)://.",
                                    "example": "https://nieuw-merk.nl"
                                },
                                "status_code": {
                                    "type": "integer",
                                    "enum": [
                                        301,
                                        302,
                                        307,
                                        308
                                    ],
                                    "default": 301,
                                    "description": "301/308 permanent, 302/307 tijdelijk. 307 en 308 behouden de HTTP-methode."
                                },
                                "masked": {
                                    "type": "boolean",
                                    "default": false,
                                    "description": "Domain masking: de bestemming in een frame, het brondomein blijft in de adresbalk."
                                },
                                "forward_path": {
                                    "type": "boolean",
                                    "default": true,
                                    "description": "Neem het pad mee: `/contact` komt uit op `bestemming/contact`."
                                },
                                "forward_query": {
                                    "type": "boolean",
                                    "default": true,
                                    "description": "Neem de querystring mee, zoals UTM-tags."
                                },
                                "prevent_embedding": {
                                    "type": "boolean",
                                    "default": false,
                                    "description": "Voorkom dat anderen de redirect in een frame laden."
                                },
                                "tracking_enabled": {
                                    "type": "boolean",
                                    "default": true,
                                    "description": "Tel hits voor analytics."
                                },
                                "paused": {
                                    "type": "boolean",
                                    "default": false
                                },
                                "domains": {
                                    "type": "array",
                                    "minItems": 1,
                                    "maxItems": 100,
                                    "uniqueItems": true,
                                    "items": {
                                        "type": "string",
                                        "format": "hostname",
                                        "example": "oud-merk.nl"
                                    },
                                    "description": "Brondomeinen. Een domein kan binnen je account maar bij één redirect horen."
                                }
                            }
                        },
                        "example": {
                            "status_code": 308,
                            "paused": false
                        }
                    }
                }
            }
        },
        "responses": {
            "Unauthenticated": {
                "description": "A valid bearer token is required.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        },
                        "example": {
                            "type": "https://app.websiteredirect.nl/docs/api#problem-unauthenticated",
                            "title": "A valid bearer token is required.",
                            "status": 401,
                            "code": "unauthenticated",
                            "instance": "/api/v1/redirects",
                            "request_id": "9b2f0c1e-4a7d-4c55-9b0e-2b1f3c4d5e6f"
                        }
                    }
                }
            },
            "InsufficientScope": {
                "description": "The token lacks the ability this endpoint needs.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        },
                        "example": {
                            "type": "https://app.websiteredirect.nl/docs/api#problem-insufficient-scope",
                            "title": "The token lacks the ability this endpoint needs.",
                            "status": 403,
                            "code": "insufficient_scope",
                            "instance": "/api/v1/redirects",
                            "request_id": "9b2f0c1e-4a7d-4c55-9b0e-2b1f3c4d5e6f"
                        }
                    }
                }
            },
            "NotFound": {
                "description": "The resource does not exist.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        },
                        "example": {
                            "type": "https://app.websiteredirect.nl/docs/api#problem-not-found",
                            "title": "The resource does not exist.",
                            "status": 404,
                            "code": "not_found",
                            "instance": "/api/v1/redirects",
                            "request_id": "9b2f0c1e-4a7d-4c55-9b0e-2b1f3c4d5e6f"
                        }
                    }
                }
            },
            "LimitReached": {
                "description": "The free plan's redirect allowance is used up.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        },
                        "example": {
                            "type": "https://app.websiteredirect.nl/docs/api#problem-redirect-limit-reached",
                            "title": "The free plan's redirect allowance is used up.",
                            "status": 402,
                            "code": "redirect_limit_reached",
                            "instance": "/api/v1/redirects",
                            "request_id": "9b2f0c1e-4a7d-4c55-9b0e-2b1f3c4d5e6f"
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "Too many requests.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/Problem"
                        },
                        "example": {
                            "type": "https://app.websiteredirect.nl/docs/api#problem-rate-limited",
                            "title": "Too many requests.",
                            "status": 429,
                            "code": "rate_limited",
                            "instance": "/api/v1/redirects",
                            "request_id": "9b2f0c1e-4a7d-4c55-9b0e-2b1f3c4d5e6f"
                        }
                    }
                },
                "headers": {
                    "Retry-After": {
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Seconden tot je het opnieuw kunt proberen."
                    }
                }
            },
            "ValidationFailed": {
                "description": "The request contains invalid fields.",
                "content": {
                    "application/problem+json": {
                        "schema": {
                            "$ref": "#/components/schemas/ValidationProblem"
                        },
                        "example": {
                            "title": "The request contains invalid fields.",
                            "status": 422,
                            "code": "validation_failed",
                            "errors": {
                                "domains.0": [
                                    "Each domain must be a hostname, such as example.com."
                                ]
                            }
                        }
                    }
                }
            }
        },
        "schemas": {
            "Problem": {
                "type": "object",
                "description": "RFC 9457 problem details.",
                "required": [
                    "title",
                    "status",
                    "code"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "format": "uri"
                    },
                    "title": {
                        "type": "string"
                    },
                    "status": {
                        "type": "integer"
                    },
                    "detail": {
                        "type": "string"
                    },
                    "instance": {
                        "type": "string"
                    },
                    "code": {
                        "type": "string",
                        "enum": [
                            "unauthenticated",
                            "insufficient_scope",
                            "forbidden",
                            "not_found",
                            "redirect_limit_reached",
                            "validation_failed",
                            "rate_limited",
                            "method_not_allowed",
                            "server_error"
                        ]
                    },
                    "request_id": {
                        "type": "string"
                    }
                }
            },
            "ValidationProblem": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Problem"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "errors": {
                                "type": "object",
                                "additionalProperties": {
                                    "type": "array",
                                    "items": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    }
                ]
            },
            "Account": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "object": {
                        "const": "account"
                    },
                    "name": {
                        "type": "string"
                    },
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "plan": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string",
                                "enum": [
                                    "free",
                                    "unlimited"
                                ]
                            },
                            "subscription_status": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "enum": [
                                    "pending",
                                    "active",
                                    "suspended",
                                    "cancelled",
                                    null
                                ]
                            },
                            "redirect_limit": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Null bij onbeperkt."
                            },
                            "redirects_used": {
                                "type": "integer"
                            }
                        }
                    },
                    "token": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "abilities": {
                                "type": "array",
                                "items": {
                                    "type": "string",
                                    "enum": [
                                        "account:read",
                                        "redirects:read",
                                        "redirects:write",
                                        "domains:read",
                                        "domains:write",
                                        "analytics:read"
                                    ]
                                }
                            },
                            "expires_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            }
                        }
                    }
                }
            },
            "Redirect": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 42
                    },
                    "object": {
                        "const": "redirect"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255,
                        "description": "Eigen label.",
                        "example": "Oude webshop"
                    },
                    "destination_url": {
                        "type": "string",
                        "format": "uri",
                        "maxLength": 2048,
                        "description": "Waar bezoekers heen gaan, inclusief http(s)://.",
                        "example": "https://nieuw-merk.nl"
                    },
                    "status_code": {
                        "type": "integer",
                        "enum": [
                            301,
                            302,
                            307,
                            308
                        ],
                        "default": 301,
                        "description": "301/308 permanent, 302/307 tijdelijk. 307 en 308 behouden de HTTP-methode."
                    },
                    "masked": {
                        "type": "boolean",
                        "default": false,
                        "description": "Domain masking: de bestemming in een frame, het brondomein blijft in de adresbalk."
                    },
                    "forward_path": {
                        "type": "boolean",
                        "default": true,
                        "description": "Neem het pad mee: `/contact` komt uit op `bestemming/contact`."
                    },
                    "forward_query": {
                        "type": "boolean",
                        "default": true,
                        "description": "Neem de querystring mee, zoals UTM-tags."
                    },
                    "prevent_embedding": {
                        "type": "boolean",
                        "default": false,
                        "description": "Voorkom dat anderen de redirect in een frame laden."
                    },
                    "tracking_enabled": {
                        "type": "boolean",
                        "default": true,
                        "description": "Tel hits voor analytics."
                    },
                    "paused": {
                        "type": "boolean",
                        "default": false
                    },
                    "paused_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "manual",
                            "billing",
                            null
                        ],
                        "description": "`billing` als de redirect is gepauzeerd omdat het abonnement verliep."
                    },
                    "domains": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Domain"
                        }
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "links": {
                        "type": "object",
                        "properties": {
                            "self": {
                                "type": "string",
                                "format": "uri"
                            },
                            "analytics": {
                                "type": "string",
                                "format": "uri"
                            }
                        }
                    }
                }
            },
            "Domain": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 7
                    },
                    "object": {
                        "const": "domain"
                    },
                    "hostname": {
                        "type": "string",
                        "example": "oud-merk.nl"
                    },
                    "redirect_id": {
                        "type": "integer"
                    },
                    "dns": {
                        "type": "object",
                        "properties": {
                            "verified": {
                                "type": "boolean"
                            },
                            "verified_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "format": "date-time"
                            },
                            "required_record": {
                                "type": "object",
                                "description": "Het record dat bij je DNS-provider moet staan.",
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "A",
                                            "CNAME"
                                        ]
                                    },
                                    "name": {
                                        "type": "string",
                                        "example": "@"
                                    },
                                    "value": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "ssl": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "string",
                                "example": "issued"
                            }
                        }
                    },
                    "ownership": {
                        "type": "object",
                        "description": "Claimt een ander account hetzelfde domein, dan bewijs je eigendom met dit TXT-record.",
                        "properties": {
                            "claimed_elsewhere": {
                                "type": "boolean"
                            },
                            "txt_record": {
                                "type": [
                                    "object",
                                    "null"
                                ],
                                "properties": {
                                    "name": {
                                        "type": "string"
                                    },
                                    "value": {
                                        "type": "string"
                                    }
                                }
                            }
                        }
                    },
                    "last_hit_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "links": {
                        "type": "object",
                        "properties": {
                            "self": {
                                "type": "string",
                                "format": "uri"
                            }
                        }
                    }
                }
            },
            "Analytics": {
                "type": "object",
                "properties": {
                    "object": {
                        "const": "analytics"
                    },
                    "redirect_id": {
                        "type": "integer"
                    },
                    "from": {
                        "type": "string",
                        "format": "date"
                    },
                    "to": {
                        "type": "string",
                        "format": "date"
                    },
                    "total_hits": {
                        "type": "integer"
                    },
                    "days": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "date": {
                                    "type": "string",
                                    "format": "date"
                                },
                                "hits": {
                                    "type": "integer"
                                }
                            }
                        }
                    },
                    "domains": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "hostname": {
                                    "type": "string"
                                },
                                "hits": {
                                    "type": "integer"
                                }
                            }
                        }
                    }
                }
            },
            "PaginationLinks": {
                "type": "object",
                "properties": {
                    "first": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    },
                    "last": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    },
                    "prev": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    },
                    "next": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "uri"
                    }
                }
            },
            "PaginationMeta": {
                "type": "object",
                "properties": {
                    "current_page": {
                        "type": "integer"
                    },
                    "from": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "last_page": {
                        "type": "integer"
                    },
                    "per_page": {
                        "type": "integer"
                    },
                    "to": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "total": {
                        "type": "integer"
                    }
                }
            }
        }
    }
}