{
  "openapi": "3.1.0",
  "info": {
    "title": "Recruit100x API",
    "version": "1",
    "description": "Create screening invites, read reports and subscribe to webhooks. Version 1 only grows: fields and endpoints are added, never renamed or removed."
  },
  "servers": [
    {
      "url": "https://www.recruit100x.com",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The key and its agency"
    },
    {
      "name": "Roles",
      "description": "Roles and their counts"
    },
    {
      "name": "Invites",
      "description": "Screening invites"
    },
    {
      "name": "Reports",
      "description": "Screening reports"
    },
    {
      "name": "Webhooks",
      "description": "REST-hook subscriptions and samples"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/api/v1/hooks": {
      "post": {
        "operationId": "createHook",
        "summary": "Subscribe a webhook",
        "description": "A REST-hook subscription (Zapier, Make or your own endpoint). The signing secret is returned only here. Without `api_version` the hook gets 2026-09-01 payloads.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "manage:hooks"
        ],
        "requestBody": {
          "description": "Where to send which events",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HookCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The subscription and its signing secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HookCreatedResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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 — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/hooks/samples/{event}": {
      "get": {
        "operationId": "getHookSample",
        "summary": "Get a sample event",
        "description": "A sample event envelope for Zapier and Make (the same fixtures the webhook contract tests validate). Needs the event's read scope. Without `api_version` (or with 2026-09-01) the sample is a 2026-09-01 envelope; with `api_version=2026-11-01` it is a 2026-11-01 envelope and the role events are available.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [],
        "parameters": [
          {
            "name": "event",
            "in": "path",
            "description": "The event type (role.* only with api_version 2026-11-01)",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "invite.sent",
                "invite.opened",
                "screen.completed",
                "report.ready",
                "report.failed",
                "decision.recorded",
                "client_feedback.received",
                "candidate.sms_opted_out",
                "shortlist.created",
                "candidate.handoff",
                "role.ready",
                "role.closed",
                "role.guide_failed"
              ]
            }
          },
          {
            "name": "api_version",
            "in": "query",
            "description": "The payload version of the sample",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "2026-09-01",
                "2026-11-01"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One sample envelope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HookSampleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/hooks/{hookId}": {
      "delete": {
        "operationId": "deleteHook",
        "summary": "Unsubscribe a webhook",
        "description": "Removes a subscription created through this API. Idempotent: deleting it again also returns 204.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "manage:hooks"
        ],
        "parameters": [
          {
            "name": "hookId",
            "in": "path",
            "description": "The subscription's id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Unsubscribed"
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/hooks/{hookId}/test": {
      "post": {
        "operationId": "testHook",
        "summary": "Send a test event",
        "description": "Sends a signed `test.ping` event of the hook's payload version to a subscription created through this API — the same path real events take. At most 30 per 10 minutes per key. The hook must be on.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "manage:hooks"
        ],
        "parameters": [
          {
            "name": "hookId",
            "in": "path",
            "description": "The subscription's id",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Your unique key for this request (1–255 characters). A retry with the same key and body returns the first answer for 24 hours; the same key with another body is refused (409).",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The test delivery",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HookTestResponse"
                }
              }
            }
          },
          "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 — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "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."
              }
            ]
          },
          "410": {
            "description": "Error — `WEBHOOK_ENDPOINT_GONE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "WEBHOOK_ENDPOINT_GONE"
            ],
            "x-error-docs": [
              {
                "code": "WEBHOOK_ENDPOINT_GONE",
                "meaning": "The webhook endpoint was deleted.",
                "fix": "Subscribe a new endpoint."
              }
            ]
          },
          "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 — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/invites/{inviteId}": {
      "get": {
        "operationId": "getInvite",
        "summary": "Get an invite",
        "description": "One invite: its status, expiry, your `external_ref`, who delivers the link (`delivery`) and the door it came through (`source`).",
        "tags": [
          "Invites"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "read:roles"
        ],
        "parameters": [
          {
            "name": "inviteId",
            "in": "path",
            "description": "The invite's id",
            "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}|inv_test_[0-9a-f]{24})$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The invite",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/invites/{inviteId}/cancel": {
      "post": {
        "operationId": "cancelInvite",
        "summary": "Cancel an invite",
        "description": "Cancels an invite that has not started, exactly as the dashboard's Cancel does (reminders stop), and turns off every link to it. Cancelling a cancelled invite returns it again; a started or finished invite cannot be cancelled (409).",
        "tags": [
          "Invites"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "write:invites"
        ],
        "parameters": [
          {
            "name": "inviteId",
            "in": "path",
            "description": "The invite's id",
            "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}|inv_test_[0-9a-f]{24})$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Your unique key for this request (1–255 characters). A retry with the same key and body returns the first answer for 24 hours; the same key with another body is refused (409).",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The invite after the cancel",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteResponse"
                }
              }
            }
          },
          "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 — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `FORBIDDEN`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "FORBIDDEN",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "code": "FORBIDDEN",
                "meaning": "This key may not act on that object.",
                "fix": "Use a key of the workspace that owns the object."
              },
              {
                "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."
              }
            ]
          },
          "409": {
            "description": "Error — `IDEMPOTENCY_CONFLICT`, `INVITE_STATE`, `IN_PROGRESS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "IDEMPOTENCY_CONFLICT",
              "INVITE_STATE",
              "IN_PROGRESS"
            ],
            "x-error-docs": [
              {
                "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": "INVITE_STATE",
                "meaning": "The invite's status doesn't allow this action (for example, cancelling a started interview).",
                "fix": "Read the invite's status first; only unstarted invites can be cancelled."
              },
              {
                "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."
              }
            ]
          },
          "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 — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/invites/{inviteId}/link": {
      "post": {
        "operationId": "createInviteLink",
        "summary": "Issue a new link",
        "description": "For a `return_link` invite whose link you lost: issues an additional link (the earlier ones keep working) and returns it once. Only while the invite is live — not completed, expired or cancelled — and only for `return_link` invites (409 INVITE_NOT_LINKABLE otherwise).",
        "tags": [
          "Invites"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "write:invites"
        ],
        "parameters": [
          {
            "name": "inviteId",
            "in": "path",
            "description": "The invite's id",
            "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}|inv_test_[0-9a-f]{24})$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Your unique key for this request (1–255 characters). A retry with the same key and body returns the first answer for 24 hours; the same key with another body is refused (409).",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "responses": {
          "201": {
            "description": "The new link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteLinkResponse"
                }
              }
            }
          },
          "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 — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "409": {
            "description": "Error — `IDEMPOTENCY_CONFLICT`, `INVITE_NOT_LINKABLE`, `IN_PROGRESS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "IDEMPOTENCY_CONFLICT",
              "INVITE_NOT_LINKABLE",
              "IN_PROGRESS"
            ],
            "x-error-docs": [
              {
                "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": "INVITE_NOT_LINKABLE",
                "meaning": "A new link can be issued only for a live invite created with `\"delivery\": \"return_link\"`.",
                "fix": "Check `details.reason`; for an expired, cancelled or finished invite, invite the candidate again."
              },
              {
                "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."
              }
            ]
          },
          "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 — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Check a key",
        "description": "The agency and key behind the bearer token — the connection test for Zapier and Make — with the credit balance, the key's scopes, whether it is a live key and the limits. Any valid key may call it.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [],
        "responses": {
          "200": {
            "description": "The agency, the key and its limits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/reports/{reportId}": {
      "get": {
        "operationId": "getReport",
        "summary": "Get a report",
        "description": "The full report — the `report.ready` event data, plus your own ids, the invite and the band summary.",
        "tags": [
          "Reports"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "read:reports"
        ],
        "parameters": [
          {
            "name": "reportId",
            "in": "path",
            "description": "The report's id",
            "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}|rep_test_[0-9a-f]{24})$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The report",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportPayload"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/roles": {
      "get": {
        "operationId": "listRoles",
        "summary": "List roles",
        "description": "The agency's roles with invite and completion counts, guide status, open link and dashboard link (not paginated).",
        "tags": [
          "Roles"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "read:roles"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Only roles in this status",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "active",
                "closed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The roles",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      },
      "post": {
        "operationId": "createRole",
        "summary": "Create a role",
        "description": "Create a role from a job description (pasted text or a job link) — the same service as the dashboard. The guide is drafted at once; `guide_status` is `drafting` until it is ready for approval. The role gets an open screening link with your workspace's default policy unless you send `open_link` — send `{\"policy\": \"invite_only\"}` if you apply your own eligibility. Needs a positive credit balance; a daily per-workspace limit applies.",
        "tags": [
          "Roles"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "write:roles"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Your unique key for this request (1–255 characters). A retry with the same key and body returns the first answer for 24 hours; the same key with another body is refused (409).",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "description": "The role",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleCreatedResponse"
                }
              }
            }
          },
          "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 — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "402": {
            "description": "Error — `INSUFFICIENT_CREDITS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INSUFFICIENT_CREDITS"
            ],
            "x-error-docs": [
              {
                "code": "INSUFFICIENT_CREDITS",
                "meaning": "The workspace has no credits left, so no new invite was sent.",
                "fix": "Buy credits on recruit100x.com, then send the invites again."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `FORBIDDEN`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "FORBIDDEN",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "code": "FORBIDDEN",
                "meaning": "This key may not act on that object.",
                "fix": "Use a key of the workspace that owns the object."
              },
              {
                "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 — `IDEMPOTENCY_CONFLICT`, `IN_PROGRESS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "IDEMPOTENCY_CONFLICT",
              "IN_PROGRESS"
            ],
            "x-error-docs": [
              {
                "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 — `JD_FETCH_FAILED`, `ROLE_COUNTRY_NOT_SUPPORTED`, `VALIDATION_FAILED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "JD_FETCH_FAILED",
              "ROLE_COUNTRY_NOT_SUPPORTED",
              "VALIDATION_FAILED"
            ],
            "x-error-docs": [
              {
                "code": "JD_FETCH_FAILED",
                "meaning": "We couldn't read a job description at the link you sent.",
                "fix": "Send the description as text: `\"jd\": {\"mode\": \"paste\", \"text\": …}`."
              },
              {
                "code": "ROLE_COUNTRY_NOT_SUPPORTED",
                "meaning": "The role's location is in the EU/EEA or outside the countries Recruit100x screens for.",
                "fix": "Recruit100x can't screen for this role; don't retry with the same location."
              },
              {
                "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`, `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 — `API_DISABLED`, `VENDOR_UNAVAILABLE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED",
              "VENDOR_UNAVAILABLE"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              },
              {
                "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/v1/roles/{roleId}": {
      "get": {
        "operationId": "getRole",
        "summary": "Get a role",
        "description": "One role with its counts, guide status, open link and dashboard link.",
        "tags": [
          "Roles"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "read:roles"
        ],
        "parameters": [
          {
            "name": "roleId",
            "in": "path",
            "description": "The role's id",
            "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}|role_test_[0-9a-f]{24})$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The role",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      },
      "patch": {
        "operationId": "updateRole",
        "summary": "Change a role",
        "description": "Change the job details while the guide is not approved (the guide is drafted again; after approval → 409 ROLE_GUIDE_APPROVED; while a guide is being drafted → 409 CONFLICT with Retry-After), activate, close (`open_invites`: cancel or keep) or reopen it, edit or regenerate its open link, or set `external_ref`. A closed role accepts only reopening.",
        "tags": [
          "Roles"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "write:roles"
        ],
        "parameters": [
          {
            "name": "roleId",
            "in": "path",
            "description": "The role's id",
            "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}|role_test_[0-9a-f]{24})$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Your unique key for this request (1–255 characters). A retry with the same key and body returns the first answer for 24 hours; the same key with another body is refused (409).",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "description": "The fields to change",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RolePatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The role after the change",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleResponse"
                }
              }
            }
          },
          "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 — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `FORBIDDEN`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "FORBIDDEN",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "code": "FORBIDDEN",
                "meaning": "This key may not act on that object.",
                "fix": "Use a key of the workspace that owns the object."
              },
              {
                "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."
              }
            ]
          },
          "409": {
            "description": "Error — `CONFLICT`, `IDEMPOTENCY_CONFLICT`, `IN_PROGRESS`, `ROLE_GUIDE_APPROVED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "CONFLICT",
              "IDEMPOTENCY_CONFLICT",
              "IN_PROGRESS",
              "ROLE_GUIDE_APPROVED"
            ],
            "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."
              },
              {
                "code": "ROLE_GUIDE_APPROVED",
                "meaning": "The role's interview guide is approved, so its job description and title can no longer change.",
                "fix": "Create a new role for a changed job."
              }
            ]
          },
          "422": {
            "description": "Error — `JD_FETCH_FAILED`, `VALIDATION_FAILED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "JD_FETCH_FAILED",
              "VALIDATION_FAILED"
            ],
            "x-error-docs": [
              {
                "code": "JD_FETCH_FAILED",
                "meaning": "We couldn't read a job description at the link you sent.",
                "fix": "Send the description as text: `\"jd\": {\"mode\": \"paste\", \"text\": …}`."
              },
              {
                "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 — `API_DISABLED`, `VENDOR_UNAVAILABLE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED",
              "VENDOR_UNAVAILABLE"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              },
              {
                "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/v1/roles/{roleId}/invites": {
      "post": {
        "operationId": "createInvites",
        "summary": "Invite candidates",
        "description": "Import up to 100 candidates and send each a screening invite through the agency's normal invite path. Request-level problems (role, approved guide, credits, paused sending) refuse the whole request before any candidate is written; a bad row is reported per row as `invalid`. Send `delivery` to choose who delivers the link (`return_link` returns it as `screen_url`) and to get each row's `invite_id`, `expires_at`, `external_ref` and the `duplicate` status — without it the answer is the original one.",
        "tags": [
          "Invites"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "write:invites"
        ],
        "parameters": [
          {
            "name": "roleId",
            "in": "path",
            "description": "The role's id",
            "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}|role_test_[0-9a-f]{24})$"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Optional: your unique key for this request (1–255 characters). A retry with the same key and body returns the first answer for 24 hours (any `screen_url` redacted); the same key with another body is refused (409).",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "description": "The candidates to invite",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteBatchRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Per-row results and a summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteBatchResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "402": {
            "description": "Error — `INSUFFICIENT_CREDITS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "INSUFFICIENT_CREDITS"
            ],
            "x-error-docs": [
              {
                "code": "INSUFFICIENT_CREDITS",
                "meaning": "The workspace has no credits left, so no new invite was sent.",
                "fix": "Buy credits on recruit100x.com, then send the invites again."
              }
            ]
          },
          "403": {
            "description": "Error — `AGENCY_SUSPENDED`, `API_SCOPE_MISSING`, `FORBIDDEN`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "AGENCY_SUSPENDED",
              "API_SCOPE_MISSING",
              "FORBIDDEN",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "AGENCY_SUSPENDED",
                "meaning": "The workspace is suspended: reads keep working, actions are refused.",
                "fix": "Contact Recruit100x support."
              },
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "code": "FORBIDDEN",
                "meaning": "This key may not act on that object.",
                "fix": "Use a key of the workspace that owns the object."
              },
              {
                "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."
              }
            ]
          },
          "409": {
            "description": "Error — `CONFLICT`, `GUIDE_NOT_APPROVED`, `IDEMPOTENCY_CONFLICT`, `IN_PROGRESS`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "CONFLICT",
              "GUIDE_NOT_APPROVED",
              "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": "GUIDE_NOT_APPROVED",
                "meaning": "The role's interview guide isn't approved yet, so candidates can't be invited.",
                "fix": "Wait for the `role.ready` event, or send `\"hold_until_ready\": true` with `\"delivery\": \"recruit100x\"`."
              },
              {
                "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 — `HOLD_NOT_SUPPORTED_FOR_RETURN_LINK`, `VALIDATION_FAILED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "HOLD_NOT_SUPPORTED_FOR_RETURN_LINK",
              "VALIDATION_FAILED"
            ],
            "x-error-docs": [
              {
                "code": "HOLD_NOT_SUPPORTED_FOR_RETURN_LINK",
                "meaning": "`hold_until_ready` can't be combined with `\"delivery\": \"return_link\"`.",
                "fix": "Wait for `role.ready` and invite then, or use `\"delivery\": \"recruit100x\"`."
              },
              {
                "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 — `API_DISABLED`, `VENDOR_UNAVAILABLE`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED",
              "VENDOR_UNAVAILABLE"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              },
              {
                "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/v1/roles/{roleId}/reports": {
      "get": {
        "operationId": "listRoleReports",
        "summary": "List a role's reports",
        "description": "Report summaries for one role, newest first, cursor-paginated, with each report's invite and band summary.",
        "tags": [
          "Reports"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "read:reports"
        ],
        "parameters": [
          {
            "name": "roleId",
            "in": "path",
            "description": "The role's id",
            "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}|role_test_[0-9a-f]{24})$"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "Only reports in this state",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "generating",
                "ready",
                "failed"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "description": "Only reports created at or after this ISO 8601 time",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "`next_cursor` from the previous page",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size (default 25)",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of report summaries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleReportsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    },
    "/api/v1/stats/candidate-care": {
      "get": {
        "operationId": "getCandidateCareStats",
        "summary": "Candidate-care totals for a month",
        "description": "Your workspace's candidate-care totals for one month: the candidates who finished an interview that month while the free practice offer could be shown to them, and how many saw it, clicked, signed up, created a plan, practiced and purchased. Recruit100x never tells you who did what (your compliance export records only, per interview, when the offer was shown and any request to be sent it after the decision); the totals are designed so they do not identify a candidate, and trying to work out an individual candidate's outcome from them is prohibited by the Recruit100x Terms. Clicks and practice count only within a fixed observation window after the offer was shown or emailed. A month is published once, on the 1st of the month after next (UTC), and is final when published; until then this answers 422. `finished`, `offer_possible` and `shown` are exact; the counts after `shown` are rounded to the nearest 5, under 5 is `\"<5\"`, and small groups are `\"hidden\"`.",
        "tags": [
          "Reports"
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "x-scopes": [
          "read:reports"
        ],
        "parameters": [
          {
            "name": "month",
            "in": "query",
            "description": "The month, `YYYY-MM`",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The published month",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CandidateCareStatsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error — `API_KEY_INVALID`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_KEY_INVALID"
            ],
            "x-error-docs": [
              {
                "code": "API_KEY_INVALID",
                "meaning": "The Authorization header is missing, or the key is unknown, revoked or expired.",
                "fix": "Send `Authorization: Bearer <key>` with an active key; create a new one in Settings › Integrations if it was revoked or expired."
              }
            ]
          },
          "403": {
            "description": "Error — `API_SCOPE_MISSING`, `TEST_MODE_ONLY`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_SCOPE_MISSING",
              "TEST_MODE_ONLY"
            ],
            "x-error-docs": [
              {
                "code": "API_SCOPE_MISSING",
                "meaning": "The key is valid but lacks the scope this call needs.",
                "fix": "Create a key with the scope named in the message (the old key keeps its scopes)."
              },
              {
                "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."
              }
            ]
          },
          "503": {
            "description": "Error — `API_DISABLED`",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            },
            "x-error-codes": [
              "API_DISABLED"
            ],
            "x-error-docs": [
              {
                "code": "API_DISABLED",
                "meaning": "The API is switched off for maintenance or by support.",
                "fix": "Retry later; check the status page or contact support if it lasts."
              }
            ]
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "r100x_live_… / r100x_test_…",
        "description": "An API key from Settings → Integrations, sent as `Authorization: Bearer <key>`."
      }
    },
    "schemas": {
      "CandidateCareStatsResponse": {
        "type": "object",
        "properties": {
          "month": {
            "type": "string",
            "description": "The cohort month, `YYYY-MM`"
          },
          "rounded": {
            "type": "boolean",
            "const": true,
            "description": "Every count after `shown` is published rounded"
          },
          "finished": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Interviews finished in the month (exact)"
          },
          "offer_possible": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Finished interviews where the offer could be shown — the month's base (exact)"
          },
          "shown": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Finished interviews whose candidate was shown the offer (exact — the compliance export lists it per interview; D-PL-362)"
          },
          "clicked": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "<5"
              },
              {
                "type": "string",
                "const": "hidden"
              }
            ],
            "description": "Rounded to the nearest 5, `\"<5\"` under 5, or `\"hidden\"` (small groups, and steps nearly everyone in the group took). The totals are designed so they do not identify a candidate; trying to work out an individual candidate's outcome is prohibited by the Recruit100x Terms."
          },
          "signed_up": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "<5"
              },
              {
                "type": "string",
                "const": "hidden"
              }
            ],
            "description": "Rounded to the nearest 5, `\"<5\"` under 5, or `\"hidden\"` (small groups, and steps nearly everyone in the group took). The totals are designed so they do not identify a candidate; trying to work out an individual candidate's outcome is prohibited by the Recruit100x Terms."
          },
          "plan_created": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "<5"
              },
              {
                "type": "string",
                "const": "hidden"
              }
            ],
            "description": "Rounded to the nearest 5, `\"<5\"` under 5, or `\"hidden\"` (small groups, and steps nearly everyone in the group took). The totals are designed so they do not identify a candidate; trying to work out an individual candidate's outcome is prohibited by the Recruit100x Terms."
          },
          "practised": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "<5"
              },
              {
                "type": "string",
                "const": "hidden"
              }
            ],
            "description": "Rounded to the nearest 5, `\"<5\"` under 5, or `\"hidden\"` (small groups, and steps nearly everyone in the group took). The totals are designed so they do not identify a candidate; trying to work out an individual candidate's outcome is prohibited by the Recruit100x Terms."
          },
          "purchased": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "string",
                "const": "<5"
              },
              {
                "type": "string",
                "const": "hidden"
              }
            ],
            "description": "Rounded to the nearest 5, `\"<5\"` under 5, or `\"hidden\"` (small groups, and steps nearly everyone in the group took). The totals are designed so they do not identify a candidate; trying to work out an individual candidate's outcome is prohibited by the Recruit100x Terms."
          },
          "livemode": {
            "type": "boolean",
            "description": "false for a test key's answer (test mode)"
          }
        },
        "required": [
          "month",
          "rounded",
          "finished",
          "offer_possible",
          "shown",
          "clicked",
          "signed_up",
          "plan_created",
          "practised",
          "purchased",
          "livemode"
        ]
      },
      "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."
      },
      "Evidence": {
        "type": "object",
        "properties": {
          "quote": {
            "type": "string",
            "description": "The candidate's own words"
          },
          "t": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Seconds into the recording; null when unknown"
          }
        },
        "required": [
          "quote",
          "t"
        ]
      },
      "HookCreateRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "https:// only, at most 2000 characters, no credentials, a public internet address (its DNS answers are checked too)"
          },
          "events": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "invite.sent",
                "invite.opened",
                "screen.completed",
                "report.ready",
                "report.failed",
                "decision.recorded",
                "client_feedback.received",
                "candidate.sms_opted_out",
                "shortlist.created",
                "candidate.handoff",
                "role.ready",
                "role.closed",
                "role.guide_failed"
              ]
            },
            "description": "Each event needs the key's matching read scope; the role.* events need api_version 2026-11-01"
          },
          "source": {
            "description": "Default `custom`",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "custom",
                  "zapier",
                  "make"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "api_version": {
            "description": "The payload version (default 2026-09-01; 2026-11-01 adds your own ids, the invite, band counts and the role.* events)",
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "2026-09-01",
                  "2026-11-01"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "url",
          "events"
        ]
      },
      "HookCreatedResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Hook id"
          },
          "secret": {
            "type": "string",
            "description": "The signing secret (`whsec_…`) — shown only in this response"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "invite.sent",
                "invite.opened",
                "screen.completed",
                "report.ready",
                "report.failed",
                "decision.recorded",
                "client_feedback.received",
                "candidate.sms_opted_out",
                "shortlist.created",
                "candidate.handoff",
                "role.ready",
                "role.closed",
                "role.guide_failed"
              ]
            }
          },
          "source": {
            "type": "string",
            "enum": [
              "custom",
              "zapier",
              "make"
            ]
          },
          "api_version": {
            "description": "Present when the request chose a version",
            "type": "string",
            "enum": [
              "2026-09-01",
              "2026-11-01"
            ]
          },
          "livemode": {
            "description": "Present (false) only for an endpoint created with a test key: it receives test events only",
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "id",
          "secret",
          "events",
          "source"
        ]
      },
      "HookSampleResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Event id"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "invite.sent",
                    "invite.opened",
                    "screen.completed",
                    "report.ready",
                    "report.failed",
                    "decision.recorded",
                    "client_feedback.received",
                    "candidate.sms_opted_out",
                    "shortlist.created",
                    "candidate.handoff"
                  ]
                },
                "api_version": {
                  "type": "string",
                  "description": "The payload version (2026-09-01)"
                },
                "occurred_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the event happened"
                },
                "agency_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Agency id"
                },
                "data": {
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {},
                  "description": "The event data — see the webhook schema for the event type"
                }
              },
              "required": [
                "id",
                "type",
                "api_version",
                "occurred_at",
                "agency_id",
                "data"
              ]
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "HookTestResponse": {
        "type": "object",
        "properties": {
          "delivery_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}|evt_test_[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})$",
            "description": "Delivery id: a uuid, or `evt_test_…` in test mode"
          },
          "status": {
            "type": "string",
            "description": "The delivery outcome (`success`, `failed`, …), or `pending` when it is queued"
          },
          "livemode": {
            "type": "boolean",
            "description": "false for a test key's answer (test mode)"
          }
        },
        "required": [
          "delivery_id",
          "status",
          "livemode"
        ]
      },
      "InviteBatchRequest": {
        "type": "object",
        "properties": {
          "candidates": {
            "minItems": 1,
            "maxItems": 100,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/InviteCandidateRow"
            }
          },
          "sms_consent_attested": {
            "description": "Texting consent attestation for every invite in the batch (texting is off unless enabled)",
            "type": "boolean"
          },
          "delivery": {
            "description": "`recruit100x`: we email the link (and remind). `return_link`: you deliver it — each invited row returns `screen_url` once. `workspace_default`: whichever of the two your workspace chose for invitations made through the API (the Zapier and Make apps send this). Sending `delivery` also turns on the rows' `invite_id`, `expires_at`, `external_ref` and the `duplicate` status; without it the answer is the original one",
            "type": "string",
            "enum": [
              "recruit100x",
              "return_link",
              "workspace_default"
            ]
          },
          "reminders": {
            "description": "With `delivery`: send the reminder before expiry (default true)",
            "type": "boolean"
          },
          "hold_until_ready": {
            "description": "With `delivery: \"recruit100x\"`: if the role's guide is not approved yet, hold the candidates (`held`) and invite them the moment it is. Not with `return_link` (422) — wait for `role.ready`",
            "type": "boolean"
          }
        },
        "required": [
          "candidates"
        ]
      },
      "InviteBatchResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "anyOf": [
                {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "const": "invited"
                    },
                    "candidate_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}|inv_test_[0-9a-f]{24})$",
                      "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
                    },
                    "invite_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}|inv_test_[0-9a-f]{24})$",
                      "description": "Invite id: a uuid, or `inv_test_…` in test mode"
                    },
                    "email_delivery": {
                      "type": "string",
                      "enum": [
                        "sent",
                        "failed",
                        "none"
                      ],
                      "description": "`none`: `return_link` — we send no email"
                    },
                    "sms_consent_attested": {
                      "type": "boolean"
                    },
                    "screen_url": {
                      "description": "`return_link` only, in the first response only — never stored; a replay says `screen_url_redacted: true`",
                      "type": "string",
                      "format": "uri"
                    },
                    "screen_url_redacted": {
                      "type": "boolean",
                      "const": true
                    },
                    "expires_at": {
                      "description": "With `delivery` only",
                      "type": "string",
                      "format": "date-time"
                    },
                    "external_ref": {
                      "description": "With `delivery` only",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "index",
                    "status",
                    "candidate_id",
                    "invite_id",
                    "email_delivery",
                    "sms_consent_attested"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "const": "skipped"
                    },
                    "candidate_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}|inv_test_[0-9a-f]{24})$",
                      "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
                    },
                    "reason": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "index",
                    "status",
                    "candidate_id",
                    "reason"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "const": "invalid"
                    },
                    "reason": {
                      "type": "string"
                    },
                    "field": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "index",
                    "status",
                    "reason"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "const": "duplicate"
                    },
                    "candidate_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}|inv_test_[0-9a-f]{24})$",
                      "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
                    },
                    "invite_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}|inv_test_[0-9a-f]{24})$",
                      "description": "The live invite this candidate already has"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "When that invite expires"
                    },
                    "external_ref": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "reason": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "index",
                    "status",
                    "candidate_id",
                    "invite_id",
                    "expires_at",
                    "external_ref",
                    "reason"
                  ],
                  "description": "With `delivery` only: the candidate already has a live invite for this role"
                },
                {
                  "type": "object",
                  "properties": {
                    "index": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "status": {
                      "type": "string",
                      "const": "held"
                    },
                    "candidate_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}|inv_test_[0-9a-f]{24})$",
                      "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
                    },
                    "invite_id": {
                      "type": "null"
                    },
                    "expires_at": {
                      "type": "null"
                    },
                    "external_ref": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "index",
                    "status",
                    "candidate_id",
                    "invite_id",
                    "expires_at",
                    "external_ref"
                  ],
                  "description": "With `hold_until_ready` only: invited automatically when the guide is approved"
                }
              ]
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "invited": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "skipped": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "invalid": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "sms_consent_attested": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "duplicate": {
                "description": "With `delivery` only",
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "held": {
                "description": "With `delivery` only",
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "invited",
              "skipped",
              "invalid",
              "sms_consent_attested"
            ]
          },
          "livemode": {
            "description": "Present (false) only on a test key's answer",
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "data",
          "summary"
        ]
      },
      "InviteCandidateRow": {
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string",
            "minLength": 1,
            "description": "Required (surrounding spaces are trimmed); a row without it is reported `invalid`"
          },
          "email": {
            "type": "string",
            "pattern": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",
            "format": "email",
            "description": "Required (trimmed); a row with an invalid or repeated email is reported `invalid`"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "description": "Where the candidate came from (first 80 characters kept); ignored unless it is text; default `api`",
            "type": "string"
          },
          "external_ref": {
            "description": "With `delivery`: your own id for this application; returned on the row, the invite and its webhooks",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ]
          },
          "country": {
            "description": "With `delivery`: the candidate's ISO 3166-1 alpha-2 country; EU/EEA countries are refused per row (`country_not_supported`)",
            "anyOf": [
              {
                "type": "string",
                "minLength": 2,
                "maxLength": 2
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "full_name",
          "email"
        ]
      },
      "InviteLinkResponse": {
        "type": "object",
        "properties": {
          "invite_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}|inv_test_[0-9a-f]{24})$",
            "description": "Invite id: a uuid, or `inv_test_…` in test mode"
          },
          "screen_url": {
            "description": "The new link — in the first answer only, never stored",
            "type": "string",
            "format": "uri"
          },
          "screen_url_redacted": {
            "description": "A replay of the same Idempotency-Key: the link is not repeated",
            "type": "boolean",
            "const": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the invite (and every link to it) expires"
          },
          "livemode": {
            "type": "boolean",
            "description": "false for a test key's answer (test mode)"
          }
        },
        "required": [
          "invite_id",
          "expires_at",
          "livemode"
        ]
      },
      "InviteRef": {
        "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}|inv_test_[0-9a-f]{24})$",
            "description": "Invite id: a uuid, or `inv_test_…` in test mode"
          },
          "status": {
            "type": "string",
            "description": "The invite's status"
          },
          "sent_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "When the invite was sent"
              },
              {
                "type": "null"
              }
            ]
          },
          "opened_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "When the candidate first opened it"
              },
              {
                "type": "null"
              }
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the link expires"
          },
          "opened_via": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "email",
                  "sms",
                  "api",
                  "unknown"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "external_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Your own id for the invite, if you sent one"
          },
          "delivery": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "recruit100x",
                  "return_link"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who delivers the link; null for invites made before it was recorded"
          },
          "source": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "dashboard",
                  "csv",
                  "api",
                  "mcp",
                  "open_link",
                  "email_in",
                  "zapier",
                  "make"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The door the invite came through; null before it was recorded"
          }
        },
        "required": [
          "id",
          "status",
          "sent_at",
          "opened_at",
          "expires_at",
          "opened_via",
          "external_ref",
          "delivery",
          "source"
        ]
      },
      "InviteResponse": {
        "type": "object",
        "properties": {
          "invite": {
            "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}|inv_test_[0-9a-f]{24})$",
                "description": "Invite id: a uuid, or `inv_test_…` in test mode"
              },
              "status": {
                "type": "string",
                "description": "The invite's status"
              },
              "sent_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the invite was sent"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "opened_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the candidate first opened it"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the link expires"
              },
              "opened_via": {
                "anyOf": [
                  {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms",
                      "api",
                      "unknown"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "external_ref": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Your own id for the invite, if you sent one"
              },
              "delivery": {
                "anyOf": [
                  {
                    "type": "string",
                    "enum": [
                      "recruit100x",
                      "return_link"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Who delivers the link; null for invites made before it was recorded"
              },
              "source": {
                "anyOf": [
                  {
                    "type": "string",
                    "enum": [
                      "dashboard",
                      "csv",
                      "api",
                      "mcp",
                      "open_link",
                      "email_in",
                      "zapier",
                      "make"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The door the invite came through; null before it was recorded"
              },
              "role_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}|role_test_[0-9a-f]{24})$",
                "description": "Role id: a uuid, or `role_test_…` in test mode"
              },
              "candidate_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}|inv_test_[0-9a-f]{24})$",
                "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
              }
            },
            "required": [
              "id",
              "status",
              "sent_at",
              "opened_at",
              "expires_at",
              "opened_via",
              "external_ref",
              "delivery",
              "source",
              "role_id",
              "candidate_id"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "false for a test key's answer (test mode)"
          }
        },
        "required": [
          "invite",
          "livemode"
        ]
      },
      "MeResponse": {
        "type": "object",
        "properties": {
          "agency": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Agency id"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ]
          },
          "key": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "read:reports",
                    "read:roles",
                    "write:invites",
                    "manage:hooks",
                    "mcp:read",
                    "mcp:manage",
                    "mcp:screen",
                    "mcp:share",
                    "mcp:handoff",
                    "write:roles"
                  ]
                }
              }
            },
            "required": [
              "name",
              "scopes"
            ]
          },
          "credit_balance": {
            "description": "The workspace's credit balance (one credit per billable completed screen)",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "scopes": {
            "description": "The key's scopes (same as `key.scopes`)",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read:reports",
                "read:roles",
                "write:invites",
                "manage:hooks",
                "mcp:read",
                "mcp:manage",
                "mcp:screen",
                "mcp:share",
                "mcp:handoff",
                "write:roles"
              ]
            }
          },
          "livemode": {
            "description": "false for a test key",
            "type": "boolean"
          },
          "limits": {
            "type": "object",
            "properties": {
              "requests_per_minute": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "description": "Requests per minute per key (60)"
              },
              "invite_batch_max": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "description": "Candidates per invite request (100)"
              }
            },
            "required": [
              "requests_per_minute",
              "invite_batch_max"
            ]
          }
        },
        "required": [
          "agency",
          "key"
        ]
      },
      "ReportPayload": {
        "type": "object",
        "properties": {
          "report": {
            "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}|rep_test_[0-9a-f]{24})$",
                "description": "Report id: a uuid, or `rep_test_…` in test mode"
              },
              "state": {
                "type": "string",
                "enum": [
                  "pending",
                  "generating",
                  "ready",
                  "failed"
                ]
              },
              "url": {
                "type": "string",
                "format": "uri"
              },
              "generated_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the report became ready"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "state",
              "url",
              "generated_at"
            ]
          },
          "role": {
            "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}|role_test_[0-9a-f]{24})$",
                "description": "Role id: a uuid, or `role_test_…` in test mode"
              },
              "title": {
                "type": "string"
              },
              "client_label": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "external_ref": {
                "description": "Your own id for the role (API reads)",
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "title",
              "client_label"
            ]
          },
          "candidate": {
            "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}|inv_test_[0-9a-f]{24})$",
                "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
              },
              "full_name": {
                "type": "string",
                "description": "\"Candidate (deleted)\" once anonymized"
              },
              "email": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "phone": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "anonymized": {
                "type": "boolean"
              },
              "external_ref": {
                "description": "Your latest reference for this candidate — not for routing (API reads)",
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "id",
              "full_name",
              "email",
              "phone",
              "anonymized"
            ]
          },
          "screen": {
            "type": "object",
            "properties": {
              "completed_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the screen finished"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "duration_seconds": {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "channel": {
                "type": "string",
                "enum": [
                  "voice",
                  "text"
                ]
              },
              "channel_reason": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "completed_at",
              "duration_seconds",
              "channel",
              "channel_reason"
            ]
          },
          "facts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "stated",
                    "not_stated",
                    "not_asked"
                  ]
                },
                "value": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "confidence": {
                  "anyOf": [
                    {
                      "type": "string",
                      "enum": [
                        "high",
                        "medium",
                        "low"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "evidence": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Evidence"
                  }
                }
              },
              "required": [
                "id",
                "label",
                "status",
                "value",
                "confidence",
                "evidence"
              ]
            }
          },
          "knockouts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "outcome": {
                  "type": "string",
                  "enum": [
                    "pass",
                    "fail",
                    "unclear"
                  ]
                },
                "quote": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "t": {
                  "anyOf": [
                    {
                      "type": "number"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "id",
                "label",
                "outcome",
                "quote",
                "t"
              ]
            }
          },
          "dimensions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "band": {
                  "anyOf": [
                    {
                      "type": "string",
                      "enum": [
                        "below_bar",
                        "meets",
                        "strong"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "evidence": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Evidence"
                  }
                }
              },
              "required": [
                "id",
                "label",
                "band",
                "evidence"
              ]
            }
          },
          "flags": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string"
                },
                "explanation": {
                  "type": "string"
                }
              },
              "required": [
                "kind",
                "explanation"
              ]
            }
          },
          "summary": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "verdict": {
                    "type": "string"
                  },
                  "strengths": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "concerns": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "suggested_follow_ups": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "verdict",
                  "strengths",
                  "concerns",
                  "suggested_follow_ups"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "decision": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string",
                    "enum": [
                      "advance",
                      "reject",
                      "hold"
                    ]
                  },
                  "note": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "decided_by": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "decided_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "description": "When a person decided"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "value",
                  "note",
                  "decided_by",
                  "decided_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Always a person's decision; null until one is recorded"
          },
          "submittal_note": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "draft",
                      "edited",
                      "approved"
                    ]
                  },
                  "text": {
                    "anyOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Present only once a member approved the note"
                  }
                },
                "required": [
                  "status",
                  "text"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "ats_note_text": {
            "type": "string",
            "description": "The Copy-for-ATS block in plain text"
          },
          "verification": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "verified",
                  "skipped"
                ]
              }
            },
            "required": [
              "status"
            ]
          },
          "billable": {
            "type": "boolean"
          },
          "invite": {
            "description": "The invite this report came from (API reads)",
            "$ref": "#/components/schemas/InviteRef"
          },
          "score_summary": {
            "description": "Band counts and failed knock-outs (API reads)",
            "$ref": "#/components/schemas/ScoreSummary"
          },
          "livemode": {
            "description": "Present (false) only on a test key's answer",
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "report",
          "role",
          "candidate",
          "screen",
          "facts",
          "knockouts",
          "dimensions",
          "flags",
          "summary",
          "decision",
          "submittal_note",
          "ats_note_text",
          "verification",
          "billable"
        ]
      },
      "Role": {
        "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}|role_test_[0-9a-f]{24})$",
            "description": "Role id: a uuid, or `role_test_…` in test mode"
          },
          "title": {
            "type": "string"
          },
          "client_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "active",
              "closed"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the role was created"
          },
          "counts": {
            "type": "object",
            "properties": {
              "invited": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "completed": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "needs_decision": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "invited",
              "completed",
              "needs_decision"
            ]
          },
          "external_ref": {
            "description": "Your own reference for the role, if you set one",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "guide_status": {
            "description": "`drafting` (guide being written), `pending_approval`, `approved`, `failed` (research failed), or `not_requested` (the guide was never requested)",
            "type": "string",
            "enum": [
              "not_requested",
              "drafting",
              "pending_approval",
              "approved",
              "failed"
            ]
          },
          "open_link": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RoleOpenLink"
              },
              {
                "type": "null"
              }
            ]
          },
          "dashboard_url": {
            "description": "The role in the Recruit100x dashboard (absent for a test role)",
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "id",
          "title",
          "client_label",
          "status",
          "created_at",
          "counts"
        ]
      },
      "RoleCreateRequest": {
        "type": "object",
        "properties": {
          "title": {
            "description": "Read from the job description when omitted",
            "type": "string"
          },
          "jd": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "const": "paste"
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "mode",
                  "text"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "const": "url"
                  },
                  "url": {
                    "type": "string",
                    "pattern": "^https?:\\/\\/",
                    "format": "uri"
                  }
                },
                "required": [
                  "mode",
                  "url"
                ]
              }
            ]
          },
          "client_label": {
            "description": "Shown to candidates; omit to keep the client confidential",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "location": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "country": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 2,
                    "description": "ISO 3166-1 alpha-2; EU/EEA and countries outside the allowed list are refused"
                  },
                  "note": {
                    "type": "string"
                  }
                },
                "required": [
                  "country"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "comp_range": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "min": {
                    "type": "number",
                    "minimum": 0
                  },
                  "max": {
                    "type": "number",
                    "minimum": 0
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Za-z]{3}$",
                    "description": "ISO 4217"
                  },
                  "period": {
                    "type": "string",
                    "enum": [
                      "year",
                      "month",
                      "hour"
                    ]
                  }
                },
                "required": [
                  "min",
                  "max",
                  "currency",
                  "period"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "must_haves": {
            "maxItems": 8,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          "knockouts": {
            "type": "array",
            "items": {
              "type": "object",
              "propertyNames": {
                "type": "string"
              },
              "additionalProperties": {},
              "description": "A typed knock-out rule, the same kinds the dashboard offers (comp_ceiling, work_authorization, location, licensure, notice_ceiling)"
            }
          },
          "jurisdiction_preset": {
            "description": "`default` (or omitted) = your workspace's preset",
            "type": "string",
            "enum": [
              "default",
              "us_base",
              "nyc",
              "il",
              "ca",
              "co",
              "md",
              "international"
            ]
          },
          "invite_expiry_days": {
            "type": "integer",
            "minimum": 3,
            "maximum": 30
          },
          "open_link": {
            "description": "Omitted: your workspace's default policy. If you apply your own eligibility, send {\"policy\": \"invite_only\"}.",
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "policy": {
                    "type": "string",
                    "enum": [
                      "open",
                      "applicants_only",
                      "invite_only"
                    ]
                  },
                  "cap": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the link closes (future)"
                  }
                },
                "required": [
                  "policy"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "external_ref": {
            "description": "Your own id for the role",
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ]
          },
          "auto_approve": {
            "description": "Auto-approve the guide if it passes every check — trusted workspaces with auto-approval on only",
            "type": "boolean"
          }
        },
        "required": [
          "jd"
        ]
      },
      "RoleCreatedResponse": {
        "type": "object",
        "properties": {
          "role": {
            "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}|role_test_[0-9a-f]{24})$",
                "description": "Role id: a uuid, or `role_test_…` in test mode"
              },
              "title": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": [
                  "draft",
                  "active",
                  "closed"
                ]
              },
              "guide_status": {
                "type": "string",
                "enum": [
                  "not_requested",
                  "drafting",
                  "pending_approval",
                  "approved",
                  "failed"
                ]
              },
              "external_ref": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "open_link": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/RoleOpenLink"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "dashboard_url": {
                "description": "The role in the Recruit100x dashboard (absent for a test role)",
                "type": "string",
                "format": "uri"
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the role was created"
              }
            },
            "required": [
              "id",
              "title",
              "status",
              "guide_status",
              "external_ref",
              "open_link",
              "created_at"
            ]
          },
          "livemode": {
            "type": "boolean",
            "description": "false for a test key's answer (test mode)"
          }
        },
        "required": [
          "role",
          "livemode"
        ]
      },
      "RoleListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Role"
            }
          },
          "livemode": {
            "description": "Present (false) only on a test key's answer",
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "data"
        ]
      },
      "RoleOpenLink": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The public open screening link"
          },
          "policy": {
            "type": "string",
            "enum": [
              "open",
              "applicants_only",
              "invite_only",
              "off"
            ]
          },
          "cap": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Interviews this link may start"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "When the link stops accepting candidates"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "url",
          "policy",
          "cap",
          "expires_at"
        ]
      },
      "RolePatchRequest": {
        "type": "object",
        "properties": {
          "jd": {
            "description": "Only while the guide is not approved: the guide is drafted again",
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "const": "paste"
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "mode",
                  "text"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "const": "url"
                  },
                  "url": {
                    "type": "string",
                    "pattern": "^https?:\\/\\/",
                    "format": "uri"
                  }
                },
                "required": [
                  "mode",
                  "url"
                ]
              }
            ]
          },
          "title": {
            "description": "Only while the guide is not approved",
            "type": "string",
            "minLength": 1
          },
          "client_label": {
            "description": "Only while the guide is not approved",
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "closed"
            ]
          },
          "open_invites": {
            "description": "With status closed: `cancel` (default) stops unstarted invites; `keep` lets every live invite finish until it expires",
            "type": "string",
            "enum": [
              "cancel",
              "keep"
            ]
          },
          "open_link": {
            "description": "Creates the link when the role has none and a policy other than off is sent",
            "type": "object",
            "properties": {
              "policy": {
                "type": "string",
                "enum": [
                  "open",
                  "applicants_only",
                  "invite_only",
                  "off"
                ]
              },
              "cap": {
                "type": "integer",
                "minimum": 1,
                "maximum": 10000
              },
              "expires_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the link closes (future), or null to close it only with the role"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "regenerate": {
                "description": "A new link; the old one stops working at once",
                "type": "boolean"
              }
            }
          },
          "external_ref": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "RoleReportsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "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}|rep_test_[0-9a-f]{24})$",
                  "description": "Report id: a uuid, or `rep_test_…` in test mode"
                },
                "state": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "generating",
                    "ready",
                    "failed"
                  ]
                },
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When the report row was created"
                },
                "generated_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "description": "When the report became ready"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "completed_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "description": "When the screen finished"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "candidate": {
                  "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}|inv_test_[0-9a-f]{24})$",
                      "description": "Candidate id: a uuid, or `inv_test_…` in test mode"
                    },
                    "full_name": {
                      "type": "string"
                    },
                    "external_ref": {
                      "description": "Your latest reference for this candidate — not for routing (use the invite's)",
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "full_name"
                  ]
                },
                "decision": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "value": {
                          "type": "string",
                          "enum": [
                            "advance",
                            "reject",
                            "hold"
                          ]
                        },
                        "decided_at": {
                          "anyOf": [
                            {
                              "type": "string",
                              "format": "date-time",
                              "description": "When a person decided"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      },
                      "required": [
                        "value",
                        "decided_at"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "knockouts": {
                  "type": "object",
                  "properties": {
                    "pass": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "fail": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "unclear": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "pass",
                    "fail",
                    "unclear"
                  ]
                },
                "bands": {
                  "type": "object",
                  "properties": {
                    "strong": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "meets": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "below_bar": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "not_observed": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    }
                  },
                  "required": [
                    "strong",
                    "meets",
                    "below_bar",
                    "not_observed"
                  ]
                },
                "invite": {
                  "$ref": "#/components/schemas/InviteRef"
                },
                "score_summary": {
                  "$ref": "#/components/schemas/ScoreSummary"
                }
              },
              "required": [
                "id",
                "state",
                "url",
                "created_at",
                "generated_at",
                "completed_at",
                "candidate",
                "decision",
                "knockouts",
                "bands"
              ]
            }
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Pass as `cursor` for the next page; null on the last page"
          },
          "livemode": {
            "description": "Present (false) only on a test key's answer",
            "type": "boolean",
            "const": false
          }
        },
        "required": [
          "data",
          "next_cursor"
        ]
      },
      "RoleResponse": {
        "type": "object",
        "properties": {
          "role": {
            "$ref": "#/components/schemas/Role"
          },
          "livemode": {
            "type": "boolean",
            "description": "false for a test key's answer (test mode)"
          }
        },
        "required": [
          "role",
          "livemode"
        ]
      },
      "ScoreSummary": {
        "type": "object",
        "properties": {
          "bands": {
            "type": "object",
            "properties": {
              "strong": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "meets": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "below_bar": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "strong",
              "meets",
              "below_bar"
            ],
            "description": "Observed dimensions per band"
          },
          "knockouts_failed": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "bands",
          "knockouts_failed"
        ],
        "description": "Counts only — never a recommendation or a composite score"
      }
    }
  }
}
