{
  "openapi": "3.1.0",
  "info": {
    "title": "Interview100x Partner API",
    "version": "1",
    "description": "Bring people into Interview100x practice: create personal practice invites carrying a job, check an invite's status, and read monthly aggregate counts. Partners never see answers, scores, recordings, or whether a specific person practised or paid. Version 1 only grows."
  },
  "servers": [
    {
      "url": "https://www.interview100x.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The key and its partner"
    },
    {
      "name": "Practice invites",
      "description": "Personal practice links"
    },
    {
      "name": "Counts",
      "description": "Monthly aggregate counts"
    },
    {
      "name": "Webhooks",
      "description": "practice.opened and practice.signed_up deliveries"
    }
  ],
  "security": [
    {
      "partnerKey": []
    }
  ],
  "paths": {
    "/api/partner/v1/hooks": {
      "post": {
        "operationId": "createPartnerHook",
        "summary": "Subscribe a webhook",
        "description": "Deliveries of practice.opened and practice.signed_up (ids and timestamps only), signed per Standard Webhooks with the returned secret (headers webhook-id, webhook-timestamp, webhook-signature, x-interview100x-event) and retried for about a day. Deeper stages are available only as counts.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "hooks:manage"
        ],
        "requestBody": {
          "description": "Where to send which events",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerHookCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The endpoint and its signing secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerHookCreated"
                }
              }
            }
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "409": {
            "description": "Error — `WEBHOOK_LIMIT`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "WEBHOOK_LIMIT"
            ],
            "x-error-docs": [
              {
                "code": "WEBHOOK_LIMIT",
                "meaning": "You already have the maximum number of webhook endpoints.",
                "fix": "Delete an endpoint you no longer use, then subscribe again."
              }
            ]
          },
          "422": {
            "description": "Error — `VALIDATION_FAILED`, `WEBHOOK_URL_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "VALIDATION_FAILED",
              "WEBHOOK_URL_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "VALIDATION_FAILED",
                "meaning": "The request is not valid; `details.field` names the first field that failed.",
                "fix": "Correct the named field and send the request again."
              },
              {
                "code": "WEBHOOK_URL_INVALID",
                "meaning": "The webhook address is not a public https:// URL.",
                "fix": "Use an https:// address on the public internet, without credentials in it."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          },
          "503": {
            "description": "Error — `VENDOR_UNAVAILABLE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "VENDOR_UNAVAILABLE"
            ],
            "x-error-docs": [
              {
                "code": "VENDOR_UNAVAILABLE",
                "meaning": "A service we depend on did not answer in time.",
                "fix": "Retry with backoff; nothing was changed when this is returned."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/hooks/{id}": {
      "delete": {
        "operationId": "deletePartnerHook",
        "summary": "Unsubscribe a webhook",
        "description": "Removes the endpoint and cancels its pending deliveries. Idempotent: deleting it again also returns 204.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "hooks:manage"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The endpoint's id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Unsubscribed"
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "404": {
            "description": "Error — `NOT_FOUND`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "NOT_FOUND"
            ],
            "x-error-docs": [
              {
                "code": "NOT_FOUND",
                "meaning": "No object with that id exists for your workspace or partnership.",
                "fix": "Check the id; objects of another workspace, partnership or mode are never visible."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/hooks/{id}/rotate": {
      "post": {
        "operationId": "rotatePartnerHookSecret",
        "summary": "Rotate a webhook's signing secret",
        "description": "A new signing secret, returned only in this response. The old secret keeps signing for 24 hours: every delivery meanwhile carries both signatures in webhook-signature, so your receiver can switch at any point in that window without dropping an event.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "hooks:manage"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The endpoint's id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The new secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerHookRotated"
                }
              }
            }
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "404": {
            "description": "Error — `NOT_FOUND`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "NOT_FOUND"
            ],
            "x-error-docs": [
              {
                "code": "NOT_FOUND",
                "meaning": "No object with that id exists for your workspace or partnership.",
                "fix": "Check the id; objects of another workspace, partnership or mode are never visible."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/hooks/{id}/test": {
      "post": {
        "operationId": "testPartnerHook",
        "summary": "Send a test event",
        "description": "One signed test.ping to the endpoint, now (no retries). At most 30 per 10 minutes per key.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "hooks:manage"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The endpoint's id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "What your endpoint answered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerHookTestResult"
                }
              }
            }
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "404": {
            "description": "Error — `NOT_FOUND`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "NOT_FOUND"
            ],
            "x-error-docs": [
              {
                "code": "NOT_FOUND",
                "meaning": "No object with that id exists for your workspace or partnership.",
                "fix": "Check the id; objects of another workspace, partnership or mode are never visible."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`, `RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED",
              "RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              },
              {
                "code": "RATE_LIMITED",
                "meaning": "Too many requests of this kind in a short time.",
                "fix": "Wait for `Retry-After` (when present) and retry with backoff."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          },
          "503": {
            "description": "Error — `VENDOR_UNAVAILABLE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "VENDOR_UNAVAILABLE"
            ],
            "x-error-docs": [
              {
                "code": "VENDOR_UNAVAILABLE",
                "meaning": "A service we depend on did not answer in time.",
                "fix": "Retry with backoff; nothing was changed when this is returned."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/me": {
      "get": {
        "operationId": "getPartnerMe",
        "summary": "Check a key",
        "description": "The partner and key behind the bearer token, its scopes, livemode and limits. Any valid key may call it.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [],
        "responses": {
          "200": {
            "description": "The partner and key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerMeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/practice-invites": {
      "post": {
        "operationId": "createPracticeInvite",
        "summary": "Create a practice invite",
        "description": "A personal link that opens Interview100x practice for one job. Requires an `Idempotency-Key` header; a repeat with the same key returns the same answer, and a repeat `external_ref` hands back the same live invite.",
        "tags": [
          "Practice invites"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "practice:write"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "1–255 characters, unique per request you mean",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "description": "The person and the job",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PracticeInviteCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The invite and its link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PracticeInviteCreated"
                }
              }
            }
          },
          "400": {
            "description": "Error — `IDEMPOTENCY_KEY_REQUIRED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "IDEMPOTENCY_KEY_REQUIRED"
            ],
            "x-error-docs": [
              {
                "code": "IDEMPOTENCY_KEY_REQUIRED",
                "meaning": "This write route needs an `Idempotency-Key` header and none was sent.",
                "fix": "Send a unique `Idempotency-Key` (1–255 characters) per operation you mean, and reuse it only to retry that operation."
              }
            ]
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "409": {
            "description": "Error — `CONFLICT`, `IDEMPOTENCY_CONFLICT`, `IN_PROGRESS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "IN_PROGRESS"
            ],
            "x-error-docs": [
              {
                "code": "CONFLICT",
                "meaning": "The object is not in a state that allows this change (the message says which).",
                "fix": "Read the object, then retry when its state allows the change; a `retry_after_seconds` detail says when."
              },
              {
                "code": "IDEMPOTENCY_CONFLICT",
                "meaning": "The Idempotency-Key was already used with a different body or on another object.",
                "fix": "Use a new key for a new request; reuse a key only to retry exactly the same request."
              },
              {
                "code": "IN_PROGRESS",
                "meaning": "The first request with this Idempotency-Key is still running.",
                "fix": "Wait for `Retry-After` and retry with the same key; you will get the first request's answer."
              }
            ]
          },
          "422": {
            "description": "Error — `PRACTICE_COUNTRY_NOT_SUPPORTED`, `VALIDATION_FAILED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PRACTICE_COUNTRY_NOT_SUPPORTED",
              "VALIDATION_FAILED"
            ],
            "x-error-docs": [
              {
                "code": "PRACTICE_COUNTRY_NOT_SUPPORTED",
                "meaning": "The job's country is in the EU/EEA or outside the countries Interview100x practice is offered in.",
                "fix": "Practice can't be offered for this job; don't retry with the same country."
              },
              {
                "code": "VALIDATION_FAILED",
                "meaning": "The request is not valid; `details.field` names the first field that failed.",
                "fix": "Correct the named field and send the request again."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          },
          "503": {
            "description": "Error — `VENDOR_UNAVAILABLE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "VENDOR_UNAVAILABLE"
            ],
            "x-error-docs": [
              {
                "code": "VENDOR_UNAVAILABLE",
                "meaning": "A service we depend on did not answer in time.",
                "fix": "Retry with backoff; nothing was changed when this is returned."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/practice-invites/{id}": {
      "get": {
        "operationId": "getPracticeInvite",
        "summary": "Get a practice invite",
        "description": "One invite's status (created, opened, signed_up, expired, cancelled) — enough to resend a link, never more.",
        "tags": [
          "Practice invites"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "practice:read"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The invite's id: a uuid, or `pi_test_…` for a test key",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|pi_test_[0-9a-f]{24})$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The invite",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PracticeInviteRead"
                }
              }
            }
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "404": {
            "description": "Error — `NOT_FOUND`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "NOT_FOUND"
            ],
            "x-error-docs": [
              {
                "code": "NOT_FOUND",
                "meaning": "No object with that id exists for your workspace or partnership.",
                "fix": "Check the id; objects of another workspace, partnership or mode are never visible."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          }
        }
      }
    },
    "/api/partner/v1/stats": {
      "get": {
        "operationId": "getPartnerStats",
        "summary": "Get monthly counts",
        "description": "Aggregate counts for one published cohort month. A month that is not published yet, or a from/to window, is 422.",
        "tags": [
          "Counts"
        ],
        "security": [
          {
            "partnerKey": []
          }
        ],
        "x-scopes": [
          "stats:read"
        ],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "description": "The cohort month, YYYY-MM",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            }
          },
          {
            "name": "sub_partner_ref",
            "in": "query",
            "description": "One cohort: the exact base counts only",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The published counts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerStatsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `PARTNER_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the partner key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active partner key; ask your Neural Bits contact for a new one."
              }
            ]
          },
          "403": {
            "description": "Error — `PARTNER_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "PARTNER_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "PARTNER_SCOPE_MISSING",
                "meaning": "The partner key is valid but lacks the scope this call needs.",
                "fix": "Ask for a key with the scope named in the message."
              },
              {
                "code": "TEST_MODE_ONLY",
                "meaning": "A test key touched a live object, a live key touched a test object, or test mode is turned off.",
                "fix": "Use the key of the same mode as the object (test ids start with `role_test_`, `inv_test_`, `rep_test_`, `pi_test_`); for a test key, ask for test mode to be turned on."
              }
            ]
          },
          "422": {
            "description": "Error — `VALIDATION_FAILED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "VALIDATION_FAILED"
            ],
            "x-error-docs": [
              {
                "code": "VALIDATION_FAILED",
                "meaning": "The request is not valid; `details.field` names the first field that failed.",
                "fix": "Correct the named field and send the request again."
              }
            ]
          },
          "429": {
            "description": "Error — `INTEGRATION_RATE_LIMITED`",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTEGRATION_RATE_LIMITED"
            ],
            "x-error-docs": [
              {
                "code": "INTEGRATION_RATE_LIMITED",
                "meaning": "This key sent more requests in the last minute than its limit allows.",
                "fix": "Wait for the number of seconds in the `Retry-After` header, then retry; spread bursts out."
              }
            ]
          },
          "500": {
            "description": "Error — `INTERNAL`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INTERNAL"
            ],
            "x-error-docs": [
              {
                "code": "INTERNAL",
                "meaning": "Something failed on our side.",
                "fix": "Retry with the same Idempotency-Key (where the route takes one); contact support with the time of the call if it keeps failing."
              }
            ]
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "partnerKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "i100x_live_… / i100x_test_…",
        "description": "A partner key from Neural Bits, sent as `Authorization: Bearer <key>`."
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "UNAUTHENTICATED",
                  "FORBIDDEN",
                  "NOT_FOUND",
                  "VALIDATION_FAILED",
                  "ENTITLEMENT_REQUIRED",
                  "DAILY_CAP",
                  "TRIAL_SPENT",
                  "DEAD_URL",
                  "RATE_LIMITED",
                  "CONFLICT",
                  "VENDOR_UNAVAILABLE",
                  "INTERNAL",
                  "INSUFFICIENT_CREDITS",
                  "INVITE_STATE",
                  "CONSENT_REQUIRED",
                  "GUIDE_NOT_APPROVED",
                  "AGENCY_SUSPENDED",
                  "SESSION_NOT_STARTED",
                  "TEXT_NOT_AVAILABLE",
                  "FLYWHEEL_PAUSED",
                  "FLYWHEEL_BUDGET_EXHAUSTED",
                  "PROPOSAL_GATE_FAILED",
                  "ROLE_REBASELINE_FORBIDDEN",
                  "JUDGE_NOT_CALIBRATED",
                  "SMS_NOT_ENABLED",
                  "SMS_NOT_ATTESTED",
                  "SMS_SUPPRESSED",
                  "SMS_NUMBER_INELIGIBLE",
                  "SMS_PLATFORM_PAUSED",
                  "SHORTLIST_EMPTY",
                  "SHORTLIST_EXPIRED",
                  "NOTE_NOT_APPROVED",
                  "NOTE_UNGROUNDED",
                  "NOTE_IN_PROGRESS",
                  "API_KEY_INVALID",
                  "API_SCOPE_MISSING",
                  "API_DISABLED",
                  "API_KEY_LIMIT",
                  "WEBHOOK_URL_INVALID",
                  "WEBHOOK_LIMIT",
                  "WEBHOOK_ENDPOINT_GONE",
                  "WEBHOOK_DISABLED_BY_SUPPORT",
                  "INTEGRATION_RATE_LIMITED",
                  "GUIDE_NOT_READY",
                  "BRIEF_REFRESH_LIMIT",
                  "BRIEF_RETRY_LIMIT",
                  "BRIEF_ASK_LIMIT",
                  "CUSTOMIZE_REJECTED",
                  "CUSTOMIZE_LIMIT",
                  "RETRY_NOT_ALLOWED",
                  "ROUND_LIMIT",
                  "LOOP_LIMIT",
                  "USER_COST_CEILING",
                  "IDEMPOTENCY_CONFLICT",
                  "IN_PROGRESS",
                  "INSUFFICIENT_SCOPE",
                  "MCP_DISABLED",
                  "TOOL_DISABLED",
                  "TENANT_SUSPENDED",
                  "APPROVAL_REQUIRED",
                  "POOL_EXHAUSTED",
                  "PAYLOAD_TOO_LARGE",
                  "IDEMPOTENCY_KEY_REQUIRED",
                  "ROLE_COUNTRY_NOT_SUPPORTED",
                  "JD_FETCH_FAILED",
                  "HOLD_NOT_SUPPORTED_FOR_RETURN_LINK",
                  "INVITE_NOT_LINKABLE",
                  "ROLE_GUIDE_APPROVED",
                  "OPEN_LINK_CLOSED",
                  "OPEN_LINK_CAP_REACHED",
                  "PRACTICE_COUNTRY_NOT_SUPPORTED",
                  "PRACTICE_INVITE_EXPIRED",
                  "PARTNER_KEY_INVALID",
                  "PARTNER_SCOPE_MISSING",
                  "TEST_MODE_ONLY",
                  "EMAIL_LINK_RATE_LIMITED"
                ],
                "description": "Stable machine-readable code"
              },
              "message": {
                "type": "string",
                "description": "Plain-language message, safe to show"
              },
              "details": {
                "description": "Code-specific details, e.g. `{ field }` for a validation error or `{ retry_after_seconds }` for a 429"
              },
              "message_key": {
                "type": "string"
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ],
        "description": "Every error response has this shape."
      },
      "PartnerHookCreateRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "A public https:// address"
          },
          "events": {
            "description": "Omit (or empty) for every event",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "practice.opened",
                "practice.signed_up"
              ]
            }
          }
        },
        "required": [
          "url"
        ]
      },
      "PartnerHookCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "practice.opened",
                "practice.signed_up"
              ]
            }
          },
          "livemode": {
            "type": "boolean",
            "description": "false for test keys"
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the endpoint was created"
          },
          "secret": {
            "type": "string",
            "description": "whsec_… — shown only in this response; verify each delivery's webhook-signature with it"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "livemode",
          "status",
          "created_at",
          "secret"
        ]
      },
      "PartnerHookRotated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "secret": {
            "type": "string",
            "description": "The new whsec_… — shown only in this response"
          },
          "previous_valid_until": {
            "type": "string",
            "format": "date-time",
            "description": "Until when the old secret still signs (24 hours): every delivery meanwhile carries both signatures"
          }
        },
        "required": [
          "id",
          "secret",
          "previous_valid_until"
        ]
      },
      "PartnerHookTestResult": {
        "type": "object",
        "properties": {
          "delivered": {
            "type": "boolean"
          },
          "status": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ],
            "description": "Your endpoint's HTTP status; null when it could not be reached"
          },
          "livemode": {
            "description": "Present (false) when a test key sent the ping to a test endpoint",
            "type": "boolean"
          }
        },
        "required": [
          "delivered",
          "status"
        ]
      },
      "PartnerMeResponse": {
        "type": "object",
        "properties": {
          "partner": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "key": {
            "type": "object",
            "properties": {
              "prefix": {
                "type": "string"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "practice:write",
                    "practice:read",
                    "stats:read",
                    "hooks:manage"
                  ]
                }
              }
            },
            "required": [
              "prefix",
              "scopes"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "false for test keys"
          },
          "limits": {
            "type": "object",
            "properties": {
              "requests_per_minute": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "practice_invite_days": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "requests_per_minute",
              "practice_invite_days"
            ]
          }
        },
        "required": [
          "partner",
          "key",
          "livemode",
          "limits"
        ]
      },
      "PartnerStatsResponse": {
        "type": "object",
        "properties": {
          "month": {
            "type": "string",
            "description": "The cohort month, YYYY-MM"
          },
          "sub_partner_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "rounded": {
            "type": "boolean",
            "description": "true: later stages are rounded to the nearest 5. false for a test key: the exact counts of your test invites"
          },
          "livemode": {
            "type": "boolean",
            "description": "false for test keys"
          },
          "counts": {
            "type": "object",
            "properties": {
              "invites": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Exact"
              },
              "opened": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Exact"
              },
              "signed_up": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Exact"
              },
              "plan_created": {
                "description": "Only without sub_partner_ref: a rounded count, \"<5\", or \"hidden\"",
                "anyOf": [
                  {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  {
                    "type": "string",
                    "const": "<5"
                  },
                  {
                    "type": "string",
                    "const": "hidden"
                  }
                ]
              },
              "practised": {
                "description": "Only without sub_partner_ref: a rounded count, \"<5\", or \"hidden\"",
                "anyOf": [
                  {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  {
                    "type": "string",
                    "const": "<5"
                  },
                  {
                    "type": "string",
                    "const": "hidden"
                  }
                ]
              },
              "purchased": {
                "description": "Only without sub_partner_ref: a rounded count, \"<5\", or \"hidden\"",
                "anyOf": [
                  {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9007199254740991
                  },
                  {
                    "type": "string",
                    "const": "<5"
                  },
                  {
                    "type": "string",
                    "const": "hidden"
                  }
                ]
              }
            },
            "required": [
              "invites",
              "opened",
              "signed_up"
            ],
            "description": "The cohort is the people who signed up in the month. invites/opened/signed_up are exact; plan_created/practised/purchased count that cohort whenever they happened, are published once on the 1st of the second month after, and are \"hidden\" when the cohort is under 10 or a value would identify people."
          }
        },
        "required": [
          "month",
          "sub_partner_ref",
          "rounded",
          "livemode",
          "counts"
        ]
      },
      "PracticeInviteCreateRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
            "description": "Where the person's practice link goes; the practice account belongs to whoever signs in"
          },
          "full_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 300
          },
          "external_ref": {
            "description": "Your own id for this person or application. Repeating it hands back the same live invite.",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "sub_partner_ref": {
            "description": "Your cohort, school, branch or client — counts can be read per cohort",
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ]
          },
          "job": {
            "type": "object",
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 300
              },
              "company_label": {
                "description": "Shown to the person; \"Confidential employer\" when omitted",
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 300
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "description": {
                "type": "string",
                "minLength": 1,
                "maxLength": 50000,
                "description": "The job description; read once to set up the practice"
              },
              "location": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 300
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "country": {
                "type": "string",
                "pattern": "^[A-Za-z]{2}$",
                "description": "ISO 3166-1 alpha-2. EU/EEA countries are not supported (422 PRACTICE_COUNTRY_NOT_SUPPORTED)."
              }
            },
            "required": [
              "title",
              "description",
              "country"
            ]
          },
          "sponsorship": {
            "description": "Omit for your partnership's sponsorship; \"none\" for an invite without free days",
            "type": "string",
            "const": "none"
          }
        },
        "required": [
          "email",
          "full_name",
          "job"
        ]
      },
      "PracticeInviteCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|pi_test_[0-9a-f]{24})$",
            "description": "The invite's id: a uuid, or `pi_test_…` for a test key"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The personal link, https://www.interview100x.com/p/{token}. Send it only to this person."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the link stops working"
          },
          "offer": {
            "$ref": "#/components/schemas/PracticeOffer"
          },
          "livemode": {
            "type": "boolean",
            "description": "false for test keys"
          }
        },
        "required": [
          "id",
          "url",
          "expires_at",
          "offer",
          "livemode"
        ]
      },
      "PracticeInviteRead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|pi_test_[0-9a-f]{24})$",
            "description": "The invite's id: a uuid, or `pi_test_…` for a test key"
          },
          "status": {
            "type": "string",
            "enum": [
              "created",
              "opened",
              "signed_up",
              "expired",
              "cancelled"
            ],
            "description": "Never more than signed_up: whether a person practised or paid is not shared"
          },
          "external_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "sub_partner_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the link stops working"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the invite was created"
          },
          "livemode": {
            "type": "boolean",
            "description": "false for test keys"
          }
        },
        "required": [
          "id",
          "status",
          "external_ref",
          "sub_partner_ref",
          "expires_at",
          "created_at",
          "livemode"
        ]
      },
      "PracticeOffer": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "free_days",
              "trial_pass",
              "none"
            ],
            "description": "What your partnership can offer right now — never whether this particular person already had a free pass"
          },
          "days": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "kind",
          "days"
        ]
      }
    }
  }
}
