{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/hypamoon-com/json-schema/hypamoon-com-project-schema.json",
  "title": "Project",
  "description": "The project behind the API key.",
  "x-generated": "2026-11-12",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/hypamoon-com-openapi.json#/components/schemas/Project",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "The id of the project."
    },
    "name": {
      "type": "string",
      "description": "The name of the project. The assistant uses it in its greeting."
    },
    "edition": {
      "type": "string",
      "description": "Always api for a project of the Hypamoon API."
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "description": "When the project was created."
    },
    "spending_limit_eur": {
      "type": [
        "number",
        "null"
      ],
      "description": "The most the project can spend per month, in euros. Null in test mode: a test project costs nothing. Left out for a key or connection limited to some sites and apps."
    },
    "numbers_count": {
      "type": "integer",
      "description": "How many numbers the project has. Left out for a limited key or connection."
    },
    "mode": {
      "type": "string",
      "enum": [
        "live",
        "test"
      ],
      "description": "live or test: the mode of the key, which is always the mode of its project."
    },
    "live_project_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid",
      "description": "Only in test mode: the live project this test project belongs to, or the project itself when it has no separate test project."
    },
    "rails": {
      "type": "object",
      "properties": {
        "phone": {
          "type": "string",
          "enum": [
            "live",
            "test"
          ],
          "description": "Numbers, the call plan and the voice AI on inbound calls."
        },
        "outbound": {
          "type": "string",
          "enum": [
            "live",
            "test"
          ],
          "description": "Outbound calls (start_call)."
        },
        "sms": {
          "type": "string",
          "enum": [
            "live",
            "test"
          ],
          "description": "SMS messages."
        },
        "email": {
          "type": "string",
          "enum": [
            "live",
            "test"
          ],
          "description": "Email to other people. With a live key, email to the project's own team is real even when this is test."
        },
        "payments": {
          "type": "string",
          "enum": [
            "live",
            "test"
          ],
          "description": "Checkout, orders and refunds: real money or test payments."
        },
        "domains": {
          "type": "string",
          "enum": [
            "live",
            "test"
          ],
          "description": "Buying, renewing and transferring a domain. Connecting a domain is always real."
        }
      },
      "required": [
        "phone",
        "outbound",
        "sms",
        "email",
        "payments",
        "domains"
      ],
      "additionalProperties": false,
      "description": "Per function with real-world effects, for this request: live (in use) or test (simulated: not used yet, or a test key). A function on test becomes live the first time it is asked for, once the project is verified for it; until then the request answers verification_required with a link. A test key is test everywhere. Left out for a limited key or connection. Sites, data and apps are always real and have no mode."
    },
    "verification": {
      "type": "object",
      "properties": {
        "account_type": {
          "type": "string",
          "enum": [
            "personal",
            "business"
          ],
          "description": "personal or business. You are verified for what you use: a personal account needs no business register number, a business does. A national number needs a business."
        },
        "levels": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "level": {
                "type": "string",
                "enum": [
                  "test",
                  "company",
                  "personal",
                  "number_documents",
                  "full"
                ],
                "description": "test, then company (a business) or personal (a personal account), then number_documents and full. Each level unlocks more; see unlocks."
              },
              "status": {
                "type": "string",
                "enum": [
                  "not_started",
                  "submitted",
                  "in_review",
                  "approved",
                  "rejected"
                ],
                "description": "Where this level stands. company, personal and number_documents follow from the data you set; full needs our review."
              },
              "reason": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Only when rejected: what is wrong. Fix it and submit again."
              },
              "missing": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "What is still needed, as codes: company_details.<field> (set with PUT /project/company), payment_mandate, spending_cap, document.proof_of_address, document.identity, document.company_registration (upload in the portal under Verification), level.company or level.personal (finish that level first), level.number_documents, director_identity, ubo_confirmation and review. Empty when approved."
              },
              "unlocks": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "What this level unlocks, as codes: test_keys, test_numbers, simulated_calls, live_keys, live_chat, national_numbers, inbound_calls, geographic_numbers, sms, outbound_calls, spending_cap_above_500_eur, more_concurrent_calls."
              }
            },
            "required": [
              "level",
              "status",
              "reason",
              "missing",
              "unlocks"
            ],
            "additionalProperties": false
          },
          "description": "Always four levels, in order: test, company (personal for a personal account), number_documents, full."
        }
      },
      "required": [
        "account_type",
        "levels"
      ],
      "additionalProperties": false,
      "description": "The verification (KYC) of the project. In test mode: the verification of the live project."
    },
    "access": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "limited_by": {
          "type": "string",
          "enum": [
            "api_key",
            "connection",
            "member"
          ],
          "description": "api_key or connection: an owner or admin limited this key or chat connection in the portal. member: the person behind it is limited in the team."
        },
        "sites": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The id."
              },
              "name": {
                "type": "string",
                "description": "The name."
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "description": "The sites it can use. The app of a site comes with it."
        },
        "apps": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The id."
              },
              "name": {
                "type": "string",
                "description": "The name."
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "description": "Apps chosen on their own, next to the apps of the sites."
        },
        "collections": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "description": "The id."
              },
              "name": {
                "type": "string",
                "description": "The name."
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "description": "The collections it can use: the ones the sites and apps use."
        }
      },
      "required": [
        "limited_by",
        "sites",
        "apps",
        "collections"
      ],
      "additionalProperties": false,
      "description": "Null: this key or connection can use the whole project. Otherwise only these sites, apps and collections: lists show only those, and anything for the whole project (billing, team, domains, numbers, a new site or app) is refused with 403 and a user_message."
    }
  },
  "required": [
    "id",
    "name",
    "edition",
    "created_at",
    "mode",
    "access"
  ],
  "additionalProperties": false
}