{
  "openapi": "3.1.0",
  "info": {
    "title": "Nvivio REST API",
    "version": "1",
    "summary": "Cookieless, EU-hosted web analytics: sites, statistics, visits, goals, funnels and bots, as JSON.",
    "description": "Cookieless web analytics, hosted in the EU. The dashboard has no private API: everything it shows comes from this API.\n\n**Authentication.** Send an API key as a bearer token: `Authorization: Bearer nv_…`. Keys belong to an organisation, with the scope `read` (the default) or `admin`. Make them in the dashboard (user menu › API and AI assistants) or with `POST /orgs/{org}/keys`. The API comes with Starter and up. The team, billing and notifications answer only to a signed-in person, never to an API key.\n\n**Try it without a key.** The live demo site `acme.example` can be read without a key: its numbers and visits, read only, within a fair limit per visitor. The data is made up.\n\n**Periods.** `period=today`, `yesterday`, `24h`, `7d` (the default), `30d`, `month`, `lastmonth`, `year`, `12mo` or `all`, or `from` and `to` as ISO dates. Named periods follow the site's time zone.\n\n**Shared dashboards.** A link from `POST /sites/{site}/shares` (nvivio.com/share/<token>) reads one site's numbers with `Authorization: Share <token>`: the operations marked for shared links, narrowed to what the link shows, never single visits, labels or settings.\n\n**Filters.** Repeat `f` for each filter, as in the dashboard's address: `?f=country:BE&f=path:~/blog/*&f=device:!mobile`.\n\n**Language.** Texts the API writes itself follow `Accept-Language` or `?lang=`, in the 24 EU languages; English without either.\n\n**Errors.** Every error is `{ \"error\", \"fix\", \"code\" }`: what is wrong, how to solve it, and a stable code to compare on.\n\n**Limits.** Requests with a key count per organisation and hour, by plan. Every answer carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`; above the limit the answer is `429` with the code `api.limit` and `Retry-After` in seconds.",
    "contact": {
      "name": "Nvivio support",
      "email": "support@nvivio.com",
      "url": "https://nvivio.com/docs/api"
    },
    "termsOfService": "https://nvivio.com/legal/terms"
  },
  "externalDocs": {
    "description": "The REST API in the Nvivio docs",
    "url": "https://nvivio.com/docs/api"
  },
  "servers": [
    {
      "url": "https://nvivio.com/v1",
      "description": "Nvivio, hosted in the EU"
    }
  ],
  "security": [
    {
      "apiKey": []
    },
    {
      "session": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "You, your settings and your notifications."
    },
    {
      "name": "Sites",
      "description": "Your sites, their settings, parts, data and installation."
    },
    {
      "name": "Numbers",
      "description": "Statistics of a period. All take a period and most take filters."
    },
    {
      "name": "Visits",
      "description": "Single visits and visitors, and who is online now."
    },
    {
      "name": "Goals and funnels",
      "description": "Goals with their conversions, and funnels."
    },
    {
      "name": "Bots from your server",
      "description": "The connection that lets your server forward bots that run no JavaScript."
    },
    {
      "name": "Team and keys",
      "description": "Members, invitations, API keys, usage and billing."
    },
    {
      "name": "Sharing",
      "description": "Read-only links to a site's dashboard, and your logo on them."
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Account"
        ],
        "summary": "You and your organisations",
        "description": "You, your organisations, your weekly email setting and your Overview layout. With an API key: its organisation and scopes.\n\nAccess: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "name": "readonly",
            "in": "query",
            "description": "true: no organisation is made for you and your language is not saved. Without it, a first visit makes your organisation, and the language you ask in becomes the one of your emails. Invitations for you are accepted either way.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "kind, organizations (each with id, name, role, plan, limits and units_this_month: the pageviews and custom events counted this calendar month; use: its sites, people and AI questions this month; offer: near or at a limit, which, and the plan that fits, or null; owners: who can change the plan), and for a person also email, weekly_mail and dashboard."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "patch": {
        "operationId": "updateMe",
        "tags": [
          "Account"
        ],
        "summary": "Change your settings",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "weekly_mail": {
                    "type": "boolean",
                    "description": "Get the weekly email on Monday."
                  },
                  "dashboard": {
                    "oneOf": [
                      {
                        "type": "object",
                        "properties": {
                          "panels": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "metrics",
                                "parts",
                                "insights",
                                "findings",
                                "sources",
                                "pages",
                                "location",
                                "tech",
                                "hours",
                                "goals",
                                "visit",
                                "ai",
                                "events",
                                "campaigns",
                                "languages",
                                "domains"
                              ]
                            },
                            "description": "The panels of the Overview, in order."
                          },
                          "hide": {
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "headline",
                                "metrics.visitors",
                                "metrics.sessions",
                                "metrics.pageviews",
                                "metrics.views_per_visit",
                                "metrics.bounce_rate",
                                "metrics.avg_duration_s",
                                "metrics.revenue",
                                "metrics.chart",
                                "sources.channel",
                                "sources.referrer",
                                "sources.utm_campaign",
                                "pages.path",
                                "pages.entry",
                                "pages.exit",
                                "location.country",
                                "location.map",
                                "location.region",
                                "location.city",
                                "tech.device",
                                "tech.browser",
                                "tech.os",
                                "tech.app_version",
                                "tech.os_version",
                                "tech.device_model",
                                "campaigns.utm_source",
                                "campaigns.utm_medium",
                                "campaigns.utm_campaign"
                              ]
                            },
                            "description": "Parts to leave out."
                          },
                          "widths": {
                            "type": "object",
                            "description": "Each panel's width in twelfths of the Overview. A width outside what the panel allows is brought within; a panel without one gets its default.",
                            "properties": {
                              "metrics": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 12,
                                "default": 12
                              },
                              "parts": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 12,
                                "default": 12
                              },
                              "insights": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 12,
                                "default": 6
                              },
                              "findings": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 12,
                                "default": 6
                              },
                              "sources": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 12,
                                "default": 6
                              },
                              "pages": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 12,
                                "default": 6
                              },
                              "location": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 8,
                                "default": 4
                              },
                              "tech": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 6,
                                "default": 4
                              },
                              "hours": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 8,
                                "default": 4
                              },
                              "goals": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 12,
                                "default": 12
                              },
                              "visit": {
                                "type": "integer",
                                "minimum": 4,
                                "maximum": 12,
                                "default": 12
                              },
                              "ai": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 6,
                                "default": 6
                              },
                              "events": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 8,
                                "default": 6
                              },
                              "campaigns": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 8,
                                "default": 6
                              },
                              "languages": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 6,
                                "default": 4
                              },
                              "domains": {
                                "type": "integer",
                                "minimum": 3,
                                "maximum": 8,
                                "default": 4
                              }
                            },
                            "additionalProperties": false
                          }
                        }
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "metrics",
                            "parts",
                            "insights",
                            "findings",
                            "sources",
                            "pages",
                            "location",
                            "tech",
                            "hours",
                            "goals",
                            "visit",
                            "ai",
                            "events",
                            "campaigns",
                            "languages",
                            "domains"
                          ]
                        },
                        "description": "Only the panels, in order."
                      },
                      {
                        "type": "null",
                        "description": "Back to the default layout."
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The settings changed: weekly_mail and/or dashboard."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/me/weekly-mail": {
      "get": {
        "operationId": "getWeeklyMail",
        "tags": [
          "Account"
        ],
        "summary": "Your weekly email as it would go out now",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "subject": {
                      "type": "string",
                      "description": "Subject."
                    },
                    "html": {
                      "type": "string",
                      "description": "HTML."
                    },
                    "text": {
                      "type": "string",
                      "description": "Plain text."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/notifications": {
      "get": {
        "operationId": "listNotifications",
        "tags": [
          "Account"
        ],
        "summary": "Notifications",
        "description": "The notifications of the organisations you own or administer, newest first, in your language.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "unread": {
                      "type": "integer",
                      "description": "Unread."
                    },
                    "notifications": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "description": "Kind."
                          },
                          "org": {
                            "type": "string",
                            "description": "Organisation."
                          },
                          "title": {
                            "type": "string",
                            "description": "Title."
                          },
                          "text": {
                            "type": "string",
                            "description": "Text."
                          },
                          "link": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Where to act."
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "When."
                          },
                          "read": {
                            "type": "boolean",
                            "description": "Read."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/notifications/seen": {
      "post": {
        "operationId": "markNotificationsSeen",
        "tags": [
          "Account"
        ],
        "summary": "Mark every notification as read",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "seen_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/feature-requests": {
      "post": {
        "operationId": "suggestFeature",
        "tags": [
          "Account"
        ],
        "summary": "Suggest a feature",
        "description": "Reaches Nvivio's support as an email from your address would, with your account, organisation and the page you were on, so the team can answer you by email. Up to 5 an hour.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "what": {
                    "type": "string",
                    "description": "What you would like, up to 2,000 characters."
                  },
                  "why": {
                    "type": "string",
                    "description": "Why, or how you would use it, up to 2,000 characters."
                  },
                  "org": {
                    "type": "string",
                    "description": "The organisation you were looking at.",
                    "format": "uuid"
                  },
                  "page": {
                    "type": "string",
                    "description": "The dashboard page you were on.",
                    "examples": [
                      "/app/shop.example/visitors"
                    ]
                  }
                },
                "required": [
                  "what"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean",
                      "description": "It arrived."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}": {
      "delete": {
        "operationId": "deleteOrganization",
        "tags": [
          "Account"
        ],
        "summary": "Delete the organisation",
        "description": "Deletes the organisation with every site and all their data. The owners get an email that confirms it.\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "confirm": {
                    "type": "string",
                    "description": "The organisation's name."
                  }
                },
                "required": [
                  "confirm"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "object",
                      "properties": {
                        "sites": {
                          "type": "integer",
                          "description": "Sites deleted."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "patch": {
        "operationId": "updateOrganization",
        "tags": [
          "Team and keys"
        ],
        "summary": "The Nvivio badge and how it looks",
        "description": "Free with the badge visible counts more; a paid plan pays less after a period with it visible (terms 5.8).\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "badge": {
                    "type": "boolean",
                    "description": "Show the badge."
                  },
                  "badge_style": {
                    "type": "object",
                    "description": "How the badge looks; unknown values fall back to the default.",
                    "properties": {
                      "size": {
                        "type": "string",
                        "description": "text (a link in your site's own font and colours), small or standard.",
                        "enum": [
                          "text",
                          "small",
                          "standard"
                        ]
                      },
                      "theme": {
                        "type": "string",
                        "description": "light or dark.",
                        "enum": [
                          "light",
                          "dark"
                        ]
                      },
                      "place": {
                        "type": "string",
                        "description": "In your footer (an element with id=\"nvivio-badge\") or the bottom right corner.",
                        "enum": [
                          "footer",
                          "corner"
                        ]
                      },
                      "lang": {
                        "type": "string",
                        "description": "The language of the HTML link.",
                        "enum": [
                          "en",
                          "bg",
                          "cs",
                          "da",
                          "de",
                          "el",
                          "es",
                          "et",
                          "fi",
                          "fr",
                          "ga",
                          "hr",
                          "hu",
                          "it",
                          "lt",
                          "lv",
                          "mt",
                          "nl",
                          "pl",
                          "pt",
                          "ro",
                          "sk",
                          "sl",
                          "sv"
                        ]
                      },
                      "icon": {
                        "type": "boolean",
                        "description": "The Nvivio ring before the text (default true)."
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "badge": {
                      "type": "boolean",
                      "description": "Show the badge."
                    },
                    "badge_style": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "How the badge looks; unknown values fall back to the default.",
                      "properties": {
                        "size": {
                          "type": "string",
                          "description": "text (a link in your site's own font and colours), small or standard.",
                          "enum": [
                            "text",
                            "small",
                            "standard"
                          ]
                        },
                        "theme": {
                          "type": "string",
                          "description": "light or dark.",
                          "enum": [
                            "light",
                            "dark"
                          ]
                        },
                        "place": {
                          "type": "string",
                          "description": "In your footer (an element with id=\"nvivio-badge\") or the bottom right corner.",
                          "enum": [
                            "footer",
                            "corner"
                          ]
                        },
                        "lang": {
                          "type": "string",
                          "description": "The language of the HTML link.",
                          "enum": [
                            "en",
                            "bg",
                            "cs",
                            "da",
                            "de",
                            "el",
                            "es",
                            "et",
                            "fi",
                            "fr",
                            "ga",
                            "hr",
                            "hu",
                            "it",
                            "lt",
                            "lv",
                            "mt",
                            "nl",
                            "pl",
                            "pt",
                            "ro",
                            "sk",
                            "sl",
                            "sv"
                          ]
                        },
                        "icon": {
                          "type": "boolean",
                          "description": "The Nvivio ring before the text (default true)."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites": {
      "get": {
        "operationId": "listSites",
        "tags": [
          "Sites"
        ],
        "summary": "Your sites",
        "description": "Every site you can read, with visitors today, yesterday (up to now and in all), in the last 7 days and online now, each in the site's time zone and counted as its stats (period=today, yesterday and 7d). Your favourites first, then by name.\n\nAccess: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "sites": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/Site"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "favorite": {
                                "type": "boolean",
                                "description": "You starred it: it comes first in your lists. Always false with an API key."
                              },
                              "visitors": {
                                "type": "object",
                                "properties": {
                                  "today": {
                                    "type": "integer",
                                    "description": "Today, from midnight in the site's time zone."
                                  },
                                  "yesterday": {
                                    "type": "integer",
                                    "description": "Yesterday."
                                  },
                                  "yesterday_so_far": {
                                    "type": "integer",
                                    "description": "Yesterday up to this time of day."
                                  },
                                  "week": {
                                    "type": "integer",
                                    "description": "Last 7 days."
                                  },
                                  "live": {
                                    "type": "integer",
                                    "description": "Online now."
                                  }
                                }
                              },
                              "last_event_at": {
                                "type": [
                                  "string",
                                  "null"
                                ],
                                "format": "date-time",
                                "description": "Last event."
                              },
                              "status": {
                                "type": "string",
                                "description": "waiting: nothing yet; quiet: nothing for 48 hours.",
                                "enum": [
                                  "waiting",
                                  "quiet",
                                  "active"
                                ]
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "createSite",
        "tags": [
          "Sites"
        ],
        "summary": "Add a site",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "org_id": {
                    "type": "string",
                    "description": "The organisation.",
                    "format": "uuid"
                  },
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Domains; the first is the main one."
                  },
                  "name": {
                    "type": "string",
                    "description": "Name; default the first domain."
                  },
                  "mode": {
                    "type": "string",
                    "description": "Measuring mode; cookie needs a plan with cookie mode.",
                    "enum": [
                      "privacy",
                      "cookie"
                    ]
                  }
                },
                "required": [
                  "org_id",
                  "domains"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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/Site"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/live": {
      "get": {
        "operationId": "getLiveCounts",
        "tags": [
          "Sites"
        ],
        "summary": "Who is online now, per site",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "sites": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "integer"
                      },
                      "description": "Visitors online per site code."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/live/overview": {
      "get": {
        "operationId": "getLiveOverview",
        "tags": [
          "Sites"
        ],
        "summary": "All your sites live",
        "description": "Per site who is online, the pages they are on and the pageviews per minute of the last 30 minutes: your favourites first, then the busiest. Pro, Agency and Scale.\n\nAccess: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "sites, each with who is online, their pages, per_minute and favorite."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/periods": {
      "get": {
        "operationId": "getSitePeriods",
        "tags": [
          "Sites"
        ],
        "summary": "Visitors and a chart per site",
        "description": "Per site its visitors in a period and in the period it is compared with, and the chart, up to 24 sites per request. Counted as the site's own stats and timeseries count them for the same period, in the site's time zone: today is compared with yesterday up to the same time of day, a longer period with the one just before it, of the same length.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "name": "period",
            "in": "query",
            "description": "today, 7d, 30d, 90d or 12mo (the last 12 whole months, as period=12mo on the stats).",
            "schema": {
              "type": "string",
              "enum": [
                "today",
                "7d",
                "30d",
                "90d",
                "12mo"
              ],
              "default": "7d"
            }
          },
          {
            "name": "days",
            "in": "query",
            "description": "The older way to ask: 7, 30, 90 or 365 (365 is 12mo). Ignored when period is given.",
            "schema": {
              "type": "integer",
              "enum": [
                7,
                30,
                90,
                365
              ]
            }
          },
          {
            "name": "ids",
            "in": "query",
            "description": "Site codes, comma-separated (up to 24).",
            "required": true,
            "schema": {
              "type": "string",
              "examples": [
                "NV-9Y5FVJQ,NV-ABC1234"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "period": {
                      "type": "string",
                      "description": "The period.",
                      "enum": [
                        "today",
                        "7d",
                        "30d",
                        "90d",
                        "12mo"
                      ]
                    },
                    "days": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "The same period in days (7, 30, 90 or 365); null for today."
                    },
                    "interval": {
                      "type": "string",
                      "description": "The chart: per hour today, per day, per week over 12 months.",
                      "enum": [
                        "hour",
                        "day",
                        "week"
                      ]
                    },
                    "buckets": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "The first site's buckets; each site has its own."
                    },
                    "sites": {
                      "type": "object",
                      "description": "Per site code.",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "visitors": {
                            "type": "integer",
                            "description": "Visitors in the period."
                          },
                          "previous": {
                            "type": "integer",
                            "description": "Visitors in the period it is compared with."
                          },
                          "period": {
                            "type": "integer",
                            "description": "The older name for visitors."
                          },
                          "range": {
                            "type": "object",
                            "description": "The period.",
                            "properties": {
                              "from": {
                                "type": "string",
                                "format": "date-time",
                                "description": "Start."
                              },
                              "to": {
                                "type": "string",
                                "format": "date-time",
                                "description": "End."
                              }
                            }
                          },
                          "previous_range": {
                            "type": "object",
                            "description": "The period it is compared with.",
                            "properties": {
                              "from": {
                                "type": "string",
                                "format": "date-time",
                                "description": "Start."
                              },
                              "to": {
                                "type": "string",
                                "format": "date-time",
                                "description": "End."
                              }
                            }
                          },
                          "buckets": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Each point of the chart in the site's local time: yyyy-mm-ddThh:mm per hour, yyyy-mm-dd for the day or the Monday of the week."
                          },
                          "series": {
                            "type": "array",
                            "items": {
                              "type": "integer"
                            },
                            "description": "Visitors per bucket."
                          },
                          "goals": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "description": "Goals reached in the period; null without goals.",
                            "properties": {
                              "conversions": {
                                "type": "integer",
                                "description": "Visitors who reached a goal, added up over the goals."
                              },
                              "goals": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "name": {
                                      "type": "string",
                                      "description": "Goal."
                                    },
                                    "converted": {
                                      "type": "integer",
                                      "description": "Visitors who reached it."
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}": {
      "get": {
        "operationId": "getSite",
        "tags": [
          "Sites"
        ],
        "summary": "One site and its settings",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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/Site"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "patch": {
        "operationId": "updateSite",
        "tags": [
          "Sites"
        ],
        "summary": "Change a site's settings",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name."
                  },
                  "domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Domains; the first is the main one."
                  },
                  "mode": {
                    "type": "string",
                    "description": "Measuring mode; cookie needs a plan with cookie mode.",
                    "enum": [
                      "privacy",
                      "cookie"
                    ]
                  },
                  "track_links": {
                    "type": "boolean",
                    "description": "Measure outbound clicks and downloads."
                  },
                  "hash_routes": {
                    "type": "boolean",
                    "description": "Count routes after # as pages."
                  },
                  "excluded_ips": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Addresses and ranges not to count (up to 100)."
                  },
                  "excluded_paths": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 200
                    },
                    "description": "Pages and app screens where nothing counts, up to 50 rules, matched against the path without the query string and ignoring case: `/thank-you-test` (that page), `/admin/` (that page and everything under it), `/blog/*/edit` (* within one segment, ** at any depth) or `~^/order/\\d+$` (a regular expression after ~; no backreferences, lookarounds or \\b). A full address is kept as its path. Counts from the moment it is saved. Visits stored before it that viewed such a page leave every report as a whole and come back once no rule matches them; nothing is deleted. The answer then also has `hidden_visits` (hidden now), `hidden_now` and `shown_now` (by this change). 422 `site.path_rule_*` says which rule is wrong and why."
                  },
                  "timezone": {
                    "type": "string",
                    "description": "IANA time zone."
                  },
                  "currency": {
                    "type": "string",
                    "description": "The currency reports show revenue in, and that an amount sent without one is in. Changing it shows every amount, also from before, in the new one.",
                    "enum": [
                      "EUR",
                      "AUD",
                      "BRL",
                      "CAD",
                      "CHF",
                      "CNY",
                      "CZK",
                      "DKK",
                      "GBP",
                      "HKD",
                      "HUF",
                      "IDR",
                      "ILS",
                      "INR",
                      "ISK",
                      "JPY",
                      "KRW",
                      "MXN",
                      "MYR",
                      "NOK",
                      "NZD",
                      "PHP",
                      "PLN",
                      "RON",
                      "SEK",
                      "SGD",
                      "THB",
                      "TRY",
                      "USD",
                      "ZAR"
                    ]
                  },
                  "paused": {
                    "type": "boolean",
                    "description": "true counts nothing until false; measuring again needs room in the plan."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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/Site"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "deleteSite",
        "tags": [
          "Sites"
        ],
        "summary": "Delete the site",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/favorite": {
      "put": {
        "operationId": "addFavorite",
        "tags": [
          "Sites"
        ],
        "summary": "Star a site",
        "description": "A favourite comes first in your lists: Your websites, the site switcher, the live overview, the mobile app and GET /sites. Yours alone, on any site you can read; starring it twice changes nothing.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The site code."
                    },
                    "favorite": {
                      "type": "boolean",
                      "description": "Always true."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "removeFavorite",
        "tags": [
          "Sites"
        ],
        "summary": "Unstar a site",
        "description": "Back in its usual place in your lists.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The site code."
                    },
                    "favorite": {
                      "type": "boolean",
                      "description": "Always false."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/data": {
      "get": {
        "operationId": "getDataRetention",
        "tags": [
          "Sites"
        ],
        "summary": "What is kept, and what can be exported",
        "description": "Access: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "raw_retention_days": {
                      "type": "integer",
                      "description": "How long visits are kept."
                    },
                    "daily_retention_days": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "How long daily totals are kept; null without end."
                    },
                    "oldest_visit": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "The oldest visit."
                    },
                    "oldest_daily": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The oldest daily total.",
                      "format": "date"
                    },
                    "months": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Months that can be exported (YYYY-MM)."
                    },
                    "export": {
                      "type": "boolean",
                      "description": "Export is possible."
                    },
                    "hidden_visits": {
                      "type": "integer",
                      "description": "Older visits the page rules (excluded_paths) keep out of every report, without deleting them."
                    },
                    "notice": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "What a downgrade will remove, and when."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "deleteSiteData",
        "tags": [
          "Sites"
        ],
        "summary": "Delete all data of the site",
        "description": "Every visit, event, daily total, import, label and bot of the site. The site and its settings stay.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/export": {
      "get": {
        "operationId": "exportMonth",
        "tags": [
          "Sites"
        ],
        "summary": "One month as CSV",
        "description": "kind=visits: every pageview and event; kind=daily: the daily totals. On plans with export.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "kind",
            "in": "query",
            "description": "What to export.",
            "schema": {
              "type": "string",
              "enum": [
                "visits",
                "daily"
              ],
              "default": "visits"
            }
          },
          {
            "name": "month",
            "in": "query",
            "description": "The month.",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$",
              "examples": [
                "2026-10"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/imports": {
      "get": {
        "operationId": "listImports",
        "tags": [
          "Sites"
        ],
        "summary": "Imports of the site's history",
        "description": "Daily totals from Google Analytics 4, Plausible, Umami, Fathom, Matomo or a CSV of your own, and the days an import may still fill: before Nvivio measured the site itself, up to 10 years back.\n\nAccess: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "imports": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Import"
                      }
                    },
                    "measured_from": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The first day Nvivio measured the site.",
                      "format": "date"
                    },
                    "open": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "The days an import may fill.",
                      "properties": {
                        "from": {
                          "type": "string",
                          "description": "First day.",
                          "format": "date"
                        },
                        "to": {
                          "type": "string",
                          "description": "Last day.",
                          "format": "date"
                        }
                      }
                    },
                    "sources": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "boolean"
                      },
                      "description": "Per source, whether the plan includes importing from it."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "startImport",
        "tags": [
          "Sites"
        ],
        "summary": "Start an import",
        "description": "The period is cut to the days an import may fill. One import of a site runs at a time. On plans with import.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "source": {
                    "type": "string",
                    "description": "Where it comes from.",
                    "enum": [
                      "ga4",
                      "plausible",
                      "umami",
                      "fathom",
                      "matomo",
                      "csv"
                    ]
                  },
                  "label": {
                    "type": "string",
                    "description": "The property or file, as you will recognise it (up to 120 characters)."
                  },
                  "from": {
                    "type": "string",
                    "description": "First day.",
                    "format": "date"
                  },
                  "to": {
                    "type": "string",
                    "description": "Last day.",
                    "format": "date"
                  }
                },
                "required": [
                  "source",
                  "from",
                  "to"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The import.",
                      "format": "uuid"
                    },
                    "source": {
                      "type": "string",
                      "description": "Source."
                    },
                    "label": {
                      "type": "string",
                      "description": "Label."
                    },
                    "from": {
                      "type": "string",
                      "description": "First day it may fill.",
                      "format": "date"
                    },
                    "to": {
                      "type": "string",
                      "description": "Last day it may fill.",
                      "format": "date"
                    },
                    "measured_from": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The first day Nvivio measured the site.",
                      "format": "date"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/imports/{id}/days": {
      "put": {
        "operationId": "putImportDays",
        "tags": [
          "Sites"
        ],
        "summary": "Send days of an import",
        "description": "Whole days, each with one total and its other rows (up to 1,000 values per dimension and day; 92 days per request). A day this import already has is replaced; days outside its period or of another import are skipped.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The import, from GET /sites/{site}/imports.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "days": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "day": {
                          "type": "string",
                          "description": "The day, in your old tool's time zone.",
                          "format": "date"
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "dimension": {
                                "type": "string",
                                "description": "total, entry, exit, referrer, channel, country, region, device, browser, os, lang, hostname, utm_source, utm_medium, utm_campaign, page or event."
                              },
                              "value": {
                                "type": "string",
                                "description": "The value; empty for total."
                              },
                              "visitors": {
                                "type": "integer",
                                "description": "Unique visitors that day."
                              },
                              "visits": {
                                "type": "integer",
                                "description": "Visits."
                              },
                              "pageviews": {
                                "type": "integer",
                                "description": "Pageviews (events for event)."
                              },
                              "bounces": {
                                "type": "integer",
                                "description": "Visits with one pageview."
                              },
                              "duration_s": {
                                "type": "integer",
                                "description": "Seconds of all visits together."
                              }
                            },
                            "required": [
                              "dimension"
                            ]
                          }
                        }
                      },
                      "required": [
                        "day",
                        "rows"
                      ]
                    }
                  }
                },
                "required": [
                  "days"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "stored": {
                      "type": "integer",
                      "description": "Days stored."
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Days left out."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/imports/{id}/done": {
      "post": {
        "operationId": "finishImport",
        "tags": [
          "Sites"
        ],
        "summary": "Finish an import",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The import, from GET /sites/{site}/imports.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "notes": {
                    "type": "object",
                    "description": "What you want to keep with it."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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/Import"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/imports/{id}": {
      "delete": {
        "operationId": "deleteImport",
        "tags": [
          "Sites"
        ],
        "summary": "Undo an import",
        "description": "Removes the import and all its days. On every plan.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The import, from GET /sites/{site}/imports.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/install": {
      "get": {
        "operationId": "getInstall",
        "tags": [
          "Sites"
        ],
        "summary": "How to install the script",
        "description": "Access: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "snippet": {
                      "type": "string",
                      "description": "The script line."
                    },
                    "early_calls": {
                      "type": "string",
                      "description": "An optional line for calls before the script loads."
                    },
                    "ai_prompt": {
                      "type": "string",
                      "description": "A prompt for an AI coding assistant that installs it."
                    },
                    "received": {
                      "type": "boolean",
                      "description": "An event came in during the last 7 days."
                    },
                    "last_event": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "The last event: at, url and whether its address matches the site."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/parts": {
      "get": {
        "operationId": "getParts",
        "tags": [
          "Sites"
        ],
        "summary": "The parts of a site, with their numbers",
        "description": "A website and an app in one site: each part with its hostnames and its key figures in the period.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "parts, each with key, name, hosts and its numbers."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "put": {
        "operationId": "setParts",
        "tags": [
          "Sites"
        ],
        "summary": "Set the parts of a site",
        "description": "Up to 12 parts. Exactly one has no hosts: the rest of the site.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "parts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "description": "Name (up to 40 characters)."
                        },
                        "hosts": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Hostnames, exact or *.domain."
                        }
                      },
                      "required": [
                        "name"
                      ]
                    }
                  }
                },
                "required": [
                  "parts"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "parts": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/stats": {
      "get": {
        "operationId": "getStats",
        "tags": [
          "Numbers"
        ],
        "summary": "The six key figures",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "compare",
            "in": "query",
            "description": "previous: the period before (today: yesterday until the same time; yesterday: the day before; otherwise the stretch just before, as long); year: the same period a year earlier. compared_with names it.",
            "schema": {
              "type": "string",
              "enum": [
                "previous",
                "year"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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/Stats"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/timeseries": {
      "get": {
        "operationId": "getTimeseries",
        "tags": [
          "Numbers"
        ],
        "summary": "The key figures over time",
        "description": "Every bucket of the period, empty ones as 0, in the site's time zone. Days older than the plan keeps visits come from daily totals.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "interval",
            "in": "query",
            "description": "Bucket size. Default: hour up to 2 days, day up to 120 days, else week.",
            "schema": {
              "type": "string",
              "enum": [
                "hour",
                "day",
                "week",
                "month"
              ]
            }
          },
          {
            "name": "compare",
            "in": "query",
            "description": "Adds previous: the period stats compares with (previous: the period before (today: yesterday until the same time; yesterday: the day before; otherwise the stretch just before, as long); year: the same period a year earlier), bucket for bucket, for a dashed line.",
            "schema": {
              "type": "string",
              "enum": [
                "previous",
                "year"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "interval": {
                      "type": "string",
                      "description": "Bucket size."
                    },
                    "period": {
                      "$ref": "#/components/schemas/Period"
                    },
                    "currency": {
                      "type": "string",
                      "description": "The site's currency (ISO 4217), which every amount is converted to.",
                      "enum": [
                        "EUR",
                        "AUD",
                        "BRL",
                        "CAD",
                        "CHF",
                        "CNY",
                        "CZK",
                        "DKK",
                        "GBP",
                        "HKD",
                        "HUF",
                        "IDR",
                        "ILS",
                        "INR",
                        "ISK",
                        "JPY",
                        "KRW",
                        "MXN",
                        "MYR",
                        "NOK",
                        "NZD",
                        "PHP",
                        "PLN",
                        "RON",
                        "SEK",
                        "SGD",
                        "THB",
                        "TRY",
                        "USD",
                        "ZAR"
                      ]
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TimeseriesRow"
                      }
                    },
                    "partial": {
                      "type": "boolean",
                      "description": "A filter could only count the days that still have visits."
                    },
                    "imported": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportedSpan"
                      },
                      "description": "Imported days in the series."
                    },
                    "previous": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "With compare: the period compared with and its rows, in the same interval; null through a shared link when that window has too few visitors.",
                      "properties": {
                        "period": {
                          "$ref": "#/components/schemas/Period"
                        },
                        "compared_with": {
                          "type": "string",
                          "description": "What it is: previous_period, yesterday_so_far, year_before…"
                        },
                        "rows": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/TimeseriesRow"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/breakdown": {
      "get": {
        "operationId": "getBreakdown",
        "tags": [
          "Numbers"
        ],
        "summary": "The top values of one dimension",
        "description": "Path and event count pageviews or events; currency adds up revenue per currency as sent; every other dimension counts visitors. Shares are of all visitors in the period. Every row has its revenue in the site's currency.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "dimension",
            "in": "query",
            "description": "What to break down by.",
            "schema": {
              "type": "string",
              "enum": [
                "channel",
                "referrer",
                "utm_source",
                "utm_medium",
                "utm_campaign",
                "entry",
                "path",
                "exit",
                "event",
                "country",
                "region",
                "city",
                "lang",
                "currency",
                "device",
                "browser",
                "os",
                "hostname",
                "app_version",
                "os_version",
                "device_model"
              ],
              "default": "entry"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Rows.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 10
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Only values that contain this text.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "goal",
            "in": "query",
            "description": "A goal's name: adds conversions per value, and keeps the revenue of that goal's events.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "revenue: the values with the most revenue first. Default: the most visitors, pageviews or events.",
            "schema": {
              "type": "string",
              "enum": [
                "revenue"
              ]
            }
          },
          {
            "name": "compare",
            "in": "query",
            "description": "Add each value's number in the period before (as getStats compares), or a year earlier.",
            "schema": {
              "type": "string",
              "enum": [
                "previous",
                "year"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "dimension": {
                      "type": "string",
                      "description": "The dimension."
                    },
                    "period": {
                      "$ref": "#/components/schemas/Period"
                    },
                    "previous_period": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Period"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "currency": {
                      "type": "string",
                      "description": "The site's currency (ISO 4217), which every amount is converted to.",
                      "enum": [
                        "EUR",
                        "AUD",
                        "BRL",
                        "CAD",
                        "CHF",
                        "CNY",
                        "CZK",
                        "DKK",
                        "GBP",
                        "HKD",
                        "HUF",
                        "IDR",
                        "ILS",
                        "INR",
                        "ISK",
                        "JPY",
                        "KRW",
                        "MXN",
                        "MYR",
                        "NOK",
                        "NZD",
                        "PHP",
                        "PLN",
                        "RON",
                        "SEK",
                        "SGD",
                        "THB",
                        "TRY",
                        "USD",
                        "ZAR"
                      ]
                    },
                    "total": {
                      "type": "number",
                      "description": "All visitors (or pageviews, or events, or revenue) in the period."
                    },
                    "metric": {
                      "type": "string",
                      "description": "What the rows count.",
                      "enum": [
                        "visitors",
                        "count",
                        "revenue"
                      ]
                    },
                    "goal": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The goal."
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BreakdownRow"
                      }
                    },
                    "daily": {
                      "type": "boolean",
                      "description": "Older days came from daily totals."
                    },
                    "partial": {
                      "type": "boolean",
                      "description": "Only days that still have visits carry their currency (dimension currency)."
                    },
                    "imported": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ImportedSpan"
                      },
                      "description": "Imported days counted in the rows (without filters or a goal)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/story": {
      "get": {
        "operationId": "getStory",
        "tags": [
          "Numbers"
        ],
        "summary": "The story of the period",
        "description": "The headline and findings about the period, in your language. Compared as getStats compares, so the headline and the key figures tell the same change: today with yesterday until the same time, yesterday with the day before, longer periods with the one before; the headline names it.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "compare",
            "in": "query",
            "description": "previous: the period before (today: yesterday until the same time; yesterday: the day before; otherwise the stretch just before, as long) (default); year: the same period a year earlier.",
            "schema": {
              "type": "string",
              "enum": [
                "previous",
                "year"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "period, previous_period, compared_with (as in Stats), the headline and the findings, each with its facts."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/explain": {
      "get": {
        "operationId": "explainChange",
        "tags": [
          "Numbers"
        ],
        "summary": "Why the numbers changed",
        "description": "What changed against the comparison period, and which sources, pages, countries, devices and campaigns explain it, in your language.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "compare",
            "in": "query",
            "description": "previous: the period before (today: yesterday until the same time; yesterday: the day before; otherwise the stretch just before, as long) (default), as getStats; week: the same period a week earlier (up to 7 days).",
            "schema": {
              "type": "string",
              "enum": [
                "previous",
                "week"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "period, previous_period, compare, compared_with (as in Stats), and the sentences that explain the change with the values behind them."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/insights": {
      "get": {
        "operationId": "getInsights",
        "tags": [
          "Numbers"
        ],
        "summary": "What Nvivio noticed",
        "description": "For period today, yesterday or 7d without filters: the day's insights, made once a day about the last seven whole days against the site's own usual weeks; source is \"ai\" when a language model chose and worded them, \"statistics\" when statistics alone found them. For another period or with filters: the rule-based insights against the period before, as getStats compares (source \"rules\").\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "source": {
                      "type": "string",
                      "description": "ai, statistics or rules."
                    },
                    "window": {
                      "type": "object",
                      "description": "The day's insights: the seven days they are about (from, to)."
                    },
                    "generated_at": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "When the day's insights were made."
                    },
                    "insights": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The same finding on another day has the same id; the key for feedback."
                          },
                          "kind": {
                            "type": "string",
                            "description": "Kind."
                          },
                          "tone": {
                            "type": "string",
                            "description": "Good, bad or neutral."
                          },
                          "title": {
                            "type": "string",
                            "description": "Title."
                          },
                          "text": {
                            "type": "string",
                            "description": "Text."
                          },
                          "why": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "description": "Why it matters, when the model wrote one."
                          },
                          "facts": {
                            "type": "array",
                            "description": "The numbers in the text."
                          },
                          "link": {
                            "type": "object",
                            "description": "The filter, report or tab that shows it, with from and to for the day's insights."
                          },
                          "action": {
                            "type": "object",
                            "description": "Something to do, sometimes."
                          },
                          "evidence": {
                            "type": "array",
                            "description": "The day's insights: per finding its standard sentence and its visits per week."
                          },
                          "vote": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "description": "Your own vote: 1 useful, -1 not."
                          }
                        }
                      }
                    },
                    "action": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "The first thing to do."
                    },
                    "summary": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "One sentence about the period (rules)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/insights/feedback": {
      "put": {
        "operationId": "rateInsight",
        "tags": [
          "Numbers"
        ],
        "summary": "Say whether an insight was useful",
        "description": "Yours alone. A finding marked not useful more often than useful is quieter for 30 days. A reason is one of three words; nothing you type goes to a language model.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "key": {
                    "type": "string",
                    "description": "The insight's id from GET /sites/{site}/insights."
                  },
                  "vote": {
                    "type": "integer",
                    "description": "1 useful, -1 not useful, 0 no vote."
                  },
                  "reason": {
                    "type": "string",
                    "description": "With -1: known, wrong or unimportant."
                  },
                  "source": {
                    "type": "string",
                    "description": "ai or statistics, as the insight says."
                  }
                },
                "required": [
                  "key",
                  "vote",
                  "source"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string",
                      "description": "The insight."
                    },
                    "vote": {
                      "type": "integer",
                      "description": "Your vote."
                    },
                    "reason": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The reason."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/hours": {
      "get": {
        "operationId": "getHours",
        "tags": [
          "Numbers"
        ],
        "summary": "Visits per weekday and hour",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "period": {
                      "$ref": "#/components/schemas/Period"
                    },
                    "timezone": {
                      "type": "string",
                      "description": "The site's time zone."
                    },
                    "rows": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "dow": {
                            "type": "integer",
                            "description": "Weekday, 1 is Monday."
                          },
                          "hour": {
                            "type": "integer",
                            "description": "Hour, 0 to 23."
                          },
                          "visits": {
                            "type": "integer",
                            "description": "Visits."
                          }
                        }
                      },
                      "description": "Only cells with visits."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/ai": {
      "get": {
        "operationId": "getAi",
        "tags": [
          "Numbers"
        ],
        "summary": "AI assistants and AI crawlers",
        "description": "The people AI assistants sent, and the AI crawlers that read pages (to train, to search, or for a person right now), per company, with the period before. Days for crawlers are UTC days.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "period, humans, referrals, crawlers, ratio, by_company, pages, interval, series, previous_series and complete (crawlers that only fetch HTML are seen when your server forwards them)."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/bots": {
      "get": {
        "operationId": "getBots",
        "tags": [
          "Numbers"
        ],
        "summary": "Bots by group",
        "description": "Bot requests by group, kind, bot, network and country, the pages they read, and the period before. Days are UTC days.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "period, interval, hits, groups, previous, previous_groups, share, previous_share, series, previous_series, by_kind, by_bot, by_org, by_country and pages."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/sessions": {
      "get": {
        "operationId": "listSessions",
        "tags": [
          "Visits"
        ],
        "summary": "Visits, newest first",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Visits per page.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "next_cursor of the page before.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "sessions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The next page, or null."
                    },
                    "period": {
                      "$ref": "#/components/schemas/Period"
                    },
                    "mode": {
                      "type": "string",
                      "description": "The site's mode."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/sessions/{id}": {
      "get": {
        "operationId": "getSession",
        "tags": [
          "Visits"
        ],
        "summary": "One visit with every step",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The visit, from GET /sites/{site}/sessions.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The visit and its steps: every pageview and event, with an amount as sent (revenue: amount and currency)."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/realtime": {
      "get": {
        "operationId": "getRealtime",
        "tags": [
          "Visits"
        ],
        "summary": "Who is online now",
        "description": "With filters only the visits they keep. With part:<key> the chart and the numbers of the last 30 minutes count only that part's own page views and actions, so f=part:app shows who is in your app now.\n\nAccess: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "now": {
                      "type": "integer",
                      "description": "Online now."
                    },
                    "visitors": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Up to 100."
                    },
                    "per_minute": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "The last 30 minutes."
                    },
                    "last_30_min": {
                      "type": "object"
                    },
                    "server_time": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Now."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/realtime/minute": {
      "get": {
        "operationId": "getRealtimeMinute",
        "tags": [
          "Visits"
        ],
        "summary": "What happened in one minute",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "name": "at",
            "in": "query",
            "description": "A moment in the minute, ISO 8601.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Start."
                    },
                    "to": {
                      "type": "string",
                      "format": "date-time",
                      "description": "End."
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Up to 50."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/visitors/{id}/label": {
      "put": {
        "operationId": "setVisitorLabel",
        "tags": [
          "Visits"
        ],
        "summary": "Set a visitor's label and note",
        "description": "Access: An API key with the admin scope, or an editor, admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "visitor.id of a visit.",
            "schema": {
              "type": "string",
              "pattern": "^[\\w:.-]{1,100}$"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "description": "Label (up to 60 characters); empty removes it."
                  },
                  "note": {
                    "type": "string",
                    "description": "Note."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "label": {
                      "type": "string",
                      "description": "Label."
                    },
                    "note": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Note."
                    }
                  }
                }
              }
            }
          },
          "204": {
            "description": "The label was empty, so it was removed.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/visitors/{id}/export": {
      "get": {
        "operationId": "exportVisitor",
        "tags": [
          "Visits"
        ],
        "summary": "Everything about one visitor",
        "description": "Visits, events and label of one visitor on this site.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "visitor.id of a visit; in cookie mode c: and the code from the objection box.",
            "schema": {
              "type": "string",
              "pattern": "^[\\w:.-]{1,100}$"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "exported_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When."
                    },
                    "site": {
                      "type": "string",
                      "description": "The site."
                    },
                    "visitor": {
                      "type": "string",
                      "description": "The visitor."
                    },
                    "label": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "sessions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/visitors/{id}": {
      "delete": {
        "operationId": "deleteVisitor",
        "tags": [
          "Visits"
        ],
        "summary": "Delete one visitor for good",
        "description": "All of one visitor's visits, events and label.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "visitor.id of a visit, or c: and the code from the objection box.",
            "schema": {
              "type": "string",
              "pattern": "^[\\w:.-]{1,100}$"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "visitor": {
                      "type": "string",
                      "description": "The visitor."
                    },
                    "deleted": {
                      "type": "object",
                      "properties": {
                        "sessions": {
                          "type": "integer",
                          "description": "Visits."
                        },
                        "events": {
                          "type": "integer",
                          "description": "Events."
                        },
                        "label": {
                          "type": "integer",
                          "description": "Labels."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/goals": {
      "get": {
        "operationId": "listGoals",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "Goals with their results",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "period, currency and goals, each with its definition, conversions, conversion rate, its events' revenue, orders and average order value, and value_total_cents for a fixed value per conversion."
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "createGoal",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "Add a goal",
        "description": "Access: An API key with the admin scope, or an editor, admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "description": "A pageview of a path, or a custom event.",
                    "enum": [
                      "pageview",
                      "event"
                    ]
                  },
                  "match": {
                    "type": "string",
                    "description": "The path or the event name."
                  },
                  "name": {
                    "type": "string",
                    "description": "Name (up to 60 characters); default from match."
                  },
                  "value_cents": {
                    "type": "integer",
                    "description": "A fixed value of one conversion, in hundredths of the site's currency (cents), for goals without amounts.",
                    "minimum": 0
                  }
                },
                "required": [
                  "kind",
                  "match"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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/Goal"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/goals/{id}": {
      "delete": {
        "operationId": "deleteGoal",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "Delete a goal",
        "description": "Access: An API key with the admin scope, or an editor, admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The goal.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/funnels": {
      "get": {
        "operationId": "listFunnels",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "Funnels",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "funnels": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Funnel"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "createFunnel",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "Add a funnel",
        "description": "Access: An API key with the admin scope, or an editor, admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name (up to 60 characters)."
                  },
                  "steps": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Step"
                    },
                    "minItems": 2,
                    "maxItems": 8
                  }
                },
                "required": [
                  "name",
                  "steps"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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/Funnel"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/funnels/{id}": {
      "get": {
        "operationId": "getFunnel",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "One funnel with its steps",
        "description": "Access: Any API key of the organisation, or a person with any role.\n\nThe live demo (acme.example) answers this without a key.\n\nA shared link reads this too, for its own site: narrowed to what the link shows.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          },
          {
            "share": []
          },
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The funnel.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/period"
          },
          {
            "$ref": "#/components/parameters/from"
          },
          {
            "$ref": "#/components/parameters/to"
          },
          {
            "$ref": "#/components/parameters/f"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Id."
                    },
                    "name": {
                      "type": "string",
                      "description": "Name."
                    },
                    "period": {
                      "$ref": "#/components/schemas/Period"
                    },
                    "steps": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      },
                      "description": "Each step with its visitors, and an event step's revenue and orders."
                    },
                    "conversion_rate": {
                      "type": "number",
                      "description": "From the first to the last step, in percent."
                    },
                    "currency": {
                      "type": "string",
                      "description": "The site's currency (ISO 4217), which every amount is converted to.",
                      "enum": [
                        "EUR",
                        "AUD",
                        "BRL",
                        "CAD",
                        "CHF",
                        "CNY",
                        "CZK",
                        "DKK",
                        "GBP",
                        "HKD",
                        "HUF",
                        "IDR",
                        "ILS",
                        "INR",
                        "ISK",
                        "JPY",
                        "KRW",
                        "MXN",
                        "MYR",
                        "NOK",
                        "NZD",
                        "PHP",
                        "PLN",
                        "RON",
                        "SEK",
                        "SGD",
                        "THB",
                        "TRY",
                        "USD",
                        "ZAR"
                      ]
                    },
                    "revenue": {
                      "type": "number",
                      "description": "The last step's amounts: what the visits that completed the funnel brought in."
                    },
                    "orders": {
                      "type": "integer",
                      "description": "How many."
                    },
                    "aov": {
                      "type": "number",
                      "description": "Revenue per order."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "deleteFunnel",
        "tags": [
          "Goals and funnels"
        ],
        "summary": "Delete a funnel",
        "description": "Access: An API key with the admin scope, or an editor, admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The funnel.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/bot-key": {
      "get": {
        "operationId": "getBotKey",
        "tags": [
          "Bots from your server"
        ],
        "summary": "The connection's status",
        "description": "Access: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "bot_key": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "description": "The connection for bots from your server.",
                      "properties": {
                        "hint": {
                          "type": "string",
                          "description": "Last characters of the key."
                        },
                        "created_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Made."
                        },
                        "seen_at": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "Last request."
                        }
                      }
                    },
                    "bot_endpoint": {
                      "type": "string",
                      "description": "Where your server sends bots."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "createBotKey",
        "tags": [
          "Bots from your server"
        ],
        "summary": "Make a new key",
        "description": "The key is shown once; a new key replaces the old one.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Site"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string",
                          "description": "The key (nvb_…), shown once."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "deleteBotKey",
        "tags": [
          "Bots from your server"
        ],
        "summary": "Remove the connection",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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/Site"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/team": {
      "get": {
        "operationId": "getTeam",
        "tags": [
          "Team and keys"
        ],
        "summary": "Members, invitations and site access",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "role": {
                      "type": "string",
                      "description": "Your role."
                    },
                    "you": {
                      "type": "string",
                      "description": "Your user id."
                    },
                    "members": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "sites": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "invitations": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "site_access": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/members/{user}": {
      "patch": {
        "operationId": "updateMember",
        "tags": [
          "Team and keys"
        ],
        "summary": "Change a member's role",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "name": "user",
            "in": "path",
            "required": true,
            "description": "The member.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "editor",
                      "reader"
                    ]
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string",
                      "description": "The member."
                    },
                    "role": {
                      "type": "string",
                      "description": "The new role."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "removeMember",
        "tags": [
          "Team and keys"
        ],
        "summary": "Remove a member, or leave",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "name": "user",
            "in": "path",
            "required": true,
            "description": "The member, or you.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/invitations": {
      "post": {
        "operationId": "invite",
        "tags": [
          "Team and keys"
        ],
        "summary": "Invite someone",
        "description": "To the organisation, or with sites to those sites only.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Email address.",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "owner",
                      "admin",
                      "editor",
                      "reader"
                    ],
                    "description": "For sites: admin, editor or reader."
                  },
                  "sites": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Site codes or domains: access to these only."
                  }
                },
                "required": [
                  "email",
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "properties": {
                    "invitations": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "emailed": {
                      "type": "boolean",
                      "description": "The invitation was emailed."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/invitations/{id}": {
      "delete": {
        "operationId": "withdrawInvitation",
        "tags": [
          "Team and keys"
        ],
        "summary": "Withdraw an invitation",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The invitation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/access": {
      "get": {
        "operationId": "getSiteAccess",
        "tags": [
          "Team and keys"
        ],
        "summary": "Access to one site",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "Who has access to this site, and the open invitations for it."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "inviteToSite",
        "tags": [
          "Team and keys"
        ],
        "summary": "Invite someone to one site",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "description": "Email address.",
                    "format": "email"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "editor",
                      "reader"
                    ]
                  }
                },
                "required": [
                  "email",
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "description": "The invitation, and emailed."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/access/{user}": {
      "patch": {
        "operationId": "updateSiteAccess",
        "tags": [
          "Team and keys"
        ],
        "summary": "Change someone's access to one site",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "user",
            "in": "path",
            "required": true,
            "description": "The person.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "editor",
                      "reader"
                    ]
                  }
                },
                "required": [
                  "role"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The access as it is now."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "removeSiteAccess",
        "tags": [
          "Team and keys"
        ],
        "summary": "Remove someone's access to one site",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "user",
            "in": "path",
            "required": true,
            "description": "The person.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/invitations/{id}": {
      "delete": {
        "operationId": "withdrawSiteInvitation",
        "tags": [
          "Team and keys"
        ],
        "summary": "Withdraw an invitation for one site",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The invitation.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/keys": {
      "get": {
        "operationId": "listKeys",
        "tags": [
          "Team and keys"
        ],
        "summary": "API keys",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKey"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "createKey",
        "tags": [
          "Team and keys"
        ],
        "summary": "Make an API key",
        "description": "You see the full key once; only its hash is stored. Starter and up; on Free only keys for the MCP server ({\"mcp\": true}) and for the WordPress plugin ({\"wordpress\": true, \"site\": \"NV-…\"}), which read and nothing else.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name (up to 60 characters)."
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "read",
                        "admin"
                      ]
                    },
                    "description": "Default [\"read\"]. A read key cannot change anything."
                  },
                  "mcp": {
                    "type": "boolean",
                    "description": "A key for the MCP server: read only, on every plan; GET /me, /sites and per site what the MCP server's tools ask (stats, timeseries, breakdown, story, explain, insights, ai, bots, sessions, goals, funnels, realtime, hours) only."
                  },
                  "wordpress": {
                    "type": "boolean",
                    "description": "A key for the WordPress plugin: read only, one site, on every plan; GET /me, /sites/live, /orgs/{org}/usage and the site's /stats, /timeseries and /breakdown only."
                  },
                  "site": {
                    "type": "string",
                    "description": "With wordpress: the site code or domain."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ApiKey"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string",
                          "description": "The key (nv_…), shown once."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/connect/wordpress/code": {
      "post": {
        "operationId": "createWordPressCode",
        "tags": [
          "Team and keys"
        ],
        "summary": "A code to connect WordPress",
        "description": "For \"Connect with Nvivio\" in the WordPress plugin: a one-time code for one site, valid ten minutes, added to the WordPress page to go back to. That page must be on one of the site's domains (or on this computer: localhost, *.localhost, *.test).\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "site": {
                    "type": "string",
                    "description": "The site code or domain."
                  },
                  "return": {
                    "type": "string",
                    "description": "The WordPress page to go back to."
                  }
                },
                "required": [
                  "site",
                  "return"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "description": "The page to go back to, with nvivio_code added."
                    },
                    "expires_in": {
                      "type": "integer",
                      "description": "Seconds the code works."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/connect/wordpress": {
      "post": {
        "operationId": "connectWordPress",
        "tags": [
          "Team and keys"
        ],
        "summary": "Trade the code for a key for WordPress",
        "description": "Asked by the WordPress plugin's server, once per code: a read key for one site that reads only what the plugin shows, on every plan.\n\nAccess: No login: the one-time code in the body is the proof.",
        "security": [
          {}
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "description": "The code from nvivio_code."
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "type": "string",
                      "description": "The key (nv_…), shown once."
                    },
                    "site": {
                      "type": "string",
                      "description": "The site code."
                    },
                    "domain": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The site's main domain."
                    },
                    "name": {
                      "type": "string",
                      "description": "The site's name."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/400"
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/keys/{id}": {
      "delete": {
        "operationId": "revokeKey",
        "tags": [
          "Team and keys"
        ],
        "summary": "Revoke an API key",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The key.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Team and keys"
        ],
        "summary": "The plan, its limits and this month's use",
        "description": "Access: Any API key of the organisation, or a person with any role.",
        "security": [
          {
            "apiKey": []
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The plan, its limits, month (units, limit, grace_days, stops_at, paused_until, bots) and up to 12 months before (history); badge (on, style, seen_at, since, page, domain, counts, discount, discount_now, discount_from, discount_at_checkout, days: the days with visitors this period and on how many the badge was seen) and referral (referred_by, links: domain, site code and badge link per site, signups, paying, months_earned, free_months, months_at_start)."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/referral": {
      "put": {
        "operationId": "setReferral",
        "tags": [
          "Team and keys"
        ],
        "summary": "Came through a site's badge",
        "description": "Until the first payment. That payment then covers a referral month more, and the referrer gets one once it stood (terms 5.8).\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "via": {
                    "type": "string",
                    "description": "The domain of the site whose badge brought you (example.com); a subdomain counts for the site above it."
                  }
                },
                "required": [
                  "via"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The referral summary, as in GET /orgs/{org}/usage."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "removeReferral",
        "tags": [
          "Team and keys"
        ],
        "summary": "Remove the referral",
        "description": "Until the first payment.\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The referral summary."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/billing": {
      "get": {
        "operationId": "getBilling",
        "tags": [
          "Team and keys"
        ],
        "summary": "Who pays, the plan and the invoices",
        "description": "Access: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "Who pays, the plan paid for (plan, billing_interval, price_eur, vat, period_end, cancel_at, failed_since, credit_eur), the invoices (number is null while it is being made; pdf when there is one) and the founders' places left."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/billing/vat": {
      "post": {
        "operationId": "checkVat",
        "tags": [
          "Team and keys"
        ],
        "summary": "Check a VAT number",
        "description": "What VIES says, and the VAT that follows.\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "country": {
                    "type": "string",
                    "description": "Country, two letters.",
                    "pattern": "^[A-Za-z]{2}$"
                  },
                  "vat_number": {
                    "type": "string",
                    "description": "VAT number."
                  }
                },
                "required": [
                  "country"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "valid, the name and address VIES knows, and vat."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          },
          "503": {
            "$ref": "#/components/responses/503"
          }
        }
      }
    },
    "/orgs/{org}/checkout": {
      "post": {
        "operationId": "checkout",
        "tags": [
          "Team and keys"
        ],
        "summary": "Pay for a plan",
        "description": "Answers a checkout_url at Mollie. Accepting the terms is never implied; a consumer in the EU chooses to start at once.\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan": {
                    "type": "string",
                    "description": "The plan.",
                    "enum": [
                      "free",
                      "starter",
                      "pro",
                      "agency"
                    ]
                  },
                  "interval": {
                    "type": "string",
                    "description": "Billed per month or per year.",
                    "enum": [
                      "month",
                      "year"
                    ]
                  },
                  "account": {
                    "type": "object",
                    "description": "Who pays.",
                    "properties": {
                      "company": {
                        "type": "string",
                        "description": "Company name (a business)."
                      },
                      "consumer": {
                        "type": "boolean",
                        "description": "A consumer, not a business; then name is required."
                      },
                      "name": {
                        "type": "string",
                        "description": "Full name (a consumer)."
                      },
                      "country": {
                        "type": "string",
                        "description": "Country, two letters.",
                        "pattern": "^[A-Z]{2}$"
                      },
                      "vat_number": {
                        "type": "string",
                        "description": "VAT number (a business in the EU)."
                      },
                      "street": {
                        "type": "string",
                        "description": "Street and number."
                      },
                      "postal_code": {
                        "type": "string",
                        "description": "Postal code."
                      },
                      "city": {
                        "type": "string",
                        "description": "City."
                      },
                      "email": {
                        "type": "string",
                        "description": "Where invoices go.",
                        "format": "email"
                      }
                    },
                    "required": [
                      "country",
                      "street",
                      "postal_code",
                      "city",
                      "email"
                    ]
                  },
                  "accept_terms": {
                    "const": true,
                    "description": "You accept the terms."
                  },
                  "start_now": {
                    "type": "boolean",
                    "description": "A consumer in the EU: start now and give up the right of withdrawal for the time used."
                  }
                },
                "required": [
                  "plan",
                  "interval",
                  "account",
                  "accept_terms"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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": {
                  "type": "object",
                  "properties": {
                    "checkout_url": {
                      "type": "string",
                      "description": "Pay here.",
                      "format": "uri"
                    },
                    "amount": {
                      "type": "object"
                    },
                    "vat": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/billing/change": {
      "post": {
        "operationId": "changePlan",
        "tags": [
          "Team and keys"
        ],
        "summary": "Change the plan",
        "description": "At once, pro rata.\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan": {
                    "type": "string",
                    "description": "The plan.",
                    "enum": [
                      "free",
                      "starter",
                      "pro",
                      "agency"
                    ]
                  },
                  "interval": {
                    "type": "string",
                    "description": "Billed per month or per year.",
                    "enum": [
                      "month",
                      "year"
                    ]
                  }
                },
                "required": [
                  "plan",
                  "interval"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The plan as it is now, and what was charged or credited."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/billing/cancel": {
      "post": {
        "operationId": "cancelPlan",
        "tags": [
          "Team and keys"
        ],
        "summary": "Cancel the plan",
        "description": "The plan runs to the end of its period.\n\nAccess: A signed-in person only, not an API key. Owners only.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "description": "The plan, and when it ends."
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/invoices/{id}": {
      "get": {
        "operationId": "getInvoice",
        "tags": [
          "Team and keys"
        ],
        "summary": "An invoice",
        "description": "The PDF, or a page to print for an invoice Nvivio numbered itself; 409 invoice.pending while it is still being made.\n\nAccess: An API key with the admin scope, or an admin or owner.",
        "security": [
          {
            "apiKey": [
              "admin"
            ]
          },
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The invoice, from GET /orgs/{org}/billing.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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/pdf": {
                "schema": {
                  "type": "string",
                  "contentMediaType": "application/pdf"
                }
              },
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/shares": {
      "get": {
        "operationId": "listShares",
        "tags": [
          "Sharing"
        ],
        "summary": "The shared links of a site",
        "description": "Each link with its address, what it shows, when it was last opened and whether it works. Admins and owners.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "sharing": {
                      "type": "string",
                      "enum": [
                        "public",
                        "link",
                        "branded"
                      ],
                      "description": "What the plan allows: one open link, links with options, or that with your logo."
                    },
                    "allows": {
                      "type": "object",
                      "properties": {
                        "options": {
                          "type": "boolean",
                          "description": "Password, expiry, part, filters and embedding."
                        },
                        "brand": {
                          "type": "boolean",
                          "description": "Your logo."
                        },
                        "max": {
                          "type": "integer",
                          "description": "Links per site."
                        }
                      }
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ShareLink"
                      }
                    },
                    "brand": {
                      "type": [
                        "object",
                        "null"
                      ]
                    },
                    "org_id": {
                      "type": "string",
                      "description": "The organisation."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "post": {
        "operationId": "createShare",
        "tags": [
          "Sharing"
        ],
        "summary": "Share the dashboard",
        "description": "A link anyone who has it can open: the numbers of this site, read only; never single visits, labels, settings, plan or usage. Free: one link without options. Admins and owners.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name (up to 80 characters)."
                  },
                  "password": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A password of at least 8 characters; null for none."
                  },
                  "expires_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Stops working then; null for never."
                  },
                  "part": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Only this part of the site (its key); null for the whole site."
                  },
                  "filters": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Only the visits these filters keep, such as path:~/blog/*; never visitor or label."
                  },
                  "embed_hosts": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Hosts that may show it in an iframe, such as www.client.be or *.client.be."
                  },
                  "layout": {
                    "type": "boolean",
                    "description": "Show the Overview as you have it now (true, the default) or the default one."
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Made.",
            "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/ShareLink"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "409": {
            "$ref": "#/components/responses/409"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/sites/{site}/shares/{id}": {
      "patch": {
        "operationId": "updateShare",
        "tags": [
          "Sharing"
        ],
        "summary": "Change a shared link",
        "description": "The same fields; null takes a password, expiry or part away. A new password closes what the old one opened.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The link.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name (up to 80 characters)."
                  },
                  "password": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A password of at least 8 characters; null for none."
                  },
                  "expires_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Stops working then; null for never."
                  },
                  "part": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Only this part of the site (its key); null for the whole site."
                  },
                  "filters": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Only the visits these filters keep, such as path:~/blog/*; never visitor or label."
                  },
                  "embed_hosts": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Hosts that may show it in an iframe, such as www.client.be or *.client.be."
                  },
                  "layout": {
                    "type": "boolean",
                    "description": "Show the Overview as you have it now (true, the default) or the default one."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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/ShareLink"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "revokeShare",
        "tags": [
          "Sharing"
        ],
        "summary": "Revoke a shared link",
        "description": "It stops working at once, for good.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/site"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The link.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/orgs/{org}/brand": {
      "get": {
        "operationId": "getBrand",
        "tags": [
          "Sharing"
        ],
        "summary": "Your logo on shared links",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "brand": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "Name."
                        },
                        "logo": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The logo, as a data: URL."
                        },
                        "updated_at": {
                          "type": "string",
                          "format": "date-time",
                          "description": "Changed."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "put": {
        "operationId": "setBrand",
        "tags": [
          "Sharing"
        ],
        "summary": "Set your logo on shared links",
        "description": "Agency and up. A PNG, JPEG, WebP or SVG of at most 100 kB, as a data: URL; an SVG without scripts or anything it loads from elsewhere.\n\nAccess: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Shown next to the logo (up to 80 characters)."
                  },
                  "logo": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "data:image/…;base64,…, or null to remove it."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "brand": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      },
      "delete": {
        "operationId": "removeBrand",
        "tags": [
          "Sharing"
        ],
        "summary": "Remove your logo from shared links",
        "description": "Access: A signed-in person only, not an API key.",
        "security": [
          {
            "session": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/org"
          },
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "204": {
            "description": "Done.",
            "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"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "404": {
            "$ref": "#/components/responses/404"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/share": {
      "get": {
        "operationId": "getShare",
        "tags": [
          "Sharing"
        ],
        "summary": "A shared link, as its reader opens it",
        "description": "Whether it asks a password, the logo, and once open its site: read it with the operations marked for shared links, with the same header.\n\nAccess: The link of a shared dashboard: Authorization: Share <token>.",
        "security": [
          {
            "share": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "password": {
                      "type": "boolean",
                      "description": "Asks a password."
                    },
                    "open": {
                      "type": "boolean",
                      "description": "Open: no password, or it was given."
                    },
                    "site": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The site, once open."
                    },
                    "brand": {
                      "type": [
                        "object",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    },
    "/share/unlock": {
      "post": {
        "operationId": "unlockShare",
        "tags": [
          "Sharing"
        ],
        "summary": "Give the password of a shared link",
        "description": "Answers a value that opens the link for 12 hours: send it as Authorization: Share <token>.<unlock>. A fair number of tries per minute and per hour.\n\nAccess: The link of a shared dashboard: Authorization: Share <token>.",
        "security": [
          {
            "share": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "password": {
                    "type": "string",
                    "description": "The password."
                  }
                },
                "required": [
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "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": {
                  "type": "object",
                  "properties": {
                    "unlock": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Opens the link."
                    },
                    "hours": {
                      "type": "integer",
                      "description": "For how long."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/401"
          },
          "403": {
            "$ref": "#/components/responses/403"
          },
          "422": {
            "$ref": "#/components/responses/422"
          },
          "429": {
            "$ref": "#/components/responses/429"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "nv_…",
        "description": "An API key of your organisation. Make one at https://nvivio.com/app/api or with POST /orgs/{org}/keys. A key with the scope read reads; the scope admin also changes settings, goals and keys."
      },
      "session": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "A signed-in person: the session token the Nvivio dashboard sends."
      },
      "share": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "A shared dashboard: \"Share <token>\", the token from its address (/share/<token>), and \".<unlock>\" after it once its password was given (POST /share/unlock)."
      }
    },
    "parameters": {
      "site": {
        "name": "site",
        "in": "path",
        "required": true,
        "description": "The site code (NV-9Y5FVJQ) or one of the site's domains (example.com). Without access you get 404, not 403. The live demo is acme.example, readable without a key.",
        "schema": {
          "type": "string",
          "examples": [
            "acme.example",
            "NV-9Y5FVJQ"
          ]
        }
      },
      "org": {
        "name": "org",
        "in": "path",
        "required": true,
        "description": "Your organisation id, from GET /me.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "period": {
        "name": "period",
        "in": "query",
        "description": "today, yesterday, 24h, 7d (the default), 30d, month (this calendar month so far), lastmonth, year, 12mo or all; or a number of minutes, hours or days such as 90d or 6h. Named periods follow the site's time zone. Ignored when from is given.",
        "schema": {
          "type": "string",
          "pattern": "^(today|yesterday|month|lastmonth|year|12mo|all|[0-9]{1,3}[mhd])$",
          "default": "7d",
          "examples": [
            "30d",
            "lastmonth"
          ]
        }
      },
      "from": {
        "name": "from",
        "in": "query",
        "description": "Start of a period of your own, ISO 8601, in place of period.",
        "schema": {
          "type": "string",
          "examples": [
            "2026-10-01",
            "2026-10-01T09:00:00Z"
          ]
        }
      },
      "to": {
        "name": "to",
        "in": "query",
        "description": "End of a period of your own (exclusive), ISO 8601. Default: now.",
        "schema": {
          "type": "string",
          "examples": [
            "2026-11-01"
          ]
        }
      },
      "f": {
        "name": "f",
        "in": "query",
        "description": "Filters, the same as in the dashboard's address: repeat f for each one, all must hold. \"key:value\"; \"~\" makes the value a pattern with *, \"!\" negates. goal:<name>, label:<name>, visitor:<id or code>, min_actions:<number> and part:<name> work besides the dimensions. Examples: country:BE, referrer:google.com, path:~/blog/*, device:!mobile, channel:ai.",
        "style": "form",
        "explode": true,
        "schema": {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^(country|region|city|referrer|channel|path|entry|exit|hostname|device|browser|os|lang|app_version|os_version|device_model|event|utm_source|utm_medium|utm_campaign|label|visitor|goal|min_actions|part):!?~?.{1,300}$"
          },
          "examples": [
            [
              "country:BE",
              "path:~/blog/*"
            ]
          ]
        }
      },
      "lang": {
        "name": "lang",
        "in": "query",
        "description": "The language of the texts the API writes itself (the story, explanations, insights, errors), in place of Accept-Language. Without either: English.",
        "schema": {
          "type": "string",
          "enum": [
            "en",
            "bg",
            "cs",
            "da",
            "de",
            "el",
            "es",
            "et",
            "fi",
            "fr",
            "ga",
            "hr",
            "hu",
            "it",
            "lt",
            "lv",
            "mt",
            "nl",
            "pl",
            "pt",
            "ro",
            "sk",
            "sl",
            "sv"
          ]
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Every error: what is wrong, how to fix it, and a stable code.",
        "properties": {
          "error": {
            "type": "string",
            "description": "What is wrong, in the caller's language."
          },
          "fix": {
            "type": "string",
            "description": "How to solve it."
          },
          "code": {
            "type": "string",
            "description": "A stable code to compare on, such as \"auth.not_logged_in\" or \"api.limit\"."
          }
        },
        "required": [
          "error",
          "fix",
          "code"
        ]
      },
      "Period": {
        "type": "object",
        "description": "The period answered, as UTC instants.",
        "properties": {
          "from": {
            "type": "string",
            "format": "date-time",
            "description": "Start, inclusive."
          },
          "to": {
            "type": "string",
            "format": "date-time",
            "description": "End, exclusive."
          }
        },
        "required": [
          "from",
          "to"
        ]
      },
      "KeyFigures": {
        "type": "object",
        "description": "The six key figures.",
        "properties": {
          "visitors": {
            "type": "integer",
            "description": "Unique visitors."
          },
          "sessions": {
            "type": "integer",
            "description": "Visits."
          },
          "pageviews": {
            "type": "integer",
            "description": "Pageviews."
          },
          "views_per_visit": {
            "type": "number",
            "description": "Pageviews per visit."
          },
          "bounce_rate": {
            "type": "number",
            "description": "Visits with one pageview and nothing else, in percent."
          },
          "avg_duration_s": {
            "type": "integer",
            "description": "Average visit duration in seconds."
          }
        }
      },
      "Stats": {
        "type": "object",
        "description": "The key figures of a period.",
        "properties": {
          "period": {
            "$ref": "#/components/schemas/Period"
          },
          "visitors": {
            "type": "integer",
            "description": "Unique visitors."
          },
          "sessions": {
            "type": "integer",
            "description": "Visits."
          },
          "pageviews": {
            "type": "integer",
            "description": "Pageviews."
          },
          "views_per_visit": {
            "type": "number",
            "description": "Pageviews per visit."
          },
          "bounce_rate": {
            "type": "number",
            "description": "Visits with one pageview and nothing else, in percent."
          },
          "avg_duration_s": {
            "type": "integer",
            "description": "Average visit duration in seconds."
          },
          "revenue": {
            "type": "number",
            "description": "What the amounts of custom events add up to, in the site's currency."
          },
          "orders": {
            "type": "integer",
            "description": "How many events carried an amount."
          },
          "aov": {
            "type": "number",
            "description": "Average order value: revenue per order."
          },
          "revenue_per_visitor": {
            "type": "number",
            "description": "Revenue per unique visitor."
          },
          "currency": {
            "type": "string",
            "description": "The site's currency (ISO 4217), which every amount is converted to.",
            "enum": [
              "EUR",
              "AUD",
              "BRL",
              "CAD",
              "CHF",
              "CNY",
              "CZK",
              "DKK",
              "GBP",
              "HKD",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "ISK",
              "JPY",
              "KRW",
              "MXN",
              "MYR",
              "NOK",
              "NZD",
              "PHP",
              "PLN",
              "RON",
              "SEK",
              "SGD",
              "THB",
              "TRY",
              "USD",
              "ZAR"
            ]
          },
          "partial": {
            "type": "boolean",
            "description": "A filter could only count the days that still have visits (older days and imported days are daily totals, which filters cannot split)."
          },
          "imported": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportedSpan"
            },
            "description": "Imported days counted in these figures; empty when none (or with a filter)."
          },
          "previous": {
            "type": [
              "object",
              "null"
            ],
            "description": "The same figures for the comparison period (with compare), else null.",
            "properties": {
              "visitors": {
                "type": "integer",
                "description": "Unique visitors."
              },
              "sessions": {
                "type": "integer",
                "description": "Visits."
              },
              "pageviews": {
                "type": "integer",
                "description": "Pageviews."
              },
              "views_per_visit": {
                "type": "number",
                "description": "Pageviews per visit."
              },
              "bounce_rate": {
                "type": "number",
                "description": "Visits with one pageview and nothing else, in percent."
              },
              "avg_duration_s": {
                "type": "integer",
                "description": "Average visit duration in seconds."
              },
              "revenue": {
                "type": "number",
                "description": "What the amounts of custom events add up to, in the site's currency."
              },
              "orders": {
                "type": "integer",
                "description": "How many events carried an amount."
              },
              "aov": {
                "type": "number",
                "description": "Average order value: revenue per order."
              },
              "revenue_per_visitor": {
                "type": "number",
                "description": "Revenue per unique visitor."
              },
              "partial": {
                "type": "boolean",
                "description": "As above."
              },
              "imported": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ImportedSpan"
                },
                "description": "As above."
              }
            }
          },
          "previous_period": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Period"
              },
              {
                "type": "null"
              }
            ]
          },
          "compare": {
            "type": [
              "string",
              "null"
            ],
            "description": "The comparison asked for.",
            "enum": [
              "previous",
              "year",
              null
            ]
          },
          "compared_with": {
            "type": [
              "string",
              "null"
            ],
            "description": "What previous_period is: yesterday_so_far (today until now against yesterday until the same time), day_before_yesterday (yesterday against the day before it), previous_24h, previous_period (the stretch just before, as long), week_before (explain with compare=week) or year_before.",
            "enum": [
              "yesterday_so_far",
              "day_before_yesterday",
              "previous_24h",
              "previous_period",
              "week_before",
              "year_before",
              null
            ]
          },
          "bots_filtered": {
            "type": "integer",
            "description": "Bot requests left out of the numbers."
          }
        }
      },
      "Site": {
        "type": "object",
        "description": "A site and its settings, with the plan of its organisation and that plan's limits.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The site code.",
            "examples": [
              "NV-9Y5FVJQ"
            ]
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "role": {
            "type": "string",
            "description": "What you may do here.",
            "enum": [
              "reader",
              "editor",
              "admin",
              "owner"
            ]
          },
          "domains": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The domains measured; the first is the main one."
          },
          "mode": {
            "type": "string",
            "description": "privacy: no cookies, no consent needed; cookie: recognises returning visitors, with consent.",
            "enum": [
              "privacy",
              "cookie"
            ]
          },
          "timezone": {
            "type": "string",
            "description": "IANA time zone; named periods follow it.",
            "examples": [
              "Europe/Brussels"
            ]
          },
          "currency": {
            "type": "string",
            "description": "The site's currency (ISO 4217), which every amount is converted to.",
            "enum": [
              "EUR",
              "AUD",
              "BRL",
              "CAD",
              "CHF",
              "CNY",
              "CZK",
              "DKK",
              "GBP",
              "HKD",
              "HUF",
              "IDR",
              "ILS",
              "INR",
              "ISK",
              "JPY",
              "KRW",
              "MXN",
              "MYR",
              "NOK",
              "NZD",
              "PHP",
              "PLN",
              "RON",
              "SEK",
              "SGD",
              "THB",
              "TRY",
              "USD",
              "ZAR"
            ]
          },
          "retention_days": {
            "type": "integer",
            "description": "How long visits are kept."
          },
          "daily_retention_days": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How long daily totals are kept; null without end."
          },
          "excluded_ips": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Addresses and ranges that are not counted."
          },
          "excluded_paths": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Pages and app screens where nothing counts: a path, a path with a trailing slash (and everything under it), wildcards * and **, or a regular expression after ~."
          },
          "paused": {
            "type": [
              "object",
              "null"
            ],
            "description": "Paused: nothing is counted.",
            "properties": {
              "since": {
                "type": "string",
                "format": "date-time",
                "description": "Since when."
              },
              "by": {
                "type": "string",
                "description": "By the plan or by choice.",
                "enum": [
                  "plan",
                  "user"
                ]
              }
            }
          },
          "snippet": {
            "type": "string",
            "description": "The script line to paste into the site."
          },
          "track_links": {
            "type": "boolean",
            "description": "Outbound clicks and downloads are measured."
          },
          "hash_routes": {
            "type": "boolean",
            "description": "Routes after # count as pages."
          },
          "bot_endpoint": {
            "type": "string",
            "description": "Where your server forwards bots."
          },
          "bot_key": {
            "type": [
              "object",
              "null"
            ],
            "description": "The connection for bots from your server.",
            "properties": {
              "hint": {
                "type": "string",
                "description": "Last characters of the key."
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "Made."
              },
              "seen_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time",
                "description": "Last request."
              }
            }
          },
          "demo": {
            "type": "boolean",
            "description": "Read as the public demo: its settings stay private."
          }
        }
      },
      "TimeseriesRow": {
        "type": "object",
        "properties": {
          "bucket": {
            "type": "string",
            "description": "Start of the hour, day, week or month, in the site's time zone."
          },
          "visitors": {
            "type": "integer",
            "description": "Unique visitors."
          },
          "sessions": {
            "type": "integer",
            "description": "Visits."
          },
          "pageviews": {
            "type": "integer",
            "description": "Pageviews."
          },
          "views_per_visit": {
            "type": "number",
            "description": "Pageviews per visit."
          },
          "bounce_rate": {
            "type": "number",
            "description": "Visits with one pageview and nothing else, in percent."
          },
          "avg_duration_s": {
            "type": "integer",
            "description": "Average visit duration in seconds."
          },
          "revenue": {
            "type": "number",
            "description": "What the amounts of custom events add up to, in the site's currency."
          },
          "orders": {
            "type": "integer",
            "description": "How many events carried an amount."
          },
          "imported": {
            "type": "boolean",
            "description": "Present and true when the bucket has imported days."
          }
        }
      },
      "ImportedSpan": {
        "type": "object",
        "description": "Imported days within the answer: daily totals from another tool, before Nvivio measured the site.",
        "properties": {
          "source": {
            "type": "string",
            "description": "Where it came from.",
            "enum": [
              "ga4",
              "plausible",
              "umami",
              "fathom",
              "matomo",
              "csv"
            ]
          },
          "label": {
            "type": "string",
            "description": "The property or file it was imported from."
          },
          "from": {
            "type": "string",
            "description": "First imported day in the period.",
            "format": "date"
          },
          "to": {
            "type": "string",
            "description": "Last imported day in the period.",
            "format": "date"
          }
        }
      },
      "Import": {
        "type": "object",
        "description": "One import of a site's history.",
        "properties": {
          "id": {
            "type": "string",
            "description": "The import.",
            "format": "uuid"
          },
          "source": {
            "type": "string",
            "description": "Where it came from.",
            "enum": [
              "ga4",
              "plausible",
              "umami",
              "fathom",
              "matomo",
              "csv"
            ]
          },
          "label": {
            "type": "string",
            "description": "The property or file it was imported from."
          },
          "status": {
            "type": "string",
            "description": "running: days are coming in; interrupted: none for an hour; done.",
            "enum": [
              "running",
              "interrupted",
              "done"
            ]
          },
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its first day.",
            "format": "date"
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "description": "Its last day.",
            "format": "date"
          },
          "allowed": {
            "type": "object",
            "properties": {
              "from": {
                "type": "string",
                "description": "First day it may fill.",
                "format": "date"
              },
              "to": {
                "type": "string",
                "description": "Last day it may fill.",
                "format": "date"
              }
            }
          },
          "days": {
            "type": "integer",
            "description": "Days it has."
          },
          "dimensions": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The dimensions it has besides the totals."
          },
          "notes": {
            "type": "object",
            "description": "What the importer noted, such as Google leaving rows out."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Started."
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Finished."
          }
        }
      },
      "BreakdownRow": {
        "type": "object",
        "description": "One value of a dimension.",
        "properties": {
          "value": {
            "type": [
              "string",
              "null"
            ],
            "description": "The value (a country code, a path, a referrer…); null when unknown."
          },
          "label": {
            "type": "string",
            "description": "The name of a channel or device in the asked language (?lang= or Accept-Language), such as \"Search ads\" for paid_search or \"Smartphone\" for mobile (dimensions channel and device)."
          },
          "visitors": {
            "type": "integer",
            "description": "Visitors."
          },
          "count": {
            "type": "integer",
            "description": "Pageviews or events (path and event)."
          },
          "sessions": {
            "type": "integer",
            "description": "Visits."
          },
          "pageviews": {
            "type": "integer",
            "description": "Pageviews."
          },
          "bounce_rate": {
            "type": "number",
            "description": "Bounce rate in percent."
          },
          "avg_duration_s": {
            "type": "integer",
            "description": "Average visit duration in seconds."
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "The page title (path)."
          },
          "avg_time_s": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Average time on the page in seconds (path)."
          },
          "avg_scroll": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Average scroll depth in percent (path)."
          },
          "converted": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Visitors who reached the goal (with goal)."
          },
          "cr": {
            "type": "number",
            "description": "Conversion rate in percent (with goal)."
          },
          "prev_visitors": {
            "type": "integer",
            "description": "Visitors in the comparison period (with compare)."
          },
          "prev_count": {
            "type": "integer",
            "description": "Count in the comparison period (with compare, path and event)."
          },
          "revenue": {
            "type": "number",
            "description": "Revenue in the site's currency: of the visits with this value; of the visits that viewed it (path); its own amounts (event); with goal, of that goal's events."
          },
          "orders": {
            "type": "integer",
            "description": "Amounts in that revenue."
          },
          "aov": {
            "type": "number",
            "description": "Revenue per order."
          },
          "amount": {
            "type": "number",
            "description": "The amounts as sent, in this currency (dimension currency)."
          }
        }
      },
      "Step": {
        "type": "object",
        "description": "A goal or a funnel step.",
        "properties": {
          "kind": {
            "type": "string",
            "description": "A pageview of a path, or a custom event.",
            "enum": [
              "pageview",
              "event"
            ]
          },
          "match": {
            "type": "string",
            "description": "The path (\"/thank-you\", \"/blog/*\" with * as a wildcard) or the event name (\"signup\")."
          },
          "label": {
            "type": "string",
            "description": "A name for a funnel step (up to 60 characters)."
          }
        },
        "required": [
          "kind",
          "match"
        ]
      },
      "Goal": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id.",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "kind": {
            "type": "string",
            "description": "A pageview of a path, or a custom event.",
            "enum": [
              "pageview",
              "event"
            ]
          },
          "match": {
            "type": "string",
            "description": "Path or event name."
          },
          "value_cents": {
            "type": [
              "integer",
              "null"
            ],
            "description": "A fixed value of one conversion, in hundredths of the site's currency (cents)."
          }
        }
      },
      "Funnel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id.",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Step"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Made."
          }
        }
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id.",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "prefix": {
            "type": "string",
            "description": "The first characters, to recognise it."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "admin"
              ]
            }
          },
          "mcp": {
            "type": "boolean",
            "description": "A key of the MCP server (made by connecting an AI assistant)."
          },
          "wordpress": {
            "type": "boolean",
            "description": "A key for the WordPress plugin: one site, only what the plugin shows, on every plan."
          },
          "site": {
            "type": [
              "string",
              "null"
            ],
            "description": "The site of a key for WordPress."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Made."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Last used."
          }
        }
      },
      "ShareLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id.",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "description": "Name."
          },
          "url": {
            "type": "string",
            "description": "The link to give: whoever has it reads the dashboard, read only.",
            "format": "uri"
          },
          "password": {
            "type": "boolean",
            "description": "Asks a password."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Stops working then."
          },
          "part": {
            "type": [
              "string",
              "null"
            ],
            "description": "Shows only this part of the site."
          },
          "filters": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Shows only the visits these filters keep, as in the dashboard."
          },
          "embed_hosts": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Hosts that may show it in an iframe, over https."
          },
          "layout": {
            "type": "boolean",
            "description": "Shows the Overview as its maker had it."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Made."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Last changed."
          },
          "last_opened_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Last opened."
          },
          "opens": {
            "type": "integer",
            "description": "Times opened."
          },
          "state": {
            "type": "string",
            "enum": [
              "active",
              "expired",
              "plan"
            ],
            "description": "Works, has expired, or is more than the plan allows now."
          }
        }
      },
      "Report": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Id.",
            "format": "uuid"
          },
          "question": {
            "type": "string",
            "description": "The question."
          },
          "answer": {
            "type": "string",
            "description": "The answer, in Markdown; every number links to the tool result it comes from."
          },
          "tools": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "The API calls the answer is based on, each with its dashboard page."
          },
          "lang": {
            "type": "string",
            "description": "Language."
          },
          "model": {
            "type": "string",
            "description": "The model that wrote it."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Asked."
          },
          "shared": {
            "type": "boolean",
            "description": "Shared as a page."
          },
          "share_url": {
            "type": [
              "string",
              "null"
            ],
            "description": "The shared page."
          },
          "monthly": {
            "type": "boolean",
            "description": "Asked again every month, by email."
          }
        }
      }
    },
    "headers": {
      "X-RateLimit-Limit": {
        "description": "Requests per hour (with an API key).",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Remaining": {
        "description": "What is left this hour.",
        "schema": {
          "type": "integer"
        }
      },
      "X-RateLimit-Reset": {
        "description": "Seconds until the next hour.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "400": {
        "description": "The request is not valid: an unknown period, filter value, dimension or parameter.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "401": {
        "description": "No API key or session, or one that is not valid (auth.not_logged_in, auth.invalid_key).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "403": {
        "description": "Not allowed: a read-only key, a role that may not do this, a plan without the API or this function, or an API key where only a signed-in person may.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "404": {
        "description": "Not found, or no access: a site or organisation you cannot see is \"not found\", so you do not learn that it exists.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "409": {
        "description": "Conflicts with what is there: a name or domain that is taken, a limit of the plan, or not possible right now.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "422": {
        "description": "The body is not valid; fix says what to send, with an example.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "429": {
        "description": "Too many requests: the hourly limit of your plan (api.limit, with Retry-After in seconds), too many demo requests at once (demo.too_many), or a limit of this function.",
        "headers": {
          "Retry-After": {
            "description": "Seconds after which trying again can work.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "503": {
        "description": "A service this depends on does not answer; try again later.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}