{
  "openapi": "3.1.0",
  "info": {
    "title": "WorldPlane control plane API",
    "version": "1",
    "description": "The API the WorldPlane panel, CLI and CI use. Reference: https://worldplane.net/docs/api",
    "contact": {
      "name": "Artisan Gameworks Inc.",
      "email": "info@artisangameworks.com"
    }
  },
  "servers": [
    {
      "url": "https://app.worldplane.net"
    }
  ],
  "security": [
    {
      "bearer": []
    },
    {
      "cookie": []
    }
  ],
  "tags": [
    {
      "name": "Accounts"
    },
    {
      "name": "Organisations"
    },
    {
      "name": "Billing"
    },
    {
      "name": "Projects"
    },
    {
      "name": "Environments"
    },
    {
      "name": "Secrets"
    },
    {
      "name": "Atlas"
    },
    {
      "name": "Builds"
    },
    {
      "name": "Players"
    },
    {
      "name": "Downloads"
    }
  ],
  "paths": {
    "/v1/health": {
      "get": {
        "summary": "Health check",
        "tags": [
          "Accounts"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "The text ok.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts": {
      "post": {
        "summary": "Sign up",
        "tags": [
          "Accounts"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Signed up; sets the wp_session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "400": {
            "description": "Bad e-mail, short password or no name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Sign-up is closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "An account for that e-mail already exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 10
                  }
                },
                "required": [
                  "email",
                  "name",
                  "password"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/sessions": {
      "post": {
        "summary": "Sign in",
        "tags": [
          "Accounts"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Signed in; sets the wp_session cookie.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Session"
                }
              }
            }
          },
          "401": {
            "description": "Wrong e-mail or password, a code needed, or a wrong code.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many wrong sign-ins for this e-mail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  },
                  "code": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/sessions/current": {
      "delete": {
        "summary": "Sign out",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Ended; the cookie is cleared."
          }
        }
      }
    },
    "/v1/password-resets": {
      "post": {
        "summary": "Request a password reset",
        "tags": [
          "Accounts"
        ],
        "security": [],
        "responses": {
          "202": {
            "description": "Accepted, whether or not the e-mail has an account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "501": {
            "description": "This control plane sends no e-mail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/password-resets/confirm": {
      "post": {
        "summary": "Set a new password",
        "tags": [
          "Accounts"
        ],
        "security": [],
        "responses": {
          "204": {
            "description": "Set; every session of the account ends."
          },
          "400": {
            "description": "Short password, or the link expired or was used.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "minLength": 10
                  }
                },
                "required": [
                  "token",
                  "password"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "summary": "Who am I",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "account": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Account"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "actor": {
                      "type": "string"
                    },
                    "grants": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Grant"
                      }
                    },
                    "tenants": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me/totp": {
      "post": {
        "summary": "Set up an authenticator",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "secret": {
                      "type": "string"
                    },
                    "uri": {
                      "type": "string"
                    },
                    "next": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "A person's session only; keys get 403."
      }
    },
    "/v1/me/totp/confirm": {
      "post": {
        "summary": "Confirm the authenticator",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Set up."
          },
          "400": {
            "description": "Nothing to confirm or remove, or the code doesn't match.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/me/totp/remove": {
      "post": {
        "summary": "Remove the authenticator",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Removed."
          },
          "400": {
            "description": "Nothing to confirm or remove, or the code doesn't match.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string"
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/regions": {
      "get": {
        "summary": "Regions",
        "tags": [
          "Accounts"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "regions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/tenants": {
      "post": {
        "summary": "Create an organisation",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Created; the caller is its owner.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Tenant"
                }
              }
            }
          },
          "400": {
            "description": "Bad or reserved slug.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The slug is taken.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "slug",
                  "name"
                ]
              }
            }
          }
        },
        "description": "A person's session only."
      }
    },
    "/v1/tenants/{tenant}": {
      "get": {
        "summary": "Get an organisation",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tenant": {
                      "$ref": "#/components/schemas/Tenant"
                    },
                    "projects": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "description": "Needs read or read billing."
      }
    },
    "/v1/tenants/{tenant}/members": {
      "get": {
        "summary": "List members",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "members": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "role": {
                            "$ref": "#/components/schemas/Role"
                          },
                          "project": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "invited": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "email": {
                            "type": "string"
                          },
                          "role": {
                            "$ref": "#/components/schemas/Role"
                          },
                          "project": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ]
      },
      "post": {
        "summary": "Add or invite a member",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "Added."
          },
          "202": {
            "description": "Invited: no account yet."
          },
          "400": {
            "description": "Not an e-mail address.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "role": {
                    "$ref": "#/components/schemas/Role"
                  },
                  "project": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "email",
                  "role"
                ]
              }
            }
          }
        },
        "description": "Needs administer; adding an owner needs own."
      }
    },
    "/v1/tenants/{tenant}/members/{email}": {
      "delete": {
        "summary": "Remove a member",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Removed."
          },
          "404": {
            "description": "No such member.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A tenant keeps at least one owner.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "email",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "URL-encoded."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/keys": {
      "get": {
        "summary": "List API keys",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ApiKey"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ]
      },
      "post": {
        "summary": "Make an API key",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "$ref": "#/components/schemas/ApiKey"
                    },
                    "secret": {
                      "type": "string",
                      "description": "wpk_..., shown once."
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "An owner key, or no name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such project"
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "role": {
                    "$ref": "#/components/schemas/Role"
                  },
                  "project": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "name",
                  "role"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/keys/{id}": {
      "delete": {
        "summary": "Revoke an API key",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked."
          },
          "404": {
            "description": "No such key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/audit": {
      "get": {
        "summary": "Audit log",
        "tags": [
          "Organisations"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "records": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AuditRecord"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "before",
            "in": "query",
            "schema": {
              "type": "integer"
            },
            "description": "Records with a lower seq."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 1000
            }
          }
        ],
        "description": "Newest first. Owners and admins."
      }
    },
    "/v1/tenants/{tenant}/downloads/unreal-plugin": {
      "get": {
        "summary": "Download the Unreal plugin",
        "description": "The WorldPlane and WorldPlaneGAS plugins as a zip. Any member of the tenant; needs an active subscription.",
        "tags": [
          "Downloads"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "responses": {
          "200": {
            "description": "The plugin zip",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in"
          },
          "403": {
            "description": "Not a member"
          },
          "402": {
            "description": "No active subscription"
          },
          "404": {
            "description": "No plugin on this control plane"
          }
        }
      }
    },
    "/v1/downloads/cli/{platform}": {
      "get": {
        "summary": "Download the CLI",
        "description": "The worldplane CLI for windows or linux (x86-64), for anyone signed in or an API key.",
        "tags": [
          "Downloads"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "windows",
                "linux"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The CLI binary",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in"
          },
          "404": {
            "description": "Another platform, or no CLI on this control plane"
          }
        }
      }
    },
    "/v1/tenants/{tenant}/usage": {
      "get": {
        "summary": "Usage this month",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "since": {
                      "type": "integer"
                    },
                    "environments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project": {
                            "type": "string"
                          },
                          "environment": {
                            "type": "string"
                          },
                          "server_hours": {
                            "type": "number"
                          },
                          "usd": {
                            "type": "number"
                          }
                        }
                      }
                    },
                    "usd": {
                      "type": "number"
                    },
                    "billing": {
                      "type": "string",
                      "enum": [
                        "stripe",
                        "estimate"
                      ]
                    },
                    "subscribed": {
                      "type": "boolean"
                    },
                    "subscription_status": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "checkout": {
                      "type": "boolean"
                    },
                    "plan": {
                      "type": "boolean"
                    },
                    "active": {
                      "type": "boolean"
                    },
                    "portal": {
                      "type": "boolean"
                    },
                    "max_per_month": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/billing/checkout": {
      "post": {
        "summary": "Start a subscription (Stripe Checkout)",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Url"
                }
              }
            }
          },
          "400": {
            "description": "No usable Origin header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already subscribed, or estimate mode.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Stripe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The panel's origin; Stripe returns to {Origin}/#/panel/{tenant}."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/billing/portal": {
      "post": {
        "summary": "Manage billing (Stripe portal)",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Url"
                }
              }
            }
          },
          "400": {
            "description": "No usable Origin header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Billing not set up, or estimate mode.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Stripe.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The panel's origin; Stripe returns to {Origin}/#/panel/{tenant}."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/spend-limit": {
      "put": {
        "summary": "Set the spend limit",
        "tags": [
          "Billing"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "max_per_month": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Negative or not finite.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "max_per_month": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/billing/stripe/webhook": {
      "post": {
        "summary": "Stripe webhook (not for callers)",
        "tags": [
          "Billing"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Handled or ignored."
          },
          "400": {
            "description": "Bad signature or body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Estimate mode.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Stripe-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "description": "Stripe's events for WorldPlane's own endpoint. Not for API callers."
      }
    },
    "/v1/tenants/{tenant}/projects": {
      "get": {
        "summary": "List projects",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Project"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "description": "Only the projects the caller may read."
      },
      "post": {
        "summary": "Create a project",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                }
              }
            }
          },
          "400": {
            "description": "Bad slug.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "slug",
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments": {
      "get": {
        "summary": "List environments",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Environment"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such project"
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "post": {
        "summary": "Create an environment",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Environment"
                }
              }
            }
          },
          "400": {
            "description": "Bad slug, region, budget or zone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "slug": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "region": {
                    "type": "string"
                  },
                  "max_per_hour": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "minimum": 0
                  },
                  "zone": {
                    "$ref": "#/components/schemas/ZoneSettings"
                  }
                },
                "required": [
                  "slug",
                  "name",
                  "region",
                  "zone"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}": {
      "get": {
        "summary": "Get an environment and its zone",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "environment": {
                      "$ref": "#/components/schemas/Environment"
                    },
                    "zone": {
                      "type": "object",
                      "properties": {
                        "running": {
                          "type": "boolean"
                        },
                        "gateway": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "atlas_live": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "additionalProperties": true
                    },
                    "players": {
                      "type": "object",
                      "properties": {
                        "accounts": {
                          "type": "integer"
                        },
                        "public_key": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "sign_up": {
                          "type": "string"
                        },
                        "sign_in": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "summary": "Change an environment",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Environment"
                }
              }
            }
          },
          "400": {
            "description": "Bad budget or zone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "max_per_hour": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "null removes the budget; absent leaves it."
                  },
                  "zone": {
                    "$ref": "#/components/schemas/ZoneSettings"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "description": "zone replaces the whole zone. Takes effect at the next deploy."
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}/deploy": {
      "post": {
        "summary": "Deploy",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Started.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "zone": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "No active subscription, deploys on hold for an unpaid invoice, or the spend limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such environment or build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The build isn't ready, or a secret the arguments use is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "The zone did not start.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string"
                  }
                },
                "required": [
                  "build"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}/stop": {
      "post": {
        "summary": "Stop",
        "tags": [
          "Environments"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Stopped."
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}/secrets": {
      "get": {
        "summary": "List secrets",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SecretInfo"
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}/secrets/{name}": {
      "put": {
        "summary": "Set a secret",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Replaced.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretInfo"
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretInfo"
                }
              }
            }
          },
          "400": {
            "description": "Bad name or value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Capitals, digits and _, starting with a letter; not WP_."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4096
                  }
                },
                "required": [
                  "value"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a secret",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted."
          },
          "404": {
            "description": "No such environment or secret.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}/coordinator/v0/live": {
      "get": {
        "summary": "Live feed (WebSocket)",
        "tags": [
          "Atlas"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "101": {
            "description": "Switching protocols."
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "The coordinator did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "The live map can't be reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "description": "A WebSocket upgrade relayed to the zone's coordinator. The query string is passed on."
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/environments/{env}/coordinator/v1/{path}": {
      "get": {
        "summary": "Coordinator reads",
        "tags": [
          "Atlas"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "The coordinator's answer, status and content type as it gave them."
          },
          "404": {
            "description": "No such environment, or a refused path.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "The coordinator did not answer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Can't be reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "path",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "A coordinator /v1 GET path such as zone, servers, fleet, history, replay or entities/{id}; may contain /."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/builds": {
      "get": {
        "summary": "List builds",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Build"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "post": {
        "summary": "Create a build",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Build"
                }
              }
            }
          },
          "400": {
            "description": "Unknown kind, or no image or program.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "No active subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such project.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "archive",
                      "image",
                      "local"
                    ]
                  },
                  "program": {
                    "type": "string"
                  }
                },
                "required": [
                  "label",
                  "kind"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/builds/{build}": {
      "get": {
        "summary": "Get a build",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Build"
                }
              }
            }
          },
          "404": {
            "description": "No such build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "build",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The build's id."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/builds/{build}/archive": {
      "post": {
        "summary": "Upload the archive in one request",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "Stored and checked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Build"
                }
              }
            }
          },
          "404": {
            "description": "No such build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "This build takes no upload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "build",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The build's id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/octet-stream": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/builds/{build}/image": {
      "post": {
        "summary": "Image a failed build again",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Build"
                }
              }
            }
          },
          "404": {
            "description": "No such build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Only an archive whose imaging failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "build",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The build's id."
          }
        ]
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/builds/{build}/uploads": {
      "post": {
        "summary": "Start an upload in parts",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "part_size": {
                      "type": "integer"
                    },
                    "parts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "number": {
                            "type": "integer"
                          },
                          "url": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad size.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "This control plane takes the archive itself, or the build takes no upload.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Storage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "build",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The build's id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "size": {
                    "type": "integer",
                    "minimum": 1
                  }
                },
                "required": [
                  "size"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/tenants/{tenant}/projects/{project}/builds/{build}/uploads/complete": {
      "post": {
        "summary": "Complete an upload in parts",
        "tags": [
          "Builds"
        ],
        "security": [
          {
            "bearer": []
          },
          {
            "cookie": []
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Build"
                }
              }
            }
          },
          "404": {
            "description": "No such build.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "No upload under way.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Storage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in, or an unknown token or key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Your roles here do not allow that.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The organisation's slug."
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "build",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The build's id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "parts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "number",
                        "etag"
                      ],
                      "properties": {
                        "number": {
                          "type": "integer"
                        },
                        "etag": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "required": [
                  "parts"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/play/{tenant}/{project}/{env}/accounts": {
      "post": {
        "summary": "Player sign-up",
        "tags": [
          "Players"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlayerSession"
                }
              }
            }
          },
          "400": {
            "description": "E-mail, password or name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such game environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "A player with that e-mail exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32
                  },
                  "password": {
                    "type": "string",
                    "minLength": 10
                  }
                },
                "required": [
                  "email",
                  "name",
                  "password"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/play/{tenant}/{project}/{env}/sessions": {
      "post": {
        "summary": "Player sign-in",
        "tags": [
          "Players"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlayerSession"
                }
              }
            }
          },
          "401": {
            "description": "Wrong e-mail or password.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such game environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Too many wrong sign-ins.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        }
      }
    },
    "/v1/play/{tenant}/{project}/{env}/wake": {
      "post": {
        "summary": "Wake a sleeping zone",
        "tags": [
          "Players"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Running: connect to gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "state": {
                      "const": "running"
                    },
                    "gateway": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Starting: call again in a few seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "state": {
                      "const": "starting"
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "A sleeping zone whose organisation has no active subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Not deployed (stopped or failed).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "env",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "A session token from POST /v1/sessions, or an API key (wpk_...)."
      },
      "cookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "wp_session",
        "description": "The panel's session cookie."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "A sentence for people."
          }
        }
      },
      "Account": {
        "type": "object",
        "required": [
          "id",
          "email",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Session": {
        "type": "object",
        "required": [
          "account",
          "token"
        ],
        "properties": {
          "account": {
            "$ref": "#/components/schemas/Account"
          },
          "token": {
            "type": "string",
            "description": "Send as Authorization: Bearer <token>. Also set as the wp_session cookie."
          }
        }
      },
      "Role": {
        "type": "string",
        "enum": [
          "owner",
          "admin",
          "operator",
          "developer",
          "viewer",
          "billing"
        ]
      },
      "Grant": {
        "type": "object",
        "required": [
          "tenant",
          "role"
        ],
        "properties": {
          "tenant": {
            "type": "string"
          },
          "project": {
            "type": [
              "string",
              "null"
            ]
          },
          "role": {
            "$ref": "#/components/schemas/Role"
          }
        }
      },
      "Tenant": {
        "type": "object",
        "required": [
          "slug",
          "name"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "Project": {
        "type": "object",
        "required": [
          "tenant",
          "slug",
          "name"
        ],
        "properties": {
          "tenant": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ServerSize": {
        "type": "string",
        "enum": [
          "standard",
          "plus",
          "max"
        ],
        "description": "large and xlarge are accepted as plus and max."
      },
      "ZoneSettings": {
        "type": "object",
        "required": [
          "map"
        ],
        "properties": {
          "name": {
            "type": "string",
            "default": "main"
          },
          "map": {
            "type": "string",
            "description": "An Unreal package path, such as /Game/Maps/World."
          },
          "half_size_m": {
            "type": "number",
            "default": 1000
          },
          "extra_args": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "min_servers": {
            "type": "integer",
            "minimum": 1,
            "default": 1
          },
          "max_servers": {
            "type": "integer",
            "minimum": 1,
            "default": 4
          },
          "server_capacity": {
            "type": "number",
            "default": 100
          },
          "server_size": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ServerSize"
              }
            ],
            "default": "standard"
          },
          "warm_servers": {
            "type": "integer",
            "minimum": 0,
            "default": 1
          },
          "sleep_after_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "default": null
          }
        }
      },
      "Environment": {
        "type": "object",
        "required": [
          "tenant",
          "project",
          "slug",
          "name",
          "region",
          "zone",
          "state"
        ],
        "properties": {
          "tenant": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "region": {
            "type": "string"
          },
          "max_per_hour": {
            "type": [
              "number",
              "null"
            ]
          },
          "zone": {
            "$ref": "#/components/schemas/ZoneSettings"
          },
          "build": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "stopped",
              "starting",
              "running",
              "sleeping",
              "failed"
            ]
          }
        }
      },
      "Build": {
        "type": "object",
        "required": [
          "id",
          "tenant",
          "project",
          "label",
          "kind",
          "state",
          "size",
          "uploaded_by",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant": {
            "type": "string"
          },
          "project": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "archive",
              "image",
              "local"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "uploading",
              "checking",
              "imaging",
              "starting",
              "ready",
              "rejected",
              "failed"
            ]
          },
          "reason": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": "integer"
          },
          "digest": {
            "type": [
              "string",
              "null"
            ]
          },
          "program": {
            "type": [
              "string",
              "null"
            ]
          },
          "uploaded_by": {
            "type": "string"
          },
          "created_at": {
            "type": "integer"
          }
        }
      },
      "ApiKey": {
        "type": "object",
        "required": [
          "id",
          "tenant",
          "name",
          "prefix",
          "role",
          "created_at",
          "revoked"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "project": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "integer"
          },
          "revoked": {
            "type": "boolean"
          }
        }
      },
      "AuditRecord": {
        "type": "object",
        "required": [
          "seq",
          "at",
          "tenant",
          "actor",
          "action",
          "target"
        ],
        "properties": {
          "seq": {
            "type": "integer"
          },
          "at": {
            "type": "integer"
          },
          "tenant": {
            "type": "string"
          },
          "actor": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "target": {
            "type": "string"
          },
          "detail": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SecretInfo": {
        "type": "object",
        "required": [
          "name",
          "updated"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "updated": {
            "type": "integer"
          }
        }
      },
      "Url": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string"
          }
        }
      },
      "PlayerSession": {
        "type": "object",
        "required": [
          "player",
          "token",
          "expires"
        ],
        "properties": {
          "player": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "token": {
            "type": "string"
          },
          "expires": {
            "type": "integer"
          }
        }
      }
    }
  }
}
