{
  "openapi": "3.1.0",
  "info": {
    "title": "SaaS Custom Domains API",
    "version": "1.0.0",
    "description": "SaaS Custom Domains is a managed reverse proxy that serves your app on your customers' custom domains, with automatic TLS certificates. Use this API to manage upstreams, custom domains, rules, redirects and custom certificates, and to read web and proxy analytics.\n\n## Authentication\n\nSend your API token in the `Authorization: Bearer <token>` header. You can create tokens under [Settings > API](https://app.saascustomdomains.com/api_tokens).\n\n## Requests and responses\n\nSend request bodies as JSON with `Content-Type: application/json`. Form-encoded bodies (`application/x-www-form-urlencoded`) are accepted as well. Responses are JSON. Timestamps are ISO 8601 in UTC.\n\n## Pagination\n\nList endpoints return 20 items per page by default. Use `page` (starting at 1) and `per_page` (up to 100). Items are returned in a `data` array next to a `pagination` object.\n\n## Rate limits\n\nEach API token can make 360 requests per minute. The verify DNS records endpoint also has its own limit of 5 requests per minute per token. Over the limit, the API returns `429 Too Many Requests` with `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers. Contact support if you need a higher limit.\n\n## Errors\n\nErrors return a JSON body with an `error` message and, for most errors, an `error_code`. A 401 response has no body.",
    "termsOfService": "https://app.saascustomdomains.com/terms",
    "contact": {
      "name": "SaaS Custom Domains",
      "url": "https://saascustomdomains.com"
    }
  },
  "externalDocs": {
    "description": "SaaS Custom Domains API documentation",
    "url": "https://docs.saascustomdomains.com"
  },
  "servers": [
    {
      "url": "https://app.saascustomdomains.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Accounts",
      "description": "The user that owns the API token and the accounts they belong to."
    },
    {
      "name": "Upstreams",
      "description": "Upstreams are the servers the proxy forwards requests to, usually your web application. There's no endpoint for updating an upstream; use the dashboard."
    },
    {
      "name": "Custom Domains",
      "description": "Your customers' domains, served through the proxy with automatic TLS. Custom domains can't be updated. To change one, delete it and create it again."
    },
    {
      "name": "Rules",
      "description": "Rules match requests by path, method, header, query, country or IP address and then rewrite, redirect, respond, change headers or rate limit them. Rules attach to an upstream (applying to all its custom domains) or to a single custom domain. Upstream rules are evaluated before a domain's own rules, and within each scope rules run in position order. Every matching rule is applied until a handler ends the request."
    },
    {
      "name": "Custom Certificates",
      "description": "TLS certificates you uploaded in the dashboard. Certificates can't be uploaded through the API."
    },
    {
      "name": "Redirects",
      "description": "Host and path based redirects to another URL."
    },
    {
      "name": "Web Analytics",
      "description": "Visitor analytics. Only pageviews are counted: successful (`2xx` or `304`) `GET` requests to paths without a file extension, excluding known bots and datacenter IP addresses. A visitor is a unique IP address. Visitor and visit counts are approximate, usually within 1 to 2 percent. Analytics endpoints take the custom domain's UUID and work for domains in any of your accounts. Analytics must be enabled for the account that owns the domain, otherwise they return 403. Data is available from July 1, 2025. Responses are cached for up to 5 minutes."
    },
    {
      "name": "Proxy Analytics",
      "description": "Request level analytics that count every request to the domain, including bots and datacenter traffic. Analytics endpoints take the custom domain's UUID and work for domains in any of your accounts. Analytics must be enabled for the account that owns the domain, otherwise they return 403. Data is available from July 1, 2025. Responses are cached for up to 5 minutes."
    }
  ],
  "paths": {
    "/api/v1/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Accounts"
        ],
        "summary": "Retrieve the current user",
        "description": "Returns the user that owns the API token. Handy for checking that your token works.",
        "responses": {
          "200": {
            "description": "The current user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts": {
      "get": {
        "operationId": "listAccounts",
        "tags": [
          "Accounts"
        ],
        "summary": "List accounts",
        "description": "Returns every account you belong to. This list isn't paginated.",
        "responses": {
          "200": {
            "description": "Your accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Account"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        }
      ],
      "get": {
        "operationId": "listUpstreams",
        "tags": [
          "Upstreams"
        ],
        "summary": "List upstreams",
        "description": "Returns a paginated list of the account's upstreams, oldest first.",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "description": "Only return the upstream with this exact host.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of upstreams.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpstreamList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createUpstream",
        "tags": [
          "Upstreams"
        ],
        "summary": "Create an upstream",
        "description": "Adds an upstream to the account. Requires an active subscription.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpstreamCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created upstream.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Upstream"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        }
      ],
      "get": {
        "operationId": "getUpstream",
        "tags": [
          "Upstreams"
        ],
        "summary": "Retrieve an upstream",
        "description": "Returns a single upstream.",
        "responses": {
          "200": {
            "description": "The upstream.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Upstream"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "deleteUpstream",
        "tags": [
          "Upstreams"
        ],
        "summary": "Delete an upstream",
        "description": "Deletes the upstream together with all of its custom domains.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Upstream upstream_180e8083 (app.mysaas.com) deleted."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        }
      ],
      "get": {
        "operationId": "listCustomDomains",
        "tags": [
          "Custom Domains"
        ],
        "summary": "List custom domains",
        "description": "Returns a paginated list of the upstream's custom domains, oldest first.",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "description": "Only return the custom domain with this exact host.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of custom domains.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomDomainList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createCustomDomain",
        "tags": [
          "Custom Domains"
        ],
        "summary": "Create a custom domain",
        "description": "Adds a custom domain to the upstream and starts checking its DNS records. Every custom domain you create counts toward your bill, whether or not its DNS records have been added. Requires an active subscription.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomDomainCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created custom domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomDomain"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        }
      ],
      "get": {
        "operationId": "getCustomDomain",
        "tags": [
          "Custom Domains"
        ],
        "summary": "Retrieve a custom domain",
        "description": "Returns a single custom domain.",
        "responses": {
          "200": {
            "description": "The custom domain.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomDomain"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "deleteCustomDomain",
        "tags": [
          "Custom Domains"
        ],
        "summary": "Delete a custom domain",
        "description": "Deletes the custom domain. Suspended custom domains can't be deleted; contact support.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Custom domain domain_4e30e873 (app.user.com) deleted."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "The custom domain is suspended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Suspended custom domains cannot be deleted. Please contact support.",
                  "error_code": "suspended_cannot_be_deleted"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}/dns_records": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        }
      ],
      "get": {
        "operationId": "getCustomDomainDnsRecords",
        "tags": [
          "Custom Domains"
        ],
        "summary": "Get DNS records",
        "description": "Returns the DNS records your customer needs to add for the custom domain, the same records the dashboard shows. Subdomains and wildcards get a CNAME. Root domains using `http01` get two A records, because not every DNS provider allows a CNAME at the root. `redirect_to_www` adds a CNAME for the `www` subdomain, and `dns01` adds the `_acme-challenge` CNAME records.",
        "responses": {
          "200": {
            "description": "The DNS records to add.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DnsRecordList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/custom_domains": {
      "get": {
        "operationId": "listAllCustomDomains",
        "tags": [
          "Custom Domains"
        ],
        "summary": "List custom domains across accounts",
        "description": "Returns a paginated list of custom domains in every account you belong to, oldest first. Use it to find a domain by host without knowing its account or upstream. Each item also has `account_uuid` and `upstream_host`.",
        "parameters": [
          {
            "name": "host",
            "in": "query",
            "description": "Only return the custom domain with this exact host. Case-insensitive.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account_uuid",
            "in": "query",
            "description": "Only return custom domains in this account.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "upstream_uuid",
            "in": "query",
            "description": "Only return custom domains on this upstream.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Only return custom domains with this DNS status. Wildcard domains are `dns_check_unnecessary`.",
            "schema": {
              "type": "string",
              "enum": [
                "pending_check",
                "dns_records_found",
                "dns_records_not_found",
                "dns_check_unnecessary"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of custom domains.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountCustomDomainList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}/verify_dns_records": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        }
      ],
      "post": {
        "operationId": "verifyCustomDomainDnsRecords",
        "tags": [
          "Custom Domains"
        ],
        "summary": "Verify DNS records",
        "description": "Checks the custom domain's DNS records right away and returns the result. DNS records are already checked automatically after a domain is created: immediately, at 15, 30 and 45 seconds, every minute for the first 10 minutes, every 5 minutes up to 60 minutes, and then every 3 hours. Calling this endpoint more often doesn't speed up verification. Limited to 5 requests per minute per API token. No request body is needed.",
        "responses": {
          "200": {
            "description": "The result of the DNS check.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DnsVerificationResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}/purge_http_cache": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        }
      ],
      "post": {
        "operationId": "purgeCustomDomainHttpCache",
        "tags": [
          "Custom Domains"
        ],
        "summary": "Purge the HTTP cache",
        "description": "Starts purging the custom domain's HTTP cache. The purge runs in the background and can take a few seconds to complete everywhere. It only has an effect when HTTP caching is enabled for the domain. No request body is needed.",
        "responses": {
          "202": {
            "description": "The purge was started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "HTTP cache purge initiated for domain app.example.com."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "description": "The purge couldn't be started.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Failed to initiate HTTP cache purge for domain app.example.com."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/rules": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        }
      ],
      "get": {
        "operationId": "listUpstreamRules",
        "tags": [
          "Rules"
        ],
        "summary": "List upstream rules",
        "description": "Returns a paginated list of the upstream's rules, ordered by position.",
        "parameters": [
          {
            "name": "active",
            "in": "query",
            "description": "Only return active (`true`) or inactive (`false`) rules.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of rules.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuleList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createUpstreamRule",
        "tags": [
          "Rules"
        ],
        "summary": "Create a upstream rule",
        "description": "Creates a rule that applies to every custom domain on the upstream. The rule is added after the existing rules.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuleCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/rules/update_positions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        }
      ],
      "patch": {
        "operationId": "updateUpstreamRulePositions",
        "tags": [
          "Rules"
        ],
        "summary": "Reorder upstream rules",
        "description": "Sets the positions of several of the upstream's rules at once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RulePositionsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Positions updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Rule positions updated successfully."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidRulePositions"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/rules/{rule_uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/RuleUuid"
        }
      ],
      "get": {
        "operationId": "getUpstreamRule",
        "tags": [
          "Rules"
        ],
        "summary": "Retrieve a upstream rule",
        "description": "Returns a single rule.",
        "responses": {
          "200": {
            "description": "The rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "updateUpstreamRule",
        "tags": [
          "Rules"
        ],
        "summary": "Update a upstream rule",
        "description": "Updates a rule. Only the attributes you send are changed. `PUT` is accepted as well.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "deleteUpstreamRule",
        "tags": [
          "Rules"
        ],
        "summary": "Delete a upstream rule",
        "description": "Deletes a rule. The remaining rules are renumbered so positions stay sequential.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Rule rule_01234abc (Block legacy API) deleted."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}/rules": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        }
      ],
      "get": {
        "operationId": "listDomainRules",
        "tags": [
          "Rules"
        ],
        "summary": "List domain rules",
        "description": "Returns a paginated list of the custom domain's rules, ordered by position.",
        "parameters": [
          {
            "name": "active",
            "in": "query",
            "description": "Only return active (`true`) or inactive (`false`) rules.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of rules.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuleList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createDomainRule",
        "tags": [
          "Rules"
        ],
        "summary": "Create a domain rule",
        "description": "Creates a rule that applies to one custom domain. The rule is added after the existing rules.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuleCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}/rules/update_positions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        }
      ],
      "patch": {
        "operationId": "updateDomainRulePositions",
        "tags": [
          "Rules"
        ],
        "summary": "Reorder domain rules",
        "description": "Sets the positions of several of the custom domain's rules at once.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RulePositionsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Positions updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Rule positions updated successfully."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidRulePositions"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/upstreams/{upstream_uuid}/custom_domains/{domain_uuid}/rules/{rule_uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/UpstreamUuid"
        },
        {
          "$ref": "#/components/parameters/DomainUuid"
        },
        {
          "$ref": "#/components/parameters/RuleUuid"
        }
      ],
      "get": {
        "operationId": "getDomainRule",
        "tags": [
          "Rules"
        ],
        "summary": "Retrieve a domain rule",
        "description": "Returns a single rule.",
        "responses": {
          "200": {
            "description": "The rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "patch": {
        "operationId": "updateDomainRule",
        "tags": [
          "Rules"
        ],
        "summary": "Update a domain rule",
        "description": "Updates a rule. Only the attributes you send are changed. `PUT` is accepted as well.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated rule.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Rule"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "deleteDomainRule",
        "tags": [
          "Rules"
        ],
        "summary": "Delete a domain rule",
        "description": "Deletes a rule. The remaining rules are renumbered so positions stay sequential.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Rule rule_01234abc (Block legacy API) deleted."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/custom_certificates": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        }
      ],
      "get": {
        "operationId": "listCustomCertificates",
        "tags": [
          "Custom Certificates"
        ],
        "summary": "List custom certificates",
        "description": "Returns a paginated list of the account's custom certificates, oldest first.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of custom certificates.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomCertificateList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/custom_certificates/{certificate_uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/CertificateUuid"
        }
      ],
      "get": {
        "operationId": "getCustomCertificate",
        "tags": [
          "Custom Certificates"
        ],
        "summary": "Retrieve a custom certificate",
        "description": "Returns a single custom certificate.",
        "responses": {
          "200": {
            "description": "The custom certificate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomCertificate"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "deleteCustomCertificate",
        "tags": [
          "Custom Certificates"
        ],
        "summary": "Delete a custom certificate",
        "description": "Deletes a custom certificate.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Custom Certificate cert_1a2b3c4d deleted."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/redirects": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        }
      ],
      "get": {
        "operationId": "listRedirects",
        "tags": [
          "Redirects"
        ],
        "summary": "List redirects",
        "description": "Returns a paginated list of the account's redirects, oldest first unless you set `sort`.",
        "parameters": [
          {
            "name": "source_host",
            "in": "query",
            "description": "Only return redirects with this exact source host.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Field to sort by, for example `created_at`, `updated_at` or `source_host`.",
            "schema": {
              "type": "string",
              "default": "created_at"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "description": "Sort direction.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "asc"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PerPage"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of redirects.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RedirectList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "post": {
        "operationId": "createRedirect",
        "tags": [
          "Redirects"
        ],
        "summary": "Create a redirect",
        "description": "Creates a redirect. Requires an active subscription.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RedirectCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created redirect.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Redirect"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/accounts/{account_uuid}/redirects/{redirect_uuid}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AccountUuid"
        },
        {
          "$ref": "#/components/parameters/RedirectUuid"
        }
      ],
      "get": {
        "operationId": "getRedirect",
        "tags": [
          "Redirects"
        ],
        "summary": "Retrieve a redirect",
        "description": "Returns a single redirect.",
        "responses": {
          "200": {
            "description": "The redirect.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Redirect"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "put": {
        "operationId": "updateRedirect",
        "tags": [
          "Redirects"
        ],
        "summary": "Update a redirect",
        "description": "Updates a redirect. Only the attributes you send are changed. `PATCH` is accepted as well.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RedirectUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated redirect.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Redirect"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      },
      "delete": {
        "operationId": "deleteRedirect",
        "tags": [
          "Redirects"
        ],
        "summary": "Delete a redirect",
        "description": "Deletes a redirect.",
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "message": "Redirect redirect_52069e63 (old-domain.com) deleted."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/web_summary": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getWebSummary",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Web summary",
        "description": "Returns unique visitors, pageviews, visits, and the top 10 pages and traffic sources for the period in one request.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Web summary.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebSummary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/unique_visitors_count": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getUniqueVisitorsCount",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Unique visitors count",
        "description": "Returns the number of unique visitors in the period.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Unique visitors count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsCount"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/unique_visitors_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getUniqueVisitorsByDate",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Unique visitors by date",
        "description": "Returns the number of unique visitors per day, week or month.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Unique visitors by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsIntegerTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/total_pageviews_count": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getTotalPageviewsCount",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Total pageviews count",
        "description": "Returns the number of pageviews in the period.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Total pageviews count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsCount"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/pageviews_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getPageviewsByDate",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Pageviews by date",
        "description": "Returns the number of pageviews per day, week or month.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Pageviews by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsIntegerTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/total_visits_count": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getTotalVisitsCount",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Total visits count",
        "description": "Returns the number of visits in the period. A visit is one visitor within one clock hour (UTC).",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Total visits count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsCount"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/visits_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getVisitsByDate",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Visits by date",
        "description": "Returns the number of visits per day, week or month. A visit is one visitor within one clock hour (UTC).",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Visits by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsIntegerTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/pageviews_per_visit_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getPageviewsPerVisitByDate",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Pageviews per visit by date",
        "description": "Returns the average number of pageviews per visit per day, week or month.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Pageviews per visit by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsNumberTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/sources": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getTrafficSources",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Traffic sources",
        "description": "Returns referrers by number of unique visitors. Visitors without a referrer are listed as `Direct`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Traffic sources.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RankedEntryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/utm_params": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getUtmParams",
        "tags": [
          "Web Analytics"
        ],
        "summary": "UTM parameters",
        "description": "Returns the values of one UTM parameter by number of unique visitors.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "utm_param",
            "in": "query",
            "required": true,
            "description": "The UTM parameter to break down.",
            "schema": {
              "type": "string",
              "enum": [
                "utm_source",
                "utm_medium",
                "utm_campaign",
                "utm_term",
                "utm_content"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "UTM parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RankedEntryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/pages": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getPages",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Pages",
        "description": "Returns the most viewed pages. `count` is the number of pageviews.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Pages.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RankedEntryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/locations": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getLocations",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Locations",
        "description": "Returns visitors' locations by country, region or city. `count` is the number of unique visitors.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "location_type",
            "in": "query",
            "description": "Level of detail.",
            "schema": {
              "type": "string",
              "enum": [
                "country",
                "region",
                "city"
              ],
              "default": "country"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Locations.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LocationList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/devices": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getDevices",
        "tags": [
          "Web Analytics"
        ],
        "summary": "Devices",
        "description": "Returns visitors' browsers, operating systems and screen sizes. `count` is the number of unique visitors.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Devices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Devices"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/proxy_summary": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getProxySummary",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Proxy summary",
        "description": "Returns the request count, total data transfer, average upstream response time and response codes for the period in one request.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Proxy summary.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxySummary"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/request_count": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getRequestCount",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Request count",
        "description": "Returns the number of requests in the period.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Request count.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsCount"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/request_counts_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getRequestCountsByDate",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Request counts by date",
        "description": "Returns the number of requests per day, week or month.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Request counts by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsIntegerTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/total_data_transfer": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getTotalDataTransfer",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Total data transfer",
        "description": "Returns the bytes transferred in the period, incoming and outgoing combined.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Total data transfer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsBytes"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/data_transfer_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getDataTransferByDate",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Data transfer by date",
        "description": "Returns the bytes transferred per day, week or month, incoming and outgoing combined.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Data transfer by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsIntegerTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/average_response_time": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getAverageResponseTime",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Average response time",
        "description": "Returns how long the upstream took to respond, in seconds, averaged over the requests forwarded to it.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Average response time.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsDuration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/average_response_time_by_date": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getAverageResponseTimeByDate",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Average response time by date",
        "description": "Returns the upstream's average response time in seconds per day, week or month.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "$ref": "#/components/parameters/Frequency"
          }
        ],
        "responses": {
          "200": {
            "description": "Average response time by date.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsNumberTimeSeries"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/response_time_distribution": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getResponseTimeDistribution",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Response time distribution",
        "description": "Returns the number of requests forwarded to the upstream per response time bucket.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Response time distribution.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTimeDistribution"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/response_codes": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getResponseCodes",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Response codes",
        "description": "Returns requests by HTTP status code.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Response codes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseCodeList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/bot_requests": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getBotRequests",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Bot requests",
        "description": "Returns requests from known bots and crawlers, by bot.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Bot requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RankedEntryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    },
    "/api/v1/analytics/custom_domains/{domain_uuid}/datacenter_requests": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AnalyticsDomainUuid"
        }
      ],
      "get": {
        "operationId": "getDatacenterRequests",
        "tags": [
          "Proxy Analytics"
        ],
        "summary": "Datacenter requests",
        "description": "Returns requests from datacenter and cloud provider IP addresses, by provider.",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "Datacenter requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DatacenterList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/AnalyticsBadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/AnalyticsForbidden"
          },
          "404": {
            "$ref": "#/components/responses/AnalyticsNotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API token from Settings > API in the dashboard."
      }
    },
    "parameters": {
      "AccountUuid": {
        "name": "account_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of the account.",
        "schema": {
          "type": "string"
        },
        "example": "acc_d36c56a3"
      },
      "UpstreamUuid": {
        "name": "upstream_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of the upstream.",
        "schema": {
          "type": "string"
        },
        "example": "upstream_180e8083"
      },
      "DomainUuid": {
        "name": "domain_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of the custom domain.",
        "schema": {
          "type": "string"
        },
        "example": "domain_52069e63"
      },
      "RuleUuid": {
        "name": "rule_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of the rule.",
        "schema": {
          "type": "string"
        },
        "example": "rule_01234abc"
      },
      "CertificateUuid": {
        "name": "certificate_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of the custom certificate.",
        "schema": {
          "type": "string"
        },
        "example": "cert_1a2b3c4d"
      },
      "RedirectUuid": {
        "name": "redirect_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of the redirect.",
        "schema": {
          "type": "string"
        },
        "example": "redirect_52069e63"
      },
      "AnalyticsDomainUuid": {
        "name": "domain_uuid",
        "in": "path",
        "required": true,
        "description": "UUID of a custom domain in any of your accounts.",
        "schema": {
          "type": "string"
        },
        "example": "domain_52069e63"
      },
      "Page": {
        "name": "page",
        "in": "query",
        "description": "Page number, starting at 1. A page past the last one returns the last page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "PerPage": {
        "name": "per_page",
        "in": "query",
        "description": "Number of items per page. Values above 100 are capped at 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "From": {
        "name": "from",
        "in": "query",
        "description": "Start of the period as an ISO 8601 date (`YYYY-MM-DD`) or date-time, in UTC. Defaults to the start of the day 30 days ago. Data is available from 2025-07-01; earlier dates return zeros.",
        "schema": {
          "type": "string"
        },
        "example": "2024-01-01"
      },
      "To": {
        "name": "to",
        "in": "query",
        "description": "End of the period as an ISO 8601 date (`YYYY-MM-DD`) or date-time, in UTC. The whole end day is included. Defaults to today. Must not be before `from`.",
        "schema": {
          "type": "string"
        },
        "example": "2024-01-31"
      },
      "Frequency": {
        "name": "frequency",
        "in": "query",
        "description": "Size of each period. Ranges longer than 31 days return weekly data when you ask for `day`, and ranges longer than 181 days always return monthly data.",
        "schema": {
          "type": "string",
          "enum": [
            "day",
            "week",
            "month"
          ],
          "default": "day"
        }
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Requests allowed per minute: `360`, or `5` for the verify DNS records endpoint.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Requests left in the current window. Always `0` on a 429 response.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix timestamp (seconds) when the current window ends. Wait until then before sending more requests.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "The API token is missing or invalid. The response has no body."
      },
      "NotFound": {
        "description": "The resource doesn't exist or doesn't belong to one of your accounts.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Upstream upstream_180e8083 not found.",
              "error_code": "not_found"
            }
          }
        }
      },
      "ValidationError": {
        "description": "The request failed validation. `error_code` is `<attribute>_<error>` for the first error.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Host has already been taken",
              "error_code": "host_taken"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "The account doesn't have an active subscription.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "An active subscription is required to create upstreams, custom domains, and redirects."
            }
          }
        }
      },
      "InvalidRulePositions": {
        "description": "`rule_positions` is missing or invalid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Rule positions must use existing rules and distinct positive positions.",
              "error_code": "invalid_position"
            }
          }
        }
      },
      "AnalyticsBadRequest": {
        "description": "A query parameter is invalid. `error_code` is one of `invalid_frequency`, `invalid_date_range`, `invalid_utm_param` or `invalid_location_type`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "From date must be before to date",
              "error_code": "invalid_date_range"
            }
          }
        }
      },
      "AnalyticsForbidden": {
        "description": "Analytics isn't enabled for the account that owns the domain.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "You currently don’t have access to Analytics API. Please contact our Customer Support team to learn more and unlock this feature."
            }
          }
        }
      },
      "AnalyticsNotFound": {
        "description": "The custom domain doesn't exist or doesn't belong to one of your accounts.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Custom domain not found",
              "error_code": "not_found"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded: 360 requests per minute per API token, and 5 per minute for verify DNS records.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/X-RateLimit-Limit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/X-RateLimit-Remaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/X-RateLimit-Reset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Rate Limit Exceeded",
              "error_code": "rate_limited"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Error response. Validation errors only report the first error found.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "examples": [
              "Upstream upstream_180e8083 not found."
            ]
          },
          "error_code": {
            "type": "string",
            "description": "Machine-readable error code. Validation errors use `<attribute>_<error>`, for example `host_taken`, `host_invalid` or `host_blank`. Some errors (for example 402, an unknown account, and the analytics 403) don't include an error code.",
            "examples": [
              "not_found"
            ]
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          }
        }
      },
      "User": {
        "type": "object",
        "description": "The user that owns the API token.",
        "required": [
          "id",
          "name",
          "avatar_url"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "examples": [
              1
            ]
          },
          "name": {
            "type": "string",
            "examples": [
              "Rocky Balboa"
            ]
          },
          "avatar_url": {
            "type": "string",
            "description": "URL of the user's avatar.",
            "examples": [
              "https://secure.gravatar.com/avatar/xxxxxxx.png?default=mp&rating=pg&size=48"
            ]
          }
        }
      },
      "Account": {
        "type": "object",
        "required": [
          "uuid",
          "name",
          "personal",
          "owner_uuid",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the account.",
            "examples": [
              "acc_d36c56a3"
            ]
          },
          "name": {
            "type": "string",
            "description": "Name of the account.",
            "examples": [
              "Rocky Balboa"
            ]
          },
          "personal": {
            "type": "boolean",
            "description": "Whether the account is a personal account."
          },
          "owner_uuid": {
            "type": "string",
            "description": "Unique identifier for the account owner.",
            "examples": [
              "user_33e1d4c2"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the account was created."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the account was last updated."
          }
        }
      },
      "Pagination": {
        "type": "object",
        "required": [
          "page",
          "count"
        ],
        "properties": {
          "page": {
            "type": "integer",
            "description": "The page that was returned. A page past the last one returns the last page.",
            "examples": [
              1
            ]
          },
          "count": {
            "type": "integer",
            "description": "Total number of items in the collection.",
            "examples": [
              237
            ]
          }
        }
      },
      "RulePagination": {
        "type": "object",
        "required": [
          "page",
          "count",
          "items",
          "pages"
        ],
        "properties": {
          "page": {
            "type": "integer",
            "description": "The page that was returned.",
            "examples": [
              1
            ]
          },
          "count": {
            "type": "integer",
            "description": "Total number of rules.",
            "examples": [
              10
            ]
          },
          "items": {
            "type": "integer",
            "description": "Number of items per page.",
            "examples": [
              20
            ]
          },
          "pages": {
            "type": "integer",
            "description": "Total number of pages.",
            "examples": [
              1
            ]
          }
        }
      },
      "Upstream": {
        "type": "object",
        "description": "The server that the reverse proxy forwards requests to, usually your web application.",
        "required": [
          "uuid",
          "host",
          "port",
          "tls",
          "compression_enabled",
          "geocoding_enabled",
          "bubble_io",
          "auth_token",
          "created_at",
          "updated_at",
          "account_uuid"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the upstream.",
            "examples": [
              "upstream_180e8083"
            ]
          },
          "host": {
            "type": "string",
            "description": "Host of your web application, for example `app.mysaas.com`.",
            "examples": [
              "app.mysaas.com"
            ]
          },
          "port": {
            "type": "integer",
            "description": "Port your web application listens on.",
            "examples": [
              443
            ]
          },
          "tls": {
            "type": "boolean",
            "description": "Whether the proxy connects to the upstream over TLS."
          },
          "compression_enabled": {
            "type": "boolean",
            "description": "Whether responses over 512 bytes are compressed with gzip or zstd, based on the client's `Accept-Encoding` header."
          },
          "geocoding_enabled": {
            "type": "boolean",
            "description": "Whether geolocation headers (`X-SaaS-GeoIp-*`) based on the visitor's IP address are added to forwarded requests."
          },
          "bubble_io": {
            "type": "boolean",
            "description": "Whether the upstream is a Bubble.io app."
          },
          "auth_token": {
            "type": "string",
            "description": "A secret sent with every forwarded request in the `X-SaaS-Domains-Auth-Token` header, so your app can check that the request came through SaaS Custom Domains. 1 to 64 letters, digits, dashes or underscores.",
            "examples": [
              "abcdef123456"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the upstream was created."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the upstream was last updated."
          },
          "account_uuid": {
            "type": "string",
            "description": "UUID of the account that owns the upstream.",
            "examples": [
              "acc_d36c56a3"
            ]
          }
        }
      },
      "UpstreamCreate": {
        "type": "object",
        "required": [
          "host"
        ],
        "properties": {
          "host": {
            "type": "string",
            "description": "Host of your web application, for example `app.mysaas.com`. Must be a valid hostname, can't be a wildcard, and must not already be used by another upstream.",
            "examples": [
              "app.mysaas.com"
            ]
          },
          "port": {
            "type": "integer",
            "default": 443,
            "description": "Port your web application listens on."
          },
          "tls": {
            "type": "boolean",
            "default": true,
            "description": "Whether the proxy connects to the upstream over TLS. Turn it off and set `port` to `80` if your upstream only serves plain HTTP."
          },
          "bubble_io": {
            "type": "boolean",
            "default": false,
            "description": "Whether the upstream is a Bubble.io app."
          },
          "compression_enabled": {
            "type": "boolean",
            "default": true,
            "description": "Whether responses over 512 bytes are compressed with gzip or zstd."
          },
          "geocoding_enabled": {
            "type": "boolean",
            "default": false,
            "description": "Whether geolocation headers are added to forwarded requests."
          },
          "auth_token": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{1,64}$",
            "description": "A secret sent with every forwarded request in the `X-SaaS-Domains-Auth-Token` header, so your app can check that the request came through SaaS Custom Domains. 1 to 64 letters, digits, dashes or underscores. If you leave it out, a random 32-character token is generated."
          }
        }
      },
      "UpstreamList": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Upstream"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "CustomDomain": {
        "type": "object",
        "required": [
          "uuid",
          "host",
          "created_at",
          "updated_at",
          "last_dns_check_at",
          "status",
          "prepend_path",
          "redirect_to_www",
          "acme_challenge_dns_record_status",
          "challenge_type",
          "instructions_recipient",
          "tls_certificate_issued",
          "instructions_email_sent_at",
          "bubble_target_path",
          "meta_title",
          "meta_description",
          "meta_favicon_url",
          "meta_image_url",
          "upstream_uuid",
          "delegated_domain_control_validation_record_hostname",
          "delegated_domain_control_validation_record_value"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the custom domain.",
            "examples": [
              "domain_52069e63"
            ]
          },
          "host": {
            "type": "string",
            "description": "The domain your customer uses to reach your app. Wildcards such as `*.example.com` are allowed.",
            "examples": [
              "app.user.com"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the custom domain was created."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the custom domain was last updated."
          },
          "last_dns_check_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the DNS records were last checked."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending_check",
              "dns_records_found",
              "dns_records_not_found",
              "dns_check_unnecessary"
            ],
            "description": "Status of the DNS record that points the domain to the proxy. Wildcard domains are `dns_check_unnecessary`."
          },
          "prepend_path": {
            "type": [
              "string",
              "null"
            ],
            "description": "Path prefix added to every request forwarded to the upstream. For example, with `sites/client1` a request to `/about` is forwarded as `/sites/client1/about`."
          },
          "redirect_to_www": {
            "type": "boolean",
            "description": "Whether the apex domain redirects to its `www` subdomain."
          },
          "acme_challenge_dns_record_status": {
            "type": "string",
            "enum": [
              "valid",
              "pending",
              "not_found",
              "invalid"
            ],
            "description": "Status of the `_acme-challenge` DNS record. Only meaningful for domains using the `dns01` challenge type."
          },
          "challenge_type": {
            "type": "string",
            "enum": [
              "http01",
              "dns01"
            ],
            "description": "How certificate issuance is validated. `http01` issues certificates on demand. `dns01` issues them once the `_acme-challenge` DNS record is found."
          },
          "instructions_recipient": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "description": "Email address the DNS setup instructions were sent to, if any."
          },
          "tls_certificate_issued": {
            "type": "boolean",
            "description": "Whether a TLS certificate has been issued for the domain."
          },
          "instructions_email_sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When the DNS setup instructions email was sent."
          },
          "bubble_target_path": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bubble.io upstreams only. The page in your Bubble app that visitors are routed to, for example `stores/nike`."
          },
          "meta_title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bubble.io upstreams only. Page title for browser tabs, search results and social previews."
          },
          "meta_description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bubble.io upstreams only. Description for search results and link previews."
          },
          "meta_favicon_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bubble.io upstreams only. URL of the favicon."
          },
          "meta_image_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Bubble.io upstreams only. URL of the social preview image."
          },
          "upstream_uuid": {
            "type": "string",
            "description": "UUID of the upstream the domain belongs to.",
            "examples": [
              "upstream_3f43d84c"
            ]
          },
          "delegated_domain_control_validation_record_hostname": {
            "type": [
              "string",
              "null"
            ],
            "description": "Hostname of the `_acme-challenge` CNAME record to create. Only set for `dns01` domains.",
            "examples": [
              "_acme-challenge.app.com"
            ]
          },
          "delegated_domain_control_validation_record_value": {
            "type": [
              "string",
              "null"
            ],
            "description": "Value of the `_acme-challenge` CNAME record to create. Only set for `dns01` domains.",
            "examples": [
              "_acme-challenge.app.com.challenges.saascustomdomains.com"
            ]
          }
        }
      },
      "CustomDomainCreate": {
        "type": "object",
        "required": [
          "host"
        ],
        "properties": {
          "host": {
            "type": "string",
            "description": "The domain your customer uses to reach your app. Your customer points it to `in.saascustomdomains.com` with a CNAME record. Wildcards such as `*.example.com` are allowed and must use the `dns01` challenge type. Must not already be in use.",
            "examples": [
              "app.user.com"
            ]
          },
          "instructions_recipient": {
            "type": "string",
            "format": "email",
            "description": "Email address to send the DNS setup instructions to. Requires a confirmed Sender Signature in your account."
          },
          "challenge_type": {
            "type": "string",
            "enum": [
              "http01",
              "dns01"
            ],
            "default": "http01",
            "description": "How certificate issuance is validated. Wildcard domains must use `dns01`."
          },
          "redirect_to_www": {
            "type": "boolean",
            "default": false,
            "description": "Redirect the apex domain to its `www` subdomain. Only allowed on apex domains, not on subdomains or wildcards. The `www` domain gets its own certificate, counts as a second domain on your bill, and needs its own CNAME record pointing to `in.saascustomdomains.com`."
          },
          "prepend_path": {
            "type": "string",
            "description": "Path prefix added to every request forwarded to the upstream. Can only contain letters, numbers, dashes, underscores, colons and forward slashes. Leading and trailing slashes are removed."
          },
          "bubble_target_path": {
            "type": "string",
            "description": "Bubble.io upstreams only. The page in your Bubble app that visitors are routed to. Can only contain letters, numbers, dashes, underscores, colons and forward slashes. Leading and trailing slashes are removed."
          },
          "meta_title": {
            "type": "string",
            "maxLength": 255,
            "description": "Bubble.io upstreams only. Page title."
          },
          "meta_description": {
            "type": "string",
            "maxLength": 255,
            "description": "Bubble.io upstreams only. Page description."
          },
          "meta_favicon_url": {
            "type": "string",
            "description": "Bubble.io upstreams only. An `http://` or `https://` URL of the favicon."
          },
          "meta_image_url": {
            "type": "string",
            "description": "Bubble.io upstreams only. An `http://` or `https://` URL of the social preview image."
          }
        }
      },
      "CustomDomainList": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomDomain"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "DnsVerificationResult": {
        "type": "object",
        "required": [
          "host",
          "dns_status",
          "message"
        ],
        "properties": {
          "host": {
            "type": "string",
            "examples": [
              "app.example.com"
            ]
          },
          "dns_status": {
            "type": "string",
            "enum": [
              "valid",
              "pending",
              "invalid"
            ],
            "description": "`valid`: the required DNS records were found and the domain is ready. `pending`: the check hasn't finished yet. `invalid`: the records weren't found and will be checked again later. For wildcard domains this reflects the `_acme-challenge` record."
          },
          "message": {
            "type": "string",
            "examples": [
              "DNS records verification complete."
            ]
          }
        }
      },
      "PathMatcher": {
        "type": "object",
        "description": "Matches the URL path.",
        "required": [
          "type",
          "operator",
          "value"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "path"
          },
          "operator": {
            "type": "string",
            "enum": [
              "is",
              "is_not",
              "starts_with",
              "ends_with",
              "contains",
              "does_not_contain"
            ]
          },
          "value": {
            "type": "string",
            "minLength": 1,
            "pattern": "^/?[A-Za-z0-9/._~-]*$",
            "description": "Path to match. Letters, digits, `/`, `-`, `.`, `_` and `~` only.",
            "examples": [
              "/blog"
            ]
          }
        }
      },
      "MethodMatcher": {
        "type": "object",
        "description": "Matches the HTTP method.",
        "required": [
          "type",
          "operator"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "method"
          },
          "operator": {
            "type": "string",
            "enum": [
              "is",
              "is_not",
              "is_unknown",
              "has_any_value"
            ]
          },
          "value": {
            "type": "string",
            "enum": [
              "GET",
              "POST",
              "PUT",
              "DELETE",
              "PATCH",
              "OPTIONS",
              "HEAD"
            ],
            "description": "HTTP method to match. Required unless `operator` is `is_unknown` or `has_any_value`."
          }
        }
      },
      "HeaderMatcherParam": {
        "type": "object",
        "required": [
          "name",
          "operator"
        ],
        "properties": {
          "name": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+$",
            "description": "Header name. Letters, digits, `-` and `_` only.",
            "examples": [
              "User-Agent"
            ]
          },
          "operator": {
            "type": "string",
            "enum": [
              "is",
              "is_not",
              "starts_with",
              "ends_with",
              "contains",
              "does_not_contain",
              "is_unknown",
              "has_any_value"
            ]
          },
          "value": {
            "type": "string",
            "description": "Value to compare with. Required unless `operator` is `is_unknown` or `has_any_value`."
          }
        }
      },
      "HeaderMatcher": {
        "type": "object",
        "description": "Matches request headers. All header parameters must match.",
        "required": [
          "type",
          "header_params"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "header"
          },
          "header_params": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/HeaderMatcherParam"
            }
          }
        }
      },
      "QueryMatcherParam": {
        "type": "object",
        "required": [
          "key",
          "operator"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]+$",
            "description": "Query parameter name. Letters, digits, `-` and `_` only.",
            "examples": [
              "version"
            ]
          },
          "operator": {
            "type": "string",
            "enum": [
              "is",
              "is_not",
              "starts_with",
              "ends_with",
              "contains",
              "does_not_contain",
              "is_unknown",
              "has_any_value"
            ]
          },
          "value": {
            "type": "string",
            "description": "Value to compare with. Required unless `operator` is `is_unknown` or `has_any_value`."
          }
        }
      },
      "QueryMatcher": {
        "type": "object",
        "description": "Matches query string parameters. All query parameters must match.",
        "required": [
          "type",
          "query_params"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "query"
          },
          "query_params": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/QueryMatcherParam"
            }
          }
        }
      },
      "CountryMatcher": {
        "type": "object",
        "description": "Matches the visitor's country, determined from their IP address.",
        "required": [
          "type",
          "operator"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "country"
          },
          "operator": {
            "type": "string",
            "enum": [
              "is",
              "is_not",
              "is_unknown",
              "has_any_value"
            ],
            "description": "`is_unknown` matches when the country couldn't be determined. `has_any_value` matches when it could."
          },
          "country_codes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Z]{2}$"
            },
            "description": "ISO 3166-1 alpha-2 country codes, for example `US`. At least one is required for `is` and `is_not`.",
            "examples": [
              [
                "US",
                "CA"
              ]
            ]
          }
        }
      },
      "RemoteIpMatcher": {
        "type": "object",
        "description": "Matches the visitor's IP address.",
        "required": [
          "type",
          "operator",
          "ranges"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "remote_ip"
          },
          "operator": {
            "type": "string",
            "enum": [
              "is",
              "is_not"
            ]
          },
          "ranges": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string"
            },
            "description": "IPv4 or IPv6 addresses or CIDR ranges.",
            "examples": [
              [
                "203.0.113.0/24",
                "2001:db8::/32"
              ]
            ]
          }
        }
      },
      "Matcher": {
        "description": "A condition a request must meet for the rule to apply. A rule can have at most one matcher of each type.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/PathMatcher"
          },
          {
            "$ref": "#/components/schemas/MethodMatcher"
          },
          {
            "$ref": "#/components/schemas/HeaderMatcher"
          },
          {
            "$ref": "#/components/schemas/QueryMatcher"
          },
          {
            "$ref": "#/components/schemas/CountryMatcher"
          },
          {
            "$ref": "#/components/schemas/RemoteIpMatcher"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "path": "#/components/schemas/PathMatcher",
            "method": "#/components/schemas/MethodMatcher",
            "header": "#/components/schemas/HeaderMatcher",
            "query": "#/components/schemas/QueryMatcher",
            "country": "#/components/schemas/CountryMatcher",
            "remote_ip": "#/components/schemas/RemoteIpMatcher"
          }
        }
      },
      "StaticResponseHandler": {
        "type": "object",
        "description": "Returns a fixed response without forwarding the request to the upstream.",
        "required": [
          "type",
          "status_code",
          "body"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "static_response"
          },
          "status_code": {
            "type": "integer",
            "minimum": 100,
            "maximum": 599,
            "examples": [
              410
            ]
          },
          "body": {
            "type": "string",
            "minLength": 1,
            "examples": [
              "Gone"
            ]
          }
        }
      },
      "RewriteHandler": {
        "type": "object",
        "description": "Rewrites the request URI before it is forwarded to the upstream.",
        "required": [
          "type",
          "uri"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "rewrite"
          },
          "uri": {
            "type": "string",
            "pattern": "^/",
            "description": "Path to rewrite the request to. Must start with `/` and can't include a scheme or host. Supported placeholders: `{http.request.uri}`, `{http.request.uri.path}`, `{http.request.uri.path.dir}`, `{http.request.uri.path.file}` and `{http.request.uri.query}`.",
            "examples": [
              "/blog{http.request.uri.path}?source=proxy&{http.request.uri.query}"
            ]
          }
        }
      },
      "Replacement": {
        "type": "object",
        "required": [
          "search",
          "replace"
        ],
        "properties": {
          "search": {
            "type": "string",
            "minLength": 1,
            "description": "Text to search for."
          },
          "replace": {
            "type": "string",
            "description": "Replacement text. Can be empty."
          }
        }
      },
      "ReplaceResponseHandler": {
        "type": "object",
        "description": "Replaces text in the response body.",
        "required": [
          "type",
          "replacements"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "replace_response"
          },
          "replacements": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Replacement"
            }
          }
        }
      },
      "ResponseHeader": {
        "type": "object",
        "required": [
          "name",
          "value"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1
          },
          "value": {
            "type": "string"
          }
        }
      },
      "SetResponseHeaderHandler": {
        "type": "object",
        "description": "Sets headers on the response.",
        "required": [
          "type",
          "headers"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "set_response_header"
          },
          "headers": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/ResponseHeader"
            }
          }
        }
      },
      "DeleteResponseHeaderHandler": {
        "type": "object",
        "description": "Removes headers from the response.",
        "required": [
          "type",
          "headers"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "delete_response_header"
          },
          "headers": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "minLength": 1
                }
              }
            }
          }
        }
      },
      "RedirectHandler": {
        "type": "object",
        "description": "Redirects the request to another URL.",
        "required": [
          "type",
          "location",
          "status_code"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "redirect"
          },
          "location": {
            "type": "string",
            "description": "URL to redirect to. Must start with `http://` or `https://`. Supported placeholders: `{http.request.uri}`, `{http.request.uri.path}`, `{http.request.uri.path.dir}`, `{http.request.uri.path.file}` and `{http.request.uri.query}`.",
            "examples": [
              "https://new-location.example.com{http.request.uri.path}"
            ]
          },
          "status_code": {
            "type": "integer",
            "enum": [
              301,
              302
            ],
            "description": "`301` (permanent) or `302` (temporary)."
          }
        }
      },
      "RateLimitKeyPart": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "ip",
              "domain",
              "path",
              "query",
              "header"
            ]
          },
          "name": {
            "type": "string",
            "description": "Header name. Required when `type` is `header`. Must be a valid header name and unique within the handler.",
            "examples": [
              "Authorization"
            ]
          }
        }
      },
      "RateLimitHandler": {
        "type": "object",
        "description": "Lets through at most `limit_value` matching requests per window. Requests over the limit get a `429 Too Many Requests` response.",
        "required": [
          "type",
          "limit_value",
          "window_value",
          "window_unit"
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "rate_limit"
          },
          "limit_value": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum number of matching requests per window."
          },
          "window_value": {
            "type": "integer",
            "minimum": 1,
            "description": "Length of the window in `window_unit`s: 1 to 60 for `m`, 30 to 60 for `s`, 1 to 24 for `h`, and 1 for `d`."
          },
          "window_unit": {
            "type": "string",
            "enum": [
              "s",
              "m",
              "h",
              "d"
            ],
            "description": "`m` (minutes) is available to every account. `s`, `h` and `d` are enabled on request; contact support."
          },
          "key_parts": {
            "type": "array",
            "default": [],
            "items": {
              "$ref": "#/components/schemas/RateLimitKeyPart"
            },
            "description": "How requests are counted. With an empty array all matching requests share one counter. Otherwise each unique combination of the key part values gets its own counter. On an upstream rule, counters are shared by every custom domain on the upstream unless you add a `domain` key part."
          }
        }
      },
      "Handler": {
        "description": "An action the rule performs when it matches.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/StaticResponseHandler"
          },
          {
            "$ref": "#/components/schemas/RewriteHandler"
          },
          {
            "$ref": "#/components/schemas/ReplaceResponseHandler"
          },
          {
            "$ref": "#/components/schemas/SetResponseHeaderHandler"
          },
          {
            "$ref": "#/components/schemas/DeleteResponseHeaderHandler"
          },
          {
            "$ref": "#/components/schemas/RedirectHandler"
          },
          {
            "$ref": "#/components/schemas/RateLimitHandler"
          }
        ],
        "discriminator": {
          "propertyName": "type",
          "mapping": {
            "static_response": "#/components/schemas/StaticResponseHandler",
            "rewrite": "#/components/schemas/RewriteHandler",
            "replace_response": "#/components/schemas/ReplaceResponseHandler",
            "set_response_header": "#/components/schemas/SetResponseHeaderHandler",
            "delete_response_header": "#/components/schemas/DeleteResponseHeaderHandler",
            "redirect": "#/components/schemas/RedirectHandler",
            "rate_limit": "#/components/schemas/RateLimitHandler"
          }
        }
      },
      "Rule": {
        "type": "object",
        "required": [
          "uuid",
          "name",
          "active",
          "position",
          "matchers",
          "handlers",
          "scope",
          "upstream_uuid",
          "custom_domain_uuid",
          "account_uuid",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the rule.",
            "examples": [
              "rule_01234abc"
            ]
          },
          "name": {
            "type": "string",
            "description": "Human-readable name.",
            "examples": [
              "Block legacy API"
            ]
          },
          "active": {
            "type": "boolean",
            "description": "Whether the rule is active."
          },
          "position": {
            "type": "integer",
            "description": "Evaluation order within the rule's scope. Lower numbers are evaluated first.",
            "examples": [
              1
            ]
          },
          "matchers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Matcher"
            },
            "description": "Conditions, combined with AND. An empty array matches every request."
          },
          "handlers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Handler"
            },
            "description": "Actions to perform when the rule matches."
          },
          "scope": {
            "type": "string",
            "enum": [
              "upstream",
              "domain"
            ],
            "description": "`upstream` rules apply to every custom domain on the upstream. `domain` rules apply to one custom domain."
          },
          "upstream_uuid": {
            "type": "string",
            "description": "UUID of the upstream. For domain rules, the upstream the custom domain belongs to.",
            "examples": [
              "upstream_456def"
            ]
          },
          "custom_domain_uuid": {
            "type": [
              "string",
              "null"
            ],
            "description": "UUID of the custom domain. `null` for upstream rules.",
            "examples": [
              "domain_789ghi"
            ]
          },
          "account_uuid": {
            "type": "string",
            "description": "UUID of the account that owns the rule.",
            "examples": [
              "acc_123abc"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the rule was created."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the rule was last updated."
          }
        }
      },
      "RuleCreate": {
        "type": "object",
        "required": [
          "name",
          "matchers",
          "handlers"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable name.",
            "examples": [
              "Limit login attempts"
            ]
          },
          "active": {
            "type": "boolean",
            "default": true,
            "description": "Whether the rule is active."
          },
          "matchers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Matcher"
            },
            "description": "Conditions, combined with AND. At most one matcher of each type. Send an empty array to match every request."
          },
          "handlers": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Handler"
            },
            "description": "Actions to perform when the rule matches."
          }
        }
      },
      "RuleUpdate": {
        "type": "object",
        "description": "Only the attributes you send are changed. `matchers` and `handlers` replace the existing arrays.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable name."
          },
          "active": {
            "type": "boolean",
            "description": "Whether the rule is active."
          },
          "matchers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Matcher"
            },
            "description": "Conditions, combined with AND."
          },
          "handlers": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Handler"
            },
            "description": "Actions to perform when the rule matches."
          }
        }
      },
      "RulePositionsUpdate": {
        "type": "object",
        "required": [
          "rule_positions"
        ],
        "properties": {
          "rule_positions": {
            "type": "array",
            "description": "New positions. Each UUID must belong to a rule in this scope and appear once, and positions must be distinct positive integers. Rules you leave out keep their position.",
            "items": {
              "type": "object",
              "required": [
                "uuid",
                "position"
              ],
              "properties": {
                "uuid": {
                  "type": "string",
                  "description": "UUID of the rule.",
                  "examples": [
                    "rule_01234abc"
                  ]
                },
                "position": {
                  "type": "integer",
                  "minimum": 1,
                  "description": "New position of the rule.",
                  "examples": [
                    1
                  ]
                }
              }
            }
          }
        }
      },
      "RuleList": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Rule"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/RulePagination"
          }
        }
      },
      "CustomCertificate": {
        "type": "object",
        "description": "A TLS certificate you uploaded in the dashboard.",
        "required": [
          "uuid",
          "expires_at",
          "not_before",
          "fingerprint",
          "issuer",
          "public_key_sha",
          "sans",
          "serial_number",
          "signature_algorithm",
          "subject",
          "created_at"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the certificate.",
            "examples": [
              "cert_1a2b3c4d"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the certificate expires."
          },
          "not_before": {
            "type": "string",
            "format": "date-time",
            "description": "The certificate isn't valid before this time."
          },
          "fingerprint": {
            "type": "string",
            "description": "SHA-256 fingerprint of the certificate, hex-encoded."
          },
          "issuer": {
            "type": "string",
            "description": "Distinguished name of the certificate authority.",
            "examples": [
              "/C=US/O=Example Org/CN=Example CA"
            ]
          },
          "public_key_sha": {
            "type": "string",
            "description": "SHA-256 hash of the public key, hex-encoded."
          },
          "sans": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Subject Alternative Names on the certificate.",
            "examples": [
              [
                "example.com",
                "www.example.com"
              ]
            ]
          },
          "serial_number": {
            "type": "string",
            "description": "Serial number of the certificate.",
            "examples": [
              "1234567890"
            ]
          },
          "signature_algorithm": {
            "type": "string",
            "description": "Algorithm used to sign the certificate.",
            "examples": [
              "sha256WithRSAEncryption"
            ]
          },
          "subject": {
            "type": "string",
            "description": "Distinguished name of the certificate's subject.",
            "examples": [
              "/C=US/O=Example Org/CN=example.com"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the certificate was added to SaaS Custom Domains."
          }
        }
      },
      "CustomCertificateList": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomCertificate"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "Redirect": {
        "type": "object",
        "description": "Redirects requests for a host (and optionally a path) to another URL.",
        "required": [
          "uuid",
          "source_host",
          "match_path",
          "destination_url",
          "redirect_type",
          "preserve_path",
          "preserve_query_string",
          "active",
          "created_at",
          "updated_at",
          "account_uuid"
        ],
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the redirect.",
            "examples": [
              "redirect_52069e63"
            ]
          },
          "source_host": {
            "type": "string",
            "description": "Host the requests arrive on, for example `old-domain.com`. Must be a valid hostname without wildcards. Stored in lowercase.",
            "examples": [
              "old-domain.com"
            ]
          },
          "match_path": {
            "type": "string",
            "description": "Path to match. Letters, numbers, dashes, underscores, dots and forward slashes, with an optional trailing `*` for prefix matching. `*` matches every path. The path is stored with a leading slash, so `*` is returned as `/*`.",
            "examples": [
              "/blog/*"
            ]
          },
          "destination_url": {
            "type": "string",
            "description": "URL to redirect to. Must start with `http://` or `https://`. Stored in lowercase.",
            "examples": [
              "https://new-domain.com"
            ]
          },
          "redirect_type": {
            "type": "string",
            "enum": [
              "permanent",
              "found"
            ],
            "description": "`permanent` responds with 301. `found` responds with 302 (temporary)."
          },
          "preserve_path": {
            "type": "boolean",
            "description": "Whether the original request path is appended to the destination URL."
          },
          "preserve_query_string": {
            "type": "boolean",
            "description": "Whether the original query string is appended to the destination URL."
          },
          "active": {
            "type": "boolean",
            "description": "Whether the redirect is active. Inactive redirects don't redirect any traffic."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the redirect was created."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the redirect was last updated."
          },
          "account_uuid": {
            "type": "string",
            "description": "UUID of the account that owns the redirect.",
            "examples": [
              "acc_3f43d84c"
            ]
          }
        }
      },
      "RedirectCreate": {
        "type": "object",
        "required": [
          "source_host",
          "destination_url"
        ],
        "properties": {
          "source_host": {
            "type": "string",
            "description": "Host the requests arrive on, for example `old-domain.com`. Must be a valid hostname without wildcards. Stored in lowercase.",
            "examples": [
              "old-domain.com"
            ]
          },
          "destination_url": {
            "type": "string",
            "description": "URL to redirect to. Must start with `http://` or `https://`. Stored in lowercase.",
            "examples": [
              "https://new-domain.com"
            ]
          },
          "match_path": {
            "type": "string",
            "description": "Path to match. Letters, numbers, dashes, underscores, dots and forward slashes, with an optional trailing `*` for prefix matching. `*` matches every path. The path is stored with a leading slash, so `*` is returned as `/*`.",
            "examples": [
              "/blog/*"
            ],
            "default": "*"
          },
          "redirect_type": {
            "type": "string",
            "enum": [
              "permanent",
              "found"
            ],
            "description": "`permanent` responds with 301. `found` responds with 302 (temporary).",
            "default": "permanent"
          },
          "preserve_path": {
            "type": "boolean",
            "description": "Whether the original request path is appended to the destination URL.",
            "default": true
          },
          "preserve_query_string": {
            "type": "boolean",
            "description": "Whether the original query string is appended to the destination URL.",
            "default": true
          },
          "active": {
            "type": "boolean",
            "description": "Whether the redirect is active. Inactive redirects don't redirect any traffic.",
            "default": true
          }
        }
      },
      "RedirectUpdate": {
        "type": "object",
        "description": "Only the attributes you send are changed.",
        "properties": {
          "source_host": {
            "type": "string",
            "description": "Host the requests arrive on, for example `old-domain.com`. Must be a valid hostname without wildcards. Stored in lowercase.",
            "examples": [
              "old-domain.com"
            ]
          },
          "match_path": {
            "type": "string",
            "description": "Path to match. Letters, numbers, dashes, underscores, dots and forward slashes, with an optional trailing `*` for prefix matching. `*` matches every path. The path is stored with a leading slash, so `*` is returned as `/*`.",
            "examples": [
              "/blog/*"
            ]
          },
          "destination_url": {
            "type": "string",
            "description": "URL to redirect to. Must start with `http://` or `https://`. Stored in lowercase.",
            "examples": [
              "https://new-domain.com"
            ]
          },
          "redirect_type": {
            "type": "string",
            "enum": [
              "permanent",
              "found"
            ],
            "description": "`permanent` responds with 301. `found` responds with 302 (temporary)."
          },
          "preserve_path": {
            "type": "boolean",
            "description": "Whether the original request path is appended to the destination URL."
          },
          "preserve_query_string": {
            "type": "boolean",
            "description": "Whether the original query string is appended to the destination URL."
          },
          "active": {
            "type": "boolean",
            "description": "Whether the redirect is active. Inactive redirects don't redirect any traffic."
          }
        }
      },
      "RedirectList": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Redirect"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "AnalyticsCount": {
        "type": "object",
        "required": [
          "count"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "minimum": 0,
            "examples": [
              15234
            ]
          }
        }
      },
      "AnalyticsBytes": {
        "type": "object",
        "required": [
          "bytes"
        ],
        "properties": {
          "bytes": {
            "type": "integer",
            "minimum": 0,
            "description": "Incoming plus outgoing bytes.",
            "examples": [
              1234567890
            ]
          }
        }
      },
      "AnalyticsDuration": {
        "type": "object",
        "required": [
          "duration"
        ],
        "properties": {
          "duration": {
            "type": "number",
            "minimum": 0,
            "description": "Average upstream response time in seconds.",
            "examples": [
              0.245
            ]
          }
        }
      },
      "AnalyticsIntegerTimeSeries": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "description": "Keyed by the first day of each period (`YYYY-MM-DD`): the date itself for `day`, the Monday for `week`, and the 1st for `month`. Every period in the range is included, with `0` for periods without traffic.",
            "propertyNames": {
              "format": "date"
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            },
            "examples": [
              {
                "2024-01-01": 523,
                "2024-01-02": 612,
                "2024-01-03": 598
              }
            ]
          }
        }
      },
      "AnalyticsNumberTimeSeries": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "description": "Keyed by the first day of each period (`YYYY-MM-DD`): the date itself for `day`, the Monday for `week`, and the 1st for `month`. Every period in the range is included, with `0` for periods without traffic.",
            "propertyNames": {
              "format": "date"
            },
            "additionalProperties": {
              "type": "number",
              "minimum": 0
            },
            "examples": [
              {
                "2024-01-01": 2.4,
                "2024-01-02": 2.7,
                "2024-01-03": 2.5
              }
            ]
          }
        }
      },
      "ResponseTimeDistribution": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "description": "Number of requests per upstream response time bucket, from fastest to slowest. Buckets without requests are left out.",
            "propertyNames": {
              "enum": [
                "0-100ms",
                "100-200ms",
                "200-300ms",
                "300-400ms",
                "400-500ms",
                "500-600ms",
                "600-700ms",
                "700-800ms",
                "800-900ms",
                "900ms-1s",
                "1-1.5s",
                "1.5-2s",
                "2-3s",
                "3-5s",
                "5-10s",
                "10s+"
              ]
            },
            "additionalProperties": {
              "type": "integer",
              "minimum": 0
            },
            "examples": [
              {
                "0-100ms": 10676,
                "100-200ms": 5673,
                "200-300ms": 515
              }
            ]
          }
        }
      },
      "RankedEntry": {
        "type": "object",
        "required": [
          "name",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "newsletter"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "examples": [
              1234
            ]
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "RankedEntryList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "description": "Up to 200 entries, sorted by count.",
            "items": {
              "$ref": "#/components/schemas/RankedEntry"
            }
          }
        }
      },
      "LocationEntry": {
        "type": "object",
        "required": [
          "name",
          "country_code",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Country, region or city name.",
            "examples": [
              "United States"
            ]
          },
          "country_code": {
            "type": "string",
            "description": "ISO country code, also for regions and cities.",
            "examples": [
              "US"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of unique visitors."
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "LocationList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "description": "Up to 200 entries, sorted by count.",
            "items": {
              "$ref": "#/components/schemas/LocationEntry"
            }
          }
        }
      },
      "BrowserEntry": {
        "type": "object",
        "required": [
          "name",
          "browser_id",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "Chrome"
            ]
          },
          "browser_id": {
            "type": "string",
            "examples": [
              "chrome"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of unique visitors."
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "OperatingSystemEntry": {
        "type": "object",
        "required": [
          "name",
          "operating_system_id",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "macOS"
            ]
          },
          "operating_system_id": {
            "type": "string",
            "examples": [
              "mac"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of unique visitors."
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "ScreenSizeEntry": {
        "type": "object",
        "required": [
          "name",
          "screen_size_id",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "Desktop"
            ]
          },
          "screen_size_id": {
            "type": "string",
            "examples": [
              "desktop"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of unique visitors."
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "Devices": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "object",
            "required": [
              "browsers",
              "operating_systems",
              "screen_sizes"
            ],
            "properties": {
              "browsers": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/BrowserEntry"
                }
              },
              "operating_systems": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OperatingSystemEntry"
                }
              },
              "screen_sizes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ScreenSizeEntry"
                }
              }
            }
          }
        }
      },
      "ResponseCodeEntry": {
        "type": "object",
        "required": [
          "name",
          "http_code",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Status code and its reason phrase.",
            "examples": [
              "200 (OK)"
            ]
          },
          "http_code": {
            "type": "integer",
            "examples": [
              200
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of requests."
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "ResponseCodeList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "description": "Up to 200 entries, sorted by count.",
            "items": {
              "$ref": "#/components/schemas/ResponseCodeEntry"
            }
          }
        }
      },
      "DatacenterEntry": {
        "type": "object",
        "required": [
          "name",
          "datacenter_id",
          "count",
          "percentage"
        ],
        "properties": {
          "name": {
            "type": "string",
            "examples": [
              "Cloudflare"
            ]
          },
          "datacenter_id": {
            "type": "string",
            "examples": [
              "cloudflare"
            ]
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of requests."
          },
          "percentage": {
            "type": "number",
            "description": "Share of the total of the returned entries, in percent, rounded to two decimals.",
            "examples": [
              58.48
            ]
          }
        }
      },
      "DatacenterList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "description": "Up to 200 entries, sorted by count.",
            "items": {
              "$ref": "#/components/schemas/DatacenterEntry"
            }
          }
        }
      },
      "AccountCustomDomain": {
        "description": "A custom domain, with the account and upstream it belongs to.",
        "allOf": [
          {
            "$ref": "#/components/schemas/CustomDomain"
          },
          {
            "type": "object",
            "required": [
              "account_uuid",
              "upstream_host"
            ],
            "properties": {
              "account_uuid": {
                "type": "string",
                "description": "UUID of the account that owns the custom domain.",
                "examples": [
                  "acc_d36c56a3"
                ]
              },
              "upstream_host": {
                "type": "string",
                "description": "Host of the custom domain's upstream.",
                "examples": [
                  "app.mysaas.com"
                ]
              }
            }
          }
        ]
      },
      "AccountCustomDomainList": {
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountCustomDomain"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        }
      },
      "DnsRecord": {
        "type": "object",
        "required": [
          "type",
          "name",
          "value",
          "purpose"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "A",
              "CNAME"
            ]
          },
          "name": {
            "type": "string",
            "description": "Full hostname of the record.",
            "examples": [
              "app.user.com"
            ]
          },
          "value": {
            "type": "string",
            "examples": [
              "in.saascustomdomains.com"
            ]
          },
          "purpose": {
            "type": "string",
            "enum": [
              "proxy",
              "acme_challenge"
            ],
            "description": "`proxy` records point the domain to SaaS Custom Domains. `acme_challenge` records let us issue and renew the certificate with the `dns01` challenge, so they must stay in place."
          }
        }
      },
      "DnsRecordList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DnsRecord"
            }
          }
        }
      },
      "ProxySummary": {
        "type": "object",
        "required": [
          "request_count",
          "total_data_transfer_bytes",
          "average_response_time_seconds",
          "response_codes"
        ],
        "properties": {
          "request_count": {
            "type": "integer",
            "minimum": 0,
            "examples": [
              455630
            ]
          },
          "total_data_transfer_bytes": {
            "type": "integer",
            "minimum": 0,
            "description": "Bytes received and sent.",
            "examples": [
              28356341760
            ]
          },
          "average_response_time_seconds": {
            "type": "number",
            "description": "How long the upstream took to respond, averaged over the requests that were forwarded to it.",
            "examples": [
              0.245
            ]
          },
          "response_codes": {
            "type": "array",
            "description": "Up to 200 entries, sorted by count.",
            "items": {
              "$ref": "#/components/schemas/ResponseCodeEntry"
            }
          }
        }
      },
      "WebSummary": {
        "type": "object",
        "required": [
          "unique_visitors_count",
          "total_pageviews_count",
          "total_visits_count",
          "top_pages",
          "top_sources"
        ],
        "properties": {
          "unique_visitors_count": {
            "type": "integer",
            "minimum": 0,
            "examples": [
              5250
            ]
          },
          "total_pageviews_count": {
            "type": "integer",
            "minimum": 0,
            "examples": [
              9426
            ]
          },
          "total_visits_count": {
            "type": "integer",
            "minimum": 0,
            "examples": [
              6468
            ]
          },
          "top_pages": {
            "type": "array",
            "description": "The top 10 entries, sorted by count. `percentage` is each entry's share of the top 200 entries' total.",
            "items": {
              "$ref": "#/components/schemas/RankedEntry"
            }
          },
          "top_sources": {
            "type": "array",
            "description": "The top 10 traffic sources (referrer domains, or `Direct`), sorted by count. `percentage` is each entry's share of the top 200 entries' total.",
            "items": {
              "$ref": "#/components/schemas/RankedEntry"
            }
          }
        }
      }
    }
  }
}
