{"components":{"responses":{},"schemas":{"User":{"description":"A user in the organization","example":{"deactivated_at":null,"departments":["Engineering"],"email":"john@example.com","employment_type":"full_time","first_name":"John","full_name":"John Doe","id":"7488a646-e31f-11e4-aace-600308960662","inserted_at":"2023-01-01T00:00:00Z","job_title":"Software Engineer","last_name":"Doe","location_city":"San Francisco","manager_user_id":null,"offboarding_scheduled_at":null,"onboarding_scheduled_at":null,"status":"active","teams":["Engineering","Backend"],"updated_at":"2023-01-01T00:00:00Z"},"properties":{"deactivated_at":{"description":"Deactivation timestamp","format":"date-time","nullable":true,"type":"string"},"departments":{"description":"Departments the user belongs to","items":{"type":"string"},"type":"array"},"email":{"description":"Email address","format":"email","type":"string"},"employment_type":{"description":"Employment type","enum":["full_time","part_time","contract","freelance","internship","apprenticeship","working_student","training"],"nullable":true,"type":"string"},"first_name":{"description":"First name","type":"string"},"full_name":{"description":"Full name (computed)","type":"string"},"id":{"description":"User ID","format":"uuid","type":"string"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"job_title":{"description":"Job title","nullable":true,"type":"string"},"last_name":{"description":"Last name","type":"string"},"location_city":{"description":"City location","nullable":true,"type":"string"},"manager_user_id":{"description":"Manager user ID","format":"uuid","nullable":true,"type":"string"},"offboarding_scheduled_at":{"description":"When the planned offboarding starts","format":"date-time","nullable":true,"type":"string"},"onboarding_scheduled_at":{"description":"When the planned onboarding starts provisioning","format":"date-time","nullable":true,"type":"string"},"status":{"description":"Current status","enum":["active","inactive","onboarding","onboarding_provisioning_planned","offboarding","offboarding_planned","offboarded"],"type":"string"},"teams":{"description":"Teams the user belongs to","items":{"type":"string"},"type":"array"},"updated_at":{"description":"Last update timestamp","format":"date-time","type":"string"}},"required":["id","first_name","last_name","email","status"],"title":"User","type":"object"},"ImportAccessStates":{"description":"The complete access list for one application. Any access not listed is removed.","example":{"access":[{"permissions":["Admin"],"resource":"Billing","user_email":"ana@example.com"}]},"properties":{"access":{"description":"One entry per user and resource","items":{"properties":{"permissions":{"description":"Permission titles held on the resource","items":{"type":"string"},"minItems":1,"type":"array"},"resource":{"description":"Resource title. May be omitted for an application with a single resource.","nullable":true,"type":"string"},"user_email":{"description":"Email of the user","type":"string"}},"required":["user_email","permissions"],"type":"object"},"type":"array"}},"required":["access"],"title":"ImportAccessStates","type":"object"},"PolicyList":{"description":"Paginated list of policies","properties":{"data":{"description":"List of policies","items":{"$ref":"#/components/schemas/Policy"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["data","meta"],"title":"PolicyList","type":"object"},"OffboardUser":{"description":"Request body for offboarding a user. Omit scheduled_at to offboard immediately; provide a future timestamp to schedule it. Calling again with a new value reschedules an existing planned offboarding.","example":{"scheduled_at":"2026-12-31T17:00:00Z"},"properties":{"scheduled_at":{"description":"When to offboard. Omitted or null offboards now; a future ISO 8601 timestamp schedules it.","format":"date-time","nullable":true,"type":"string"}},"title":"OffboardUser","type":"object"},"Policy":{"description":"A policy that gates access requests for a list of applications. When elevated, the policy applies only to elevated access requests; otherwise it applies to all access requests. Assign applications via PUT /policies/{id}/applications.","example":{"application_ids":["8599b757-f42a-22f5-bbdf-711419071781"],"approval_steps":[{"approver_types":["manager"],"specific_approver_user_ids":[],"step":1,"strategy":"first_to_respond"}],"default_policy":false,"elevated":false,"id":"7488a646-e31f-11e4-aace-600308960670","inserted_at":"2023-01-01T00:00:00Z","lock_version":1,"title":"Engineering manager approval","updated_at":"2023-01-01T00:00:00Z"},"properties":{"application_ids":{"description":"IDs of the applications this policy applies to","items":{"format":"uuid","type":"string"},"type":"array"},"approval_steps":{"description":"The approval path: the ordered steps a matching access request must pass. An empty list means the policy auto-approves (no approval needed).","items":{"properties":{"approver_types":{"description":"Role-based approvers for this step","items":{"enum":["manager","application_admin","business_owner"],"type":"string"},"type":"array"},"specific_approver_user_ids":{"description":"Specific users named as approvers for this step","items":{"format":"uuid","type":"string"},"type":"array"},"step":{"description":"1-based position of the step in the approval path","type":"integer"},"strategy":{"description":"How the step is satisfied: `first_to_respond` needs a single approval, `all` needs every approver to approve","enum":["first_to_respond","all"],"type":"string"}},"type":"object"},"type":"array"},"default_policy":{"description":"Whether this is the default policy","type":"boolean"},"elevated":{"description":"When true, the policy applies only to elevated access requests","type":"boolean"},"id":{"description":"Policy ID","format":"uuid","type":"string"},"inserted_at":{"format":"date-time","type":"string"},"lock_version":{"description":"Optimistic lock version","type":"integer"},"title":{"description":"Policy title","type":"string"},"updated_at":{"format":"date-time","type":"string"}},"required":["id","title","default_policy","elevated","approval_steps"],"title":"Policy","type":"object"},"PermissionInput":{"description":"Permission to upsert. Omit `id` to create a new permission. To delete an existing one, send it with its `id` and `delete: true`.","properties":{"delete":{"description":"Set to true to soft-delete this permission. Requires `id`.","type":"boolean"},"description":{"nullable":true,"type":"string"},"elevated":{"type":"boolean"},"id":{"description":"Permission ID. Omit (or supply a fresh UUID) to create.","format":"uuid","type":"string"},"requestable":{"type":"boolean"},"title":{"description":"Required when creating a permission.","type":"string"}},"title":"PermissionInput","type":"object"},"UpdateStructure":{"description":"Upsert resources and permissions for an application. This is a partial upsert, not a full overwrite: omitted items are left untouched. To remove an item, send it with its `id` and `delete: true` (this applies to both resources and their nested permissions).","properties":{"lock_version":{"description":"Optimistic lock version. Optional; if stale, returns 409.","type":"integer"},"resources":{"description":"Resources to upsert.","items":{"$ref":"#/components/schemas/ResourceInput"},"type":"array"}},"title":"UpdateStructure","type":"object"},"CreateAccessRequest":{"description":"Request body for creating an access request","example":{"permission_ids":["7488a646-e31f-11e4-aace-600308960664"],"request_reason":"Need access to complete Q4 reporting","resource_id":"7488a646-e31f-11e4-aace-600308960663"},"properties":{"permission_ids":{"description":"List of permission IDs to request","items":{"format":"uuid","type":"string"},"minItems":1,"type":"array"},"request_reason":{"description":"Reason for requesting access","maxLength":255,"type":"string"},"resource_id":{"description":"Resource ID to request access to","format":"uuid","type":"string"},"user_id":{"description":"User to request access for. Required when authenticating with an API token. With a user login, defaults to the authenticated user if omitted.","format":"uuid","type":"string"}},"required":["resource_id","permission_ids","request_reason"],"title":"CreateAccessRequest","type":"object"},"PaginationMeta":{"description":"Pagination metadata","example":{"page":1,"page_size":20,"total_count":100,"total_pages":5},"properties":{"page":{"description":"Current page number","type":"integer"},"page_size":{"description":"Items per page","type":"integer"},"total_count":{"description":"Total number of items","type":"integer"},"total_pages":{"description":"Total number of pages","type":"integer"}},"required":["page","page_size","total_count","total_pages"],"title":"PaginationMeta","type":"object"},"Error":{"description":"Standard error response","example":{"error":"not_found","message":"Resource not found"},"properties":{"error":{"description":"Error code","example":"not_found","type":"string"},"message":{"description":"Human-readable error message","example":"Resource not found","type":"string"}},"required":["error","message"],"title":"Error","type":"object"},"AccessImportResult":{"description":"Counts of the changes the import made","example":{"data":{"created":12,"deleted":5,"unchanged":40,"updated":3}},"properties":{"data":{"properties":{"created":{"type":"integer"},"deleted":{"type":"integer"},"unchanged":{"type":"integer"},"updated":{"type":"integer"}},"required":["created","updated","deleted","unchanged"],"type":"object"}},"required":["data"],"title":"AccessImportResult","type":"object"},"UnauthorizedError":{"additionalProperties":false,"description":"The bearer token is missing, malformed or not valid. Unlike other errors, this body carries no error code and no `message`.","example":{"error":"Invalid bearer token."},"properties":{"error":{"description":"Human-readable reason the token was refused","example":"Invalid bearer token.","type":"string"}},"required":["error"],"title":"UnauthorizedError","type":"object"},"AccessRequestList":{"description":"Paginated list of access requests","properties":{"data":{"description":"List of access requests","items":{"$ref":"#/components/schemas/AccessRequest"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["data","meta"],"title":"AccessRequestList","type":"object"},"RejectAccessRequest":{"description":"Request body for rejecting an access request","example":{"reason":"Unable to provision this access"},"properties":{"reason":{"description":"Reason for rejecting the request","maxLength":255,"type":"string"}},"required":["reason"],"title":"RejectAccessRequest","type":"object"},"CreateUser":{"description":"Request body for creating a new user. The org-info fields are set on the new user. Does not onboard — call POST /users/{user_id}/onboard afterwards, or create and onboard in one step with POST /users/onboard.","example":{"departments":["Engineering"],"email":"john@example.com","employment_type":"full_time","first_name":"John","job_title":"Software Engineer","last_name":"Doe","manager_user_id":"7488a646-e31f-11e4-aace-600308960663"},"properties":{"departments":{"description":"Departments the user belongs to","items":{"type":"string"},"type":"array"},"email":{"description":"Email address","format":"email","type":"string"},"employment_type":{"description":"Employment type","enum":["full_time","part_time","contract","freelance","internship","apprenticeship","working_student","training"],"nullable":true,"type":"string"},"first_name":{"description":"First name","type":"string"},"job_title":{"description":"Job title","nullable":true,"type":"string"},"last_name":{"description":"Last name","type":"string"},"location_city":{"description":"City location","nullable":true,"type":"string"},"manager_user_id":{"description":"Manager (user)","format":"uuid","nullable":true,"type":"string"},"teams":{"description":"Teams the user belongs to","items":{"type":"string"},"type":"array"}},"required":["first_name","last_name","email"],"title":"CreateUser","type":"object"},"ServerError":{"additionalProperties":false,"description":"The request could not be carried out","example":{"error":"internal_server_error","message":":pending_access_request_exists"},"properties":{"error":{"enum":["internal_server_error"],"type":"string"},"message":{"description":"Internal reason code","example":":pending_access_request_exists","type":"string"}},"required":["error","message"],"title":"ServerError","type":"object"},"CreateAccessRevocation":{"description":"Request body for creating an access revocation from an access state","example":{"access_state_id":"7488a646-e31f-11e4-aace-600308960663","reason":"Role no longer requires this access"},"properties":{"access_state_id":{"description":"Access state ID identifying the access to revoke","format":"uuid","type":"string"},"reason":{"description":"Reason for the revocation","maxLength":255,"type":"string"}},"required":["access_state_id","reason"],"title":"CreateAccessRevocation","type":"object"},"SetApplications":{"description":"Replaces a policy's complete application list. `application_ids` fully replace the policy's applications (empty list clears them).","example":{"application_ids":["7488a646-e31f-11e4-aace-600308960670"],"elevated":false},"properties":{"application_ids":{"description":"The complete set of application IDs for this policy.","items":{"format":"uuid","type":"string"},"type":"array"},"elevated":{"default":false,"description":"When true, the policy applies only to elevated access requests.","type":"boolean"}},"required":["application_ids"],"title":"SetApplications","type":"object"},"AccessRequest":{"description":"An access request","example":{"application_id":"7488a646-e31f-11e4-aace-600308960662","approval_steps":[{"approvers":[{"decided_at":"2023-01-15T11:00:00Z","decided_by_user_id":"9488a646-e31f-11e4-aace-600308960667","status":"approved","user_id":"9488a646-e31f-11e4-aace-600308960667"}],"decided_at":"2023-01-15T11:00:00Z","status":"approved","step":1,"strategy":"all"},{"approvers":[{"decided_at":null,"decided_by_user_id":null,"status":"pending","user_id":"9488a646-e31f-11e4-aace-600308960668"},{"decided_at":null,"decided_by_user_id":null,"status":"pending","user_id":"9488a646-e31f-11e4-aace-600308960669"}],"decided_at":null,"status":"pending","step":2,"strategy":"first_to_respond"},{"approvers":[{"decided_at":null,"decided_by_user_id":null,"status":"pending","user_id":"9488a646-e31f-11e4-aace-60030896066a"}],"decided_at":null,"status":"pending","step":3,"strategy":"all"}],"duration":"PT1H","expires_at":"2023-01-16T10:30:00Z","grantee_user_id":"9488a646-e31f-11e4-aace-600308960666","id":"8488a646-e31f-11e4-aace-600308960665","inserted_at":"2023-01-15T10:30:00Z","permission_ids":["7488a646-e31f-11e4-aace-600308960664"],"provisioning_type":"automatic","request_reason":"Need access to complete Q4 reporting","requestor_user_id":"9488a646-e31f-11e4-aace-600308960666","resource_id":"7488a646-e31f-11e4-aace-600308960663","status":"pending_approval","termination_reason":null},"properties":{"application_id":{"description":"Application ID","format":"uuid","type":"string"},"approval_steps":{"description":"The ordered approval steps with their approvers and decisions. Empty for auto-approved requests.","items":{"$ref":"#/components/schemas/ApprovalStep"},"type":"array"},"duration":{"description":"Duration of time-based access as an ISO 8601 duration (e.g. \"PT1H\", \"P7D\"); null for permanent access","nullable":true,"type":"string"},"expires_at":{"description":"When the time-based access expires; null for permanent access or a time-based request that has not been granted yet","format":"date-time","nullable":true,"type":"string"},"grantee_user_id":{"description":"User ID of the grantee","format":"uuid","type":"string"},"id":{"description":"Access request ID","format":"uuid","type":"string"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"permission_ids":{"description":"Requested permission IDs","items":{"format":"uuid","type":"string"},"type":"array"},"provisioning_type":{"description":"Provisioning type","enum":["application_admin","automatic"],"nullable":true,"type":"string"},"request_reason":{"description":"Request reason","type":"string"},"requestor_user_id":{"description":"User ID of the requestor","format":"uuid","type":"string"},"resource_id":{"description":"Resource ID","format":"uuid","type":"string"},"status":{"description":"Current status of the access request","enum":["pending_approval","pending_permissions_assignment","access_granted","denied","rejected","processing_access","scheduled","pending_dependency"],"type":"string"},"termination_reason":{"description":"Reason the request was ended: the denial reason when denied, the provisioner's rejection reason when rejected; null otherwise. The status field says which kind it was.","nullable":true,"type":"string"}},"required":["id","resource_id","application_id","permission_ids","request_reason","status"],"title":"AccessRequest","type":"object"},"BulkAccessRequestItem":{"description":"A single item in a bulk access request","example":{"permission_ids":["7488a646-e31f-11e4-aace-600308960664"],"resource_id":"7488a646-e31f-11e4-aace-600308960663"},"properties":{"permission_ids":{"description":"List of permission IDs to request","items":{"format":"uuid","type":"string"},"minItems":1,"type":"array"},"resource_id":{"description":"Resource ID to request access to","format":"uuid","type":"string"}},"required":["resource_id","permission_ids"],"title":"BulkAccessRequestItem","type":"object"},"ApprovalStepApprover":{"description":"An approver on one approval step","properties":{"decided_at":{"description":"When this approver approved or denied; null while pending or skipped","format":"date-time","nullable":true,"type":"string"},"decided_by_user_id":{"description":"User ID of the person who recorded the decision — the approver themselves, or the user who approved or denied on their behalf; null while the approver hasn't decided","format":"uuid","nullable":true,"type":"string"},"status":{"description":"Whether this approver approved, denied, is still pending, or was skipped (the step or request was decided without them)","enum":["pending","approved","denied","skipped"],"type":"string"},"user_id":{"description":"User ID of the approver","format":"uuid","type":"string"}},"required":["user_id","status"],"title":"ApprovalStepApprover","type":"object"},"AccessRevocationList":{"description":"Paginated list of access revocations","properties":{"data":{"description":"List of access revocations","items":{"$ref":"#/components/schemas/AccessRevocation"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["data","meta"],"title":"AccessRevocationList","type":"object"},"ApproveAccessRequest":{"description":"Request body for approving an access request","example":{"on_behalf_of_user_id":"7488a646-e31f-11e4-aace-600308960663"},"properties":{"on_behalf_of_user_id":{"description":"The approver (user) to approve on behalf of, recording the acting user as deputy. Required when authenticating with an API token; otherwise omit it to approve as the acting user.","format":"uuid","type":"string"}},"title":"ApproveAccessRequest","type":"object"},"DenyAccessRequest":{"description":"Request body for denying an access request","example":{"on_behalf_of_user_id":"7488a646-e31f-11e4-aace-600308960663","reason":"Access is not warranted for this role"},"properties":{"on_behalf_of_user_id":{"description":"The approver (user) to deny on behalf of, recording the acting token user as deputy. Required unless the acting user is themselves a current approver.","format":"uuid","type":"string"},"reason":{"description":"Reason for denying the request","maxLength":255,"type":"string"}},"required":["reason"],"title":"DenyAccessRequest","type":"object"},"OnboardUser":{"description":"Request body for onboarding a user via the Zero-Touch (access-template) flow. Omit scheduled_at to provision now; provide a future timestamp to defer provisioning to that date.","example":{"scheduled_at":"2026-12-31T09:00:00Z"},"properties":{"scheduled_at":{"description":"When to provision access. Omitted or null provisions now; a future ISO 8601 timestamp defers it. For a user already onboarding, this reschedules the planned provisioning.","format":"date-time","nullable":true,"type":"string"}},"title":"OnboardUser","type":"object"},"ApprovalStep":{"description":"A single approval step","properties":{"approvers":{"description":"The approvers resolved for this step","items":{"$ref":"#/components/schemas/ApprovalStepApprover"},"type":"array"},"decided_at":{"description":"When the step was decided; null while pending or skipped","format":"date-time","nullable":true,"type":"string"},"status":{"description":"State of the step: pending (current or upcoming), approved, denied, or skipped (a prior step's denial ended the request)","enum":["pending","approved","denied","skipped"],"type":"string"},"step":{"description":"1-based position of the step","type":"integer"},"strategy":{"description":"How many approvers must approve the step: any single one (first_to_respond) or every one (all)","enum":["first_to_respond","all"],"type":"string"}},"required":["step","strategy","status","approvers"],"title":"ApprovalStep","type":"object"},"ValidationError":{"additionalProperties":false,"description":"The request is well-formed but cannot be carried out","example":{"error":"validation_failed","errors":{"status":["access request was already granted"]},"message":"The request contains invalid data"},"properties":{"detail":{"description":"Present on `idempotency_key_params_mismatch`","type":"string"},"error":{"description":"`validation_failed` for invalid data or a record in the wrong state; `validation_error` (without `errors`) when a bulk access request has a blank `request_reason`; `idempotency_key_params_mismatch` when the `Idempotency-Key` was already used with a different body","example":"validation_failed","type":"string"},"errors":{"additionalProperties":{"items":{"oneOf":[{"type":"string"},{"type":"object"}]},"type":"array"},"description":"Reasons, keyed by field. For a field that is a list (such as `access` rows), the entry holds one object per list item, keyed the same way and empty for a valid item. Present on `validation_failed`.","type":"object"},"message":{"example":"The request contains invalid data","type":"string"}},"required":["error","message"],"title":"ValidationError","type":"object"},"ConflictError":{"additionalProperties":false,"description":"The request conflicts with an earlier request or a concurrent change","example":{"error":"idempotency_key_already_used","message":"This idempotency key has already been used"},"properties":{"error":{"description":"`idempotency_key_already_used` when the `Idempotency-Key` was already used for this request; `conflict` when the record was changed concurrently or the `lock_version` is stale","enum":["idempotency_key_already_used","conflict"],"type":"string"},"message":{"example":"This idempotency key has already been used","type":"string"}},"required":["error","message"],"title":"ConflictError","type":"object"},"UpdateApplication":{"description":"Request body for updating an application's scalar fields. Reject keys: resources, permissions, policy_ids.","properties":{"admin_user_ids":{"description":"User IDs of the application's admins. Send [] to clear; unknown IDs return 422.","items":{"format":"uuid","type":"string"},"type":"array"},"auth_method":{"description":"Authentication method used to sign in","enum":["google","microsoft","okta","sso_provider","credentials","other"],"nullable":true,"type":"string"},"data_location":{"description":"Where the vendor stores data","nullable":true,"type":"string"},"description":{"nullable":true,"type":"string"},"last_vendor_review_at":{"description":"Date of the last vendor security review","format":"date","nullable":true,"type":"string"},"lock_version":{"description":"Optimistic lock version. Optional; if stale, returns 409.","type":"integer"},"mfa_activated":{"description":"Whether MFA is activated for this application","nullable":true,"type":"boolean"},"notes":{"description":"Internal notes","nullable":true,"type":"string"},"owner_user_id":{"format":"uuid","nullable":true,"type":"string"},"processed_data_types":{"description":"Data-processing-scope slugs. Send [] to clear; unknown slugs return 422.","items":{"enum":["customer_metadata","customer_pii","company_metadata","company_sensitive_data","employee_pii","employee_sensitive_data","ephi"],"type":"string"},"type":"array"},"risk_level":{"enum":["low","medium","high"],"nullable":true,"type":"string"},"status":{"description":"Needs a set owner for \"approved\" and \"requestable\"","enum":["ignored","approved","requestable"],"type":"string"},"tags":{"description":"Tag titles. New titles are created automatically; send [] to clear.","items":{"type":"string"},"type":"array"},"title":{"type":"string"},"url":{"nullable":true,"type":"string"},"user_setup_url":{"description":"URL where existing users are shown and new users are invited","nullable":true,"type":"string"},"vendor_certificates":{"description":"Security/compliance certifications held by the vendor","items":{"enum":["iso_22301","iso_27001","iso_27017","iso_27701","iso_31000","iso_42001","soc1","soc2_t1","soc2_t2","soc3","pci_dss","nist_csf","fed_ramp","hipaa","hitrust_csf","gdpr","csa_star","fsd_safe"],"type":"string"},"type":"array"}},"title":"UpdateApplication","type":"object"},"ApplicationList":{"description":"Paginated list of applications","properties":{"data":{"description":"List of applications","items":{"$ref":"#/components/schemas/Application"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["data","meta"],"title":"ApplicationList","type":"object"},"AccessStateList":{"description":"Paginated list of access states","properties":{"data":{"description":"List of access states","items":{"$ref":"#/components/schemas/AccessState"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["data","meta"],"title":"AccessStateList","type":"object"},"CreateBulkAccessRequest":{"description":"Request body for creating multiple access requests","example":{"request_reason":"Need access to complete Q4 reporting","requests":[{"permission_ids":["7488a646-e31f-11e4-aace-600308960664"],"resource_id":"7488a646-e31f-11e4-aace-600308960663"},{"permission_ids":["7488a646-e31f-11e4-aace-600308960666"],"resource_id":"7488a646-e31f-11e4-aace-600308960665"}]},"properties":{"request_reason":{"description":"Shared reason for all access requests","maxLength":255,"type":"string"},"requests":{"description":"List of access requests to create (max 10)","items":{"$ref":"#/components/schemas/BulkAccessRequestItem"},"maxItems":10,"minItems":1,"type":"array"},"user_id":{"description":"User to request access for. Required when authenticating with an API token. With a user login, defaults to the authenticated user if omitted.","format":"uuid","type":"string"}},"required":["requests","request_reason"],"title":"CreateBulkAccessRequest","type":"object"},"BulkAccessRequestResponse":{"description":"Response containing created access requests","properties":{"data":{"description":"List of created access requests","items":{"$ref":"#/components/schemas/AccessRequest"},"type":"array"}},"required":["data"],"title":"BulkAccessRequestResponse","type":"object"},"ResourceInput":{"description":"Resource to upsert. Omit `id` to create a new resource. To delete an existing one, send it with its `id` and `delete: true`.","properties":{"delete":{"description":"Set to true to soft-delete this resource. Requires `id`.","type":"boolean"},"description":{"nullable":true,"type":"string"},"id":{"description":"Resource ID. Omit to let the server generate one. Provide a client-generated UUID to forward-reference this resource as a `parent_resource_id` of another item in the same payload.","format":"uuid","type":"string"},"order":{"nullable":true,"type":"integer"},"parent_resource_id":{"description":"Optional parent resource ID for nested groups.","format":"uuid","nullable":true,"type":"string"},"permissions":{"description":"Permissions nested under this resource.","items":{"$ref":"#/components/schemas/PermissionInput"},"type":"array"},"requestable":{"type":"boolean"},"title":{"description":"Required when creating a resource.","type":"string"}},"title":"ResourceInput","type":"object"},"ForbiddenError":{"additionalProperties":false,"description":"The API token's scopes or the user's role do not allow this action on this record","example":{"error":"forbidden","message":"Access denied"},"properties":{"error":{"enum":["forbidden"],"type":"string"},"message":{"example":"Access denied","type":"string"}},"required":["error","message"],"title":"ForbiddenError","type":"object"},"CreateApplication":{"description":"Request body for creating an application","properties":{"admin_user_ids":{"description":"User IDs of the application's admins. Send [] to clear; unknown IDs return 422.","items":{"format":"uuid","type":"string"},"type":"array"},"auth_method":{"description":"Authentication method used to sign in","enum":["google","microsoft","okta","sso_provider","credentials","other"],"nullable":true,"type":"string"},"data_location":{"description":"Where the vendor stores data","nullable":true,"type":"string"},"description":{"nullable":true,"type":"string"},"last_vendor_review_at":{"description":"Date of the last vendor security review","format":"date","nullable":true,"type":"string"},"mfa_activated":{"description":"Whether MFA is activated for this application","nullable":true,"type":"boolean"},"notes":{"description":"Internal notes","nullable":true,"type":"string"},"owner_user_id":{"description":"Required when status is \"approved\" or \"requestable\"","format":"uuid","type":"string"},"processed_data_types":{"description":"Data-processing-scope slugs. Send [] to clear; unknown slugs return 422.","items":{"enum":["customer_metadata","customer_pii","company_metadata","company_sensitive_data","employee_pii","employee_sensitive_data","ephi"],"type":"string"},"type":"array"},"resources":{"description":"Initial resources with permissions. Required for status=\"requestable\".","items":{"properties":{"description":{"nullable":true,"type":"string"},"permissions":{"items":{"properties":{"description":{"nullable":true,"type":"string"},"elevated":{"type":"boolean"},"requestable":{"type":"boolean"},"title":{"type":"string"}},"required":["title"],"type":"object"},"type":"array"},"requestable":{"type":"boolean"},"title":{"type":"string"}},"required":["title"],"type":"object"},"type":"array"},"risk_level":{"enum":["low","medium","high"],"nullable":true,"type":"string"},"status":{"description":"Defaults to \"requestable\"","enum":["ignored","approved","requestable"],"type":"string"},"tags":{"description":"Tag titles. New titles are created automatically; send [] to clear.","items":{"type":"string"},"type":"array"},"title":{"description":"Application title (required)","type":"string"},"url":{"nullable":true,"type":"string"},"user_setup_url":{"description":"URL where existing users are shown and new users are invited","nullable":true,"type":"string"},"vendor_certificates":{"description":"Security/compliance certifications held by the vendor","items":{"enum":["iso_22301","iso_27001","iso_27017","iso_27701","iso_31000","iso_42001","soc1","soc2_t1","soc2_t2","soc3","pci_dss","nist_csf","fed_ramp","hipaa","hitrust_csf","gdpr","csa_star","fsd_safe"],"type":"string"},"type":"array"}},"required":["title"],"title":"CreateApplication","type":"object"},"RateLimitError":{"additionalProperties":false,"description":"More than 1000 requests in an hour were made with this token","example":{"error":"rate_limit_exceeded","message":"Too many requests. Please retry after 1200 seconds."},"properties":{"error":{"enum":["rate_limit_exceeded"],"type":"string"},"message":{"example":"Too many requests. Please retry after 1200 seconds.","type":"string"}},"required":["error","message"],"title":"RateLimitError","type":"object"},"Resource":{"description":"A resource (grouping of permissions) within an application","example":{"application_id":"7488a646-e31f-11e4-aace-600308960662","description":"Main workspace access","id":"7488a646-e31f-11e4-aace-600308960663","multiple_permissions_selectable":false,"parent_resource_id":null,"permissions":[{"elevated":false,"id":"7488a646-e31f-11e4-aace-600308960664","requestable":true,"title":"Member"}],"requestable":true,"title":"Workspace","type":"resource"},"properties":{"application_id":{"description":"Application ID","format":"uuid","type":"string"},"description":{"description":"Description","nullable":true,"type":"string"},"id":{"description":"Resource ID","format":"uuid","type":"string"},"multiple_permissions_selectable":{"description":"Whether multiple permissions can be selected when requesting this resource","type":"boolean"},"parent_resource_id":{"description":"Parent resource ID for nested resources","format":"uuid","nullable":true,"type":"string"},"permissions":{"description":"Permissions within this resource (when loaded)","items":{"$ref":"#/components/schemas/Permission"},"type":"array"},"requestable":{"description":"Whether it can be requested","type":"boolean"},"title":{"description":"Resource title","type":"string"},"type":{"description":"Resource type","enum":["resource","group"],"nullable":true,"type":"string"}},"required":["id","title","requestable","application_id"],"title":"Resource","type":"object"},"Application":{"description":"An application in the organization","example":{"admin_user_ids":["7488a646-e31f-11e4-aace-600308960665"],"auth_method":"okta","contract":{"annual_costs":"12000.00","currency":"EUR","end_date":"2026-12-31","interval":"annually","renewal_date":"2026-12-31","start_date":"2025-01-01"},"data_location":"EU","description":"Team communication platform","id":"7488a646-e31f-11e4-aace-600308960662","inserted_at":"2023-01-01T00:00:00Z","last_vendor_review_at":"2026-01-15","mfa_activated":true,"notes":"Reviewed in Q4","owner_user_id":"7488a646-e31f-11e4-aace-600308960663","permanent_access_allowed":true,"processed_data_types":["customer_data"],"provisioning_type":"automatic","risk_level":"medium","status":"requestable","tags":[{"id":"7488a646-e31f-11e4-aace-600308960666","title":"Communication"}],"time_based_access_durations":["PT1H","P7D"],"title":"Slack","updated_at":"2023-01-01T00:00:00Z","url":"https://slack.com","user_count":150,"user_setup_url":"https://slack.com/get-started","vendor_certificates":["soc2_t2","iso_27001"]},"properties":{"admin_user_ids":{"description":"User IDs of the application's admins","items":{"format":"uuid","type":"string"},"type":"array"},"auth_method":{"description":"Authentication method used to sign in","enum":["google","microsoft","okta","sso_provider","credentials","other"],"nullable":true,"type":"string"},"contract":{"description":"Contract spend and renewal information; null when the application has no contract","nullable":true,"properties":{"annual_costs":{"description":"Annualized total spend, regardless of billing cycle","nullable":true,"type":"string"},"currency":{"description":"ISO 4217 currency code","type":"string"},"end_date":{"description":"Contract end date","format":"date","nullable":true,"type":"string"},"interval":{"description":"Billing cycle","enum":["annually","semi_annually","quarterly","monthly"],"type":"string"},"renewal_date":{"description":"Next renewal date","format":"date","nullable":true,"type":"string"},"start_date":{"description":"Contract start date","format":"date","nullable":true,"type":"string"}},"type":"object"},"data_location":{"description":"Where the vendor stores data","nullable":true,"type":"string"},"description":{"description":"Description","nullable":true,"type":"string"},"id":{"description":"Application ID","format":"uuid","type":"string"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"last_vendor_review_at":{"description":"Date of the last vendor security review","format":"date","nullable":true,"type":"string"},"mfa_activated":{"description":"Whether MFA is activated for this application","nullable":true,"type":"boolean"},"notes":{"description":"Internal notes","nullable":true,"type":"string"},"owner_user_id":{"description":"Owner user ID","format":"uuid","nullable":true,"type":"string"},"permanent_access_allowed":{"description":"Whether the application allows permanent (non-expiring) access","type":"boolean"},"processed_data_types":{"description":"Types of data this application processes","items":{"enum":["customer_metadata","customer_pii","company_metadata","company_sensitive_data","employee_pii","employee_sensitive_data","ephi"],"type":"string"},"type":"array"},"provisioning_type":{"description":"Provisioning type","enum":["application_admin","automatic"],"type":"string"},"risk_level":{"description":"Risk level assessment","enum":["low","medium","high"],"nullable":true,"type":"string"},"status":{"description":"Application status","enum":["ignored","discovered","approved","requestable"],"type":"string"},"tags":{"description":"Tags assigned to this application","items":{"properties":{"id":{"format":"uuid","type":"string"},"title":{"type":"string"}},"type":"object"},"type":"array"},"time_based_access_durations":{"description":"Configured time-based access durations as ISO 8601 durations (e.g. \"PT1H\", \"P7D\"); empty when the app offers only permanent access","items":{"type":"string"},"type":"array"},"title":{"description":"Application title","type":"string"},"updated_at":{"description":"Last update timestamp","format":"date-time","type":"string"},"url":{"description":"Application URL","nullable":true,"type":"string"},"user_count":{"description":"Number of users with access","nullable":true,"type":"integer"},"user_setup_url":{"description":"URL where existing users are shown and new users are invited","nullable":true,"type":"string"},"vendor_certificates":{"description":"Security/compliance certifications held by the vendor","items":{"enum":["iso_22301","iso_27001","iso_27017","iso_27701","iso_31000","iso_42001","soc1","soc2_t1","soc2_t2","soc3","pci_dss","nist_csf","fed_ramp","hipaa","hitrust_csf","gdpr","csa_star","fsd_safe"],"type":"string"},"type":"array"}},"required":["id","title","status"],"title":"Application","type":"object"},"ResourceList":{"description":"List of resources for an application","properties":{"data":{"description":"List of resources","items":{"$ref":"#/components/schemas/Resource"},"type":"array"}},"required":["data"],"title":"ResourceList","type":"object"},"Permission":{"description":"A permission within a resource","example":{"description":"Administrator access","elevated":true,"id":"7488a646-e31f-11e4-aace-600308960664","requestable":true,"resource_id":"7488a646-e31f-11e4-aace-600308960663","title":"Admin"},"properties":{"description":{"description":"Description","nullable":true,"type":"string"},"elevated":{"description":"Whether it's an elevated/admin access","type":"boolean"},"id":{"description":"Permission ID","format":"uuid","type":"string"},"requestable":{"description":"Whether it can be requested","type":"boolean"},"resource_id":{"description":"Parent resource ID","format":"uuid","type":"string"},"title":{"description":"Permission title","type":"string"}},"required":["id","title","requestable","elevated","resource_id"],"title":"Permission","type":"object"},"UpdateUser":{"description":"Request body for updating a user. Omitted fields stay untouched; null clears a field. For a user managed by an HRIS directory integration, name and org-info fields are refused and a manager change requires manager_override.","example":{"job_title":"Senior Software Engineer","manager_user_id":"7488a646-e31f-11e4-aace-600308960663","teams":["Engineering","Backend"]},"properties":{"departments":{"description":"Departments the user belongs to","items":{"type":"string"},"type":"array"},"employment_type":{"description":"Employment type","enum":["full_time","part_time","contract","freelance","internship","apprenticeship","working_student","training"],"nullable":true,"type":"string"},"first_name":{"description":"First name","type":"string"},"job_title":{"description":"Job title","nullable":true,"type":"string"},"last_name":{"description":"Last name","type":"string"},"location_city":{"description":"City location","nullable":true,"type":"string"},"manager_override":{"description":"Only relevant for a user managed by an HRIS directory integration. true is required to change the manager and stops the directory sync from changing it; false hands the manager back to the directory.","type":"boolean"},"manager_user_id":{"description":"Manager user ID. The user's own ID marks them as an executive, who reports to no one.","format":"uuid","nullable":true,"type":"string"},"teams":{"description":"Teams the user belongs to","items":{"type":"string"},"type":"array"}},"title":"UpdateUser","type":"object"},"CreateAndOnboardUser":{"description":"Request body for creating a new user and onboarding them via the Zero-Touch (access-template) flow in one step. The org-info fields are set on the new user so the template rules can match. Omit scheduled_at to provision now; provide a future timestamp to defer provisioning to that date.","example":{"departments":["Engineering"],"email":"john@example.com","first_name":"John","job_title":"Software Engineer","last_name":"Doe","manager_user_id":"7488a646-e31f-11e4-aace-600308960663","scheduled_at":"2026-12-31T09:00:00Z"},"properties":{"departments":{"description":"Departments the user belongs to","items":{"type":"string"},"type":"array"},"email":{"description":"Email address","format":"email","type":"string"},"employment_type":{"description":"Employment type","enum":["full_time","part_time","contract","freelance","internship","apprenticeship","working_student","training"],"nullable":true,"type":"string"},"first_name":{"description":"First name","type":"string"},"job_title":{"description":"Job title","nullable":true,"type":"string"},"last_name":{"description":"Last name","type":"string"},"location_city":{"description":"City location","nullable":true,"type":"string"},"manager_user_id":{"description":"Manager (user)","format":"uuid","nullable":false,"type":"string"},"scheduled_at":{"description":"When to provision access. Omitted or null provisions now; a future ISO 8601 timestamp defers it.","format":"date-time","nullable":true,"type":"string"},"teams":{"description":"Teams the user belongs to","items":{"type":"string"},"type":"array"}},"required":["first_name","last_name","email","manager_user_id"],"title":"CreateAndOnboardUser","type":"object"},"UserList":{"description":"Paginated list of users","properties":{"data":{"description":"List of users","items":{"$ref":"#/components/schemas/User"},"type":"array"},"meta":{"$ref":"#/components/schemas/PaginationMeta"}},"required":["data","meta"],"title":"UserList","type":"object"},"AccessState":{"description":"A current or historical access state","properties":{"application":{"description":"The application. Only present when requested via `expand=application`. Carries the application's own top-level fields only.","nullable":true,"properties":{"description":{"nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"owner_user_id":{"format":"uuid","nullable":true,"type":"string"},"provisioning_type":{"nullable":true,"type":"string"},"risk_level":{"nullable":true,"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"url":{"nullable":true,"type":"string"}},"type":"object"},"application_id":{"description":"Application ID","format":"uuid","type":"string"},"effective_end":{"description":"When the access ended (null if still effective)","format":"date-time","nullable":true,"type":"string"},"effective_start":{"description":"When the access became effective","format":"date-time","type":"string"},"grantee_user":{"allOf":[{"$ref":"#/components/schemas/User"}],"description":"The grantee user. Only present when requested via `expand=grantee_user`; null if the grantee is not linked to a user.","nullable":true},"grantee_user_account_id":{"description":"Grantee user account ID (the user's account within the app)","format":"uuid","type":"string"},"grantee_user_id":{"description":"User ID of the grantee","format":"uuid","type":"string"},"group_id":{"description":"Group ID (set when access is granted via a group)","format":"uuid","nullable":true,"type":"string"},"id":{"description":"Access state ID","format":"uuid","type":"string"},"identifier":{"description":"Human-readable identifier of the grantee's account within the application — for example an email address (Slack), a username, or an ARN (AWS). This value is volatile: it is chosen per integration and can change over time (e.g. when the person's email changes), so it is not a stable key — use `grantee_user_account_id` or `grantee_user_id` for stable references.\n","nullable":true,"type":"string"},"resource":{"description":"The resource. Only present when requested via `expand=resource`; null for app-wide access. Carries the resource's own top-level fields only (no nested permissions).","nullable":true,"properties":{"application_id":{"format":"uuid","type":"string"},"description":{"nullable":true,"type":"string"},"id":{"format":"uuid","type":"string"},"multiple_permissions_selectable":{"type":"boolean"},"parent_resource_id":{"format":"uuid","nullable":true,"type":"string"},"requestable":{"type":"boolean"},"title":{"type":"string"},"type":{"type":"string"}},"type":"object"},"resource_id":{"description":"Resource ID (null for app-wide access)","format":"uuid","nullable":true,"type":"string"},"target_permission_ids":{"description":"Permission IDs currently held","items":{"format":"uuid","type":"string"},"type":"array"},"target_permissions":{"description":"The permissions currently held. Only present when requested via `expand=target_permissions`.","items":{"properties":{"description":{"nullable":true,"type":"string"},"elevated":{"type":"boolean"},"id":{"format":"uuid","type":"string"},"requestable":{"type":"boolean"},"resource_id":{"format":"uuid","type":"string"},"title":{"type":"string"}},"type":"object"},"type":"array"}},"required":["id","application_id","grantee_user_account_id","effective_start"],"title":"AccessState","type":"object"},"AccessRevocation":{"description":"An access revocation","properties":{"application_id":{"description":"Application ID","format":"uuid","type":"string"},"grantee_user_id":{"description":"User ID of the grantee","format":"uuid","type":"string"},"id":{"description":"Access revocation ID","format":"uuid","type":"string"},"inserted_at":{"description":"Creation timestamp","format":"date-time","type":"string"},"permission_ids":{"description":"Permission IDs being revoked","items":{"format":"uuid","type":"string"},"nullable":true,"type":"array"},"provisioning_type":{"description":"Provisioning type","enum":["application_admin","automatic"],"nullable":true,"type":"string"},"reason":{"description":"Revocation reason","type":"string"},"requestor_user_id":{"description":"User ID of the requestor","format":"uuid","type":"string"},"resource_id":{"description":"Resource ID (null for app-wide revocations)","format":"uuid","nullable":true,"type":"string"},"status":{"description":"Current status of the revocation","enum":["processing_access","rejected","revoked"],"type":"string"},"termination_reason":{"description":"The provisioner's rejection reason when the revocation was rejected; null otherwise","nullable":true,"type":"string"}},"required":["id","application_id","reason","status"],"title":"AccessRevocation","type":"object"},"RejectAccessRevocation":{"description":"Request body for rejecting an access revocation","example":{"reason":"Access is legitimate and stays"},"properties":{"reason":{"description":"Reason for rejecting the revocation","maxLength":255,"type":"string"}},"required":["reason"],"title":"RejectAccessRevocation","type":"object"},"BadRequestError":{"additionalProperties":false,"description":"Error response for a malformed or invalid request","example":{"error":"invalid_params","errors":[{"field":"application_id","messages":["is invalid"]}],"message":"Invalid request parameters"},"properties":{"error":{"description":"`invalid_params` when a parameter or the body fails validation; `bad_request` or `idempotency_key_invalid_length` otherwise","example":"invalid_params","type":"string"},"errors":{"description":"One entry per rejected parameter. Present when a query or path parameter or the body fails validation, and omitted for other bad requests.","items":{"additionalProperties":false,"properties":{"field":{"description":"Name of the rejected parameter","example":"application_id","type":"string"},"messages":{"description":"Reasons the value was rejected","example":["is invalid"],"items":{"type":"string"},"type":"array"}},"required":["field","messages"],"type":"object"},"type":"array"},"message":{"description":"Human-readable error message","example":"Invalid request parameters","type":"string"}},"required":["error","message"],"title":"BadRequestError","type":"object"}},"securitySchemes":{"bearer":{"description":"Bearer token authentication. Pass your AccessOwl API token in the `Authorization` header as `Bearer <token>`.","scheme":"bearer","type":"http"}}},"info":{"description":"REST API for AccessOwl third-party integrations","title":"AccessOwl API","version":"1.0.0"},"openapi":"3.0.0","paths":{"/api/v1/access_requests":{"get":{"callbacks":{},"description":"Returns a paginated list of access requests visible to the authenticated caller. ","operationId":"AccessOwlApi.AccessRequestController.index","parameters":[{"description":"Maximum results to return (default: 20, max: 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Opaque cursor returned in the previous response's `meta.next_cursor`. Omit for the first page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Filter by the grantee user (the user the request is for)","in":"query","name":"user_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Filter by application","in":"query","name":"application_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Filter by request status","in":"query","name":"status","required":false,"schema":{"enum":["pending_approval","pending_permissions_assignment","scheduled","pending_dependency","processing_access","access_granted","denied","rejected"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequestList"}}},"description":"Access request list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"List access requests","tags":["access_requests"]},"post":{"callbacks":{},"description":"Request access to an application resource. When authenticating with an API token, user_id is required to specify the grantee.","operationId":"AccessOwlApi.AccessRequestController.create","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccessRequest"}}},"description":"Access request parameters","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"}}},"description":"Access request created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerError"}}},"description":"Internal server error"}},"summary":"Create an access request","tags":["access_requests"]}},"/api/v1/access_requests/bulk":{"post":{"callbacks":{},"description":"Request access to multiple application resources. When authenticating with an API token, user_id is required to specify the grantee.","operationId":"AccessOwlApi.AccessRequestController.create_bulk","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBulkAccessRequest"}}},"description":"Bulk access request parameters","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkAccessRequestResponse"}}},"description":"Access requests created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}},"500":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerError"}}},"description":"Internal server error"}},"summary":"Create multiple access requests","tags":["access_requests"]}},"/api/v1/access_requests/{access_request_id}/approve":{"post":{"callbacks":{},"description":"Records one approver's approval at the request's current approval step. A request with further steps moves on to the next step; after the last step it is fully approved. The caller names the approver to approve on behalf of via `on_behalf_of_user_id`, and the acting user is then persisted as the deputy. Omit it only when the acting user is themselves an approver of the current step; an API token must always name one.","operationId":"AccessOwlApi.AccessRequestController.approve","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Access request ID","in":"path","name":"access_request_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveAccessRequest"}}},"description":"Approve parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"}}},"description":"Access request approved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden: the caller lacks the approve permission; being an approver of the request is not enough"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Approve an access request","tags":["access_requests"]}},"/api/v1/access_requests/{access_request_id}/deny":{"post":{"callbacks":{},"description":"Denies an access request that is still in approval, with a required reason. The token user is usually not an assigned approver, so the caller names the approver to deny on behalf of via `on_behalf_of_user_id`; the acting token user is then persisted as the deputy (replacement). Omit it only when the acting user is themselves a current approver. A single denial terminates the request; an already-closed request returns a validation error.","operationId":"AccessOwlApi.AccessRequestController.deny","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Access request ID","in":"path","name":"access_request_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DenyAccessRequest"}}},"description":"Deny parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"}}},"description":"Access request denied"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden: the caller lacks the deny permission; being an approver of the request is not enough"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Deny an access request","tags":["access_requests"]}},"/api/v1/access_requests/{access_request_id}/grant":{"post":{"callbacks":{},"description":"Grants a (pending, fully approved) access request.","operationId":"AccessOwlApi.AccessRequestController.grant","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Access request ID","in":"path","name":"access_request_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"}}},"description":"Access request granted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Grant an access request","tags":["access_requests"]}},"/api/v1/access_requests/{access_request_id}/reject":{"post":{"callbacks":{},"description":"Rejects a fully-approved access request on the provisioning side  with a required reason, recording the acting token user as provisioner. Distinct from deny (approver refusal before approval). Terminal: a request still in approval or already closed returns a validation error.","operationId":"AccessOwlApi.AccessRequestController.reject","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Access request ID","in":"path","name":"access_request_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectAccessRequest"}}},"description":"Reject parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"}}},"description":"Access request rejected"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Reject an access request","tags":["access_requests"]}},"/api/v1/access_requests/{id}":{"get":{"callbacks":{},"description":"Returns a single access request by its ID.","operationId":"AccessOwlApi.AccessRequestController.show","parameters":[{"description":"Access request ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRequest"}}},"description":"Access request"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"}},"summary":"Get an access request","tags":["access_requests"]}},"/api/v1/access_revocations":{"get":{"callbacks":{},"description":"Returns a paginated list of access revocations visible to the authenticated caller.","operationId":"AccessOwlApi.AccessRevocationController.index","parameters":[{"description":"Maximum results to return (default: 20, max: 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Opaque cursor returned in the previous response's `meta.next_cursor`. Omit for the first page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Filter by revocation status","in":"query","name":"status","required":false,"schema":{"enum":["processing_access","revoked","rejected"],"type":"string"}},{"description":"Filter by the grantee user (the user the revocation is for)","in":"query","name":"user_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Filter by application","in":"query","name":"application_id","required":false,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRevocationList"}}},"description":"Access revocation list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"List access revocations","tags":["access_revocations"]},"post":{"callbacks":{},"description":"Creates a revocation for the access identified by `access_state_id`. For a resource-scoped access state, produces one revocation against that resource.For an app-wide access state (no resource), produces the equivalent app-wide revocation.","operationId":"AccessOwlApi.AccessRevocationController.create","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAccessRevocation"}}},"description":"Access revocation parameters","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRevocation"}}},"description":"Access revocation created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Create an access revocation","tags":["access_revocations"]}},"/api/v1/access_revocations/{access_revocation_id}/reject":{"post":{"callbacks":{},"description":"Marks a (pending) access revocation as rejected with a required reason, recording the caller as the provisioner. Terminal: an already-revoked or already-rejected revocation returns a validation error.","operationId":"AccessOwlApi.AccessRevocationController.reject","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Access revocation ID","in":"path","name":"access_revocation_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RejectAccessRevocation"}}},"description":"Reject parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRevocation"}}},"description":"Access revocation rejected"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Mark an access revocation as rejected","tags":["access_revocations"]}},"/api/v1/access_revocations/{access_revocation_id}/revoke":{"post":{"callbacks":{},"description":"Marks a (pending) access revocation as revoked, recording the caller as the provisioner. When there is no current access left to revoke, the revocation is closed as rejected instead — the returned `status` reflects the outcome.","operationId":"AccessOwlApi.AccessRevocationController.revoke","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Access revocation ID","in":"path","name":"access_revocation_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRevocation"}}},"description":"Access revocation revoked"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Mark an access revocation as revoked","tags":["access_revocations"]}},"/api/v1/access_revocations/{id}":{"get":{"callbacks":{},"description":"Returns a single access revocation by its ID.","operationId":"AccessOwlApi.AccessRevocationController.show","parameters":[{"description":"Access revocation ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessRevocation"}}},"description":"Access revocation"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"}},"summary":"Get an access revocation","tags":["access_revocations"]}},"/api/v1/access_states":{"get":{"callbacks":{},"description":"Returns a paginated list of access states — records of who currently has (or historically had) access to which application resources, including effective time ranges.","operationId":"AccessOwlApi.AccessStateController.index","parameters":[{"description":"Maximum results to return (default: 20, max: 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Opaque cursor returned in the previous response's `meta.next_cursor`. Omit for the first page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Filter by application ID","in":"query","name":"application_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Filter by grantee user ID","in":"query","name":"grantee_user_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Comma-separated list of related objects to embed inline alongside their ID fields. Allowed values: `grantee_user`, `application`, `resource`, `target_permissions`. Embedded objects carry their own top-level fields only (no further nesting). An unknown value returns 400.","in":"query","name":"expand","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessStateList"}}},"description":"Access state list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"List access states","tags":["access_states"]}},"/api/v1/applications":{"get":{"callbacks":{},"description":"Returns a paginated list of applications in your organization.","operationId":"AccessOwlApi.ApplicationController.index","parameters":[{"description":"Maximum results to return (default: 20, max: 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Opaque cursor returned in the previous response's `meta.next_cursor`. Omit for the first page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Filter by title (case-insensitive)","in":"query","name":"title_like","required":false,"schema":{"type":"string"}},{"description":"Filter by category title (case-insensitive)","in":"query","name":"category_contains_word","required":false,"schema":{"type":"string"}},{"description":"Filter by application status","in":"query","name":"status","required":false,"schema":{"enum":["ignored","discovered","approved","requestable"],"type":"string"}},{"description":"Filter by business owner (the application's owner user)","in":"query","name":"owner_user_id","required":false,"schema":{"format":"uuid","type":"string"}},{"description":"Filter by application admin user","in":"query","name":"admin_user_id","required":false,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationList"}}},"description":"Application list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"List applications","tags":["applications"]},"post":{"callbacks":{},"description":"Creates a new application in your organization. You may include its resources and permissions in the request body to define the access structure up front.","operationId":"AccessOwlApi.ApplicationController.create","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApplication"}}},"description":"Application create parameters","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}},"description":"Application"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Create an application","tags":["applications"]}},"/api/v1/applications/{application_id}/access_states":{"put":{"callbacks":{},"description":"Imports the complete access list for one application. Users, resources and permissions are matched by email and title. **Any access not present in the body is removed.** An email matching no known user creates one. If any row cannot be resolved, nothing is written and every rejected row is listed in the response. Importing into an application with an active access-syncing integration is permitted; the next scheduled sync will overwrite what the import wrote. Because this call replaces all of an application's access, send a unique `Idempotency-Key` header so an accidentally repeated request is rejected rather than re-applied.","operationId":"AccessOwlApi.AccessStateController.import","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"Application ID","in":"path","name":"application_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportAccessStates"}}},"description":"Complete access list","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccessImportResult"}}},"description":"Import result"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Import an application's access","tags":["access_states"]}},"/api/v1/applications/{application_id}/resources":{"get":{"callbacks":{},"description":"Returns the resources defined for the given application, each with its permissions.","operationId":"AccessOwlApi.ApplicationController.list_objects","parameters":[{"description":"Application ID","in":"path","name":"application_id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResourceList"}}},"description":"Resource list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"}},"summary":"List resources for an application","tags":["applications"]}},"/api/v1/applications/{application_id}/structure":{"put":{"callbacks":{},"description":"Replaces the application's access structure by upserting its resources and their permissions in a single call. On applications whose structure is synced by an integration, only manually added resources can be edited.","operationId":"AccessOwlApi.ApplicationController.update_structure","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"","in":"path","name":"application_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateStructure"}}},"description":"Update structure parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}},"description":"Application"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found, or not visible to the caller"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Upsert an application's resources and permissions","tags":["applications"]}},"/api/v1/applications/{id}":{"get":{"callbacks":{},"description":"Returns a single application, including its owner, admins, and integration details.","operationId":"AccessOwlApi.ApplicationController.show","parameters":[{"description":"Application ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}},"description":"Application"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"}},"summary":"Get an application by ID","tags":["applications"]},"patch":{"callbacks":{},"description":"Updates an application's top-level attributes. Supports optimistic locking: include the current `lock_version` to guard against concurrent edits, which returns a conflict if the application has changed since you read it. To modify resources and permissions, use the update-structure endpoint.","operationId":"AccessOwlApi.ApplicationController.update (2)","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApplication"}}},"description":"Application update parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}},"description":"Application"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found, or not visible to the caller"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Update an application","tags":["applications"]},"put":{"callbacks":{},"description":"Updates an application's top-level attributes. Supports optimistic locking: include the current `lock_version` to guard against concurrent edits, which returns a conflict if the application has changed since you read it. To modify resources and permissions, use the update-structure endpoint.","operationId":"AccessOwlApi.ApplicationController.update","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateApplication"}}},"description":"Application update parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Application"}}},"description":"Application"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found, or not visible to the caller"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Update an application","tags":["applications"]}},"/api/v1/policies":{"get":{"callbacks":{},"description":"Returns a paginated list of access policies in your organization.","operationId":"AccessOwlApi.PolicyController.index","parameters":[{"description":"Maximum results to return (default: 20, max: 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Opaque cursor returned in the previous response's `meta.next_cursor`. Omit for the first page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyList"}}},"description":"Policy list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"List policies","tags":["policies"]}},"/api/v1/policies/{policy_id}/applications":{"put":{"callbacks":{},"description":"Replaces the set of applications attached to a policy. The provided list fully overwrites the policy's current applications (it is not additive).","operationId":"AccessOwlApi.PolicyController.set_applications","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"","in":"path","name":"policy_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetApplications"}}},"description":"Set applications parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Policy"}}},"description":"Policy"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Replace a policy's application list","tags":["policies"]}},"/api/v1/users":{"get":{"callbacks":{},"description":"Returns a paginated list of users in your organization.","operationId":"AccessOwlApi.StaffController.index","parameters":[{"description":"Maximum results to return (default: 20, max: 100)","in":"query","name":"limit","required":false,"schema":{"type":"integer"}},{"description":"Opaque cursor returned in the previous response's `meta.next_cursor`. Omit for the first page.","in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Filter users by status. Returns active users by default","in":"query","name":"status","required":false,"schema":{"enum":["onboarding_provisioning_planned","onboarding","active","inactive","offboarding_planned","offboarding","offboarded","all"],"type":"string"}},{"description":"Filter users by email. Matches the primary email or any of the user's other known emails (case-insensitive, exact match).","in":"query","name":"email","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserList"}}},"description":"User list"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"}},"summary":"List users","tags":["users"]},"post":{"callbacks":{},"description":"Creates a new user with the given identity and org info (department/team/job_title/location/employment_type + manager). Does not onboard — call POST /users/:user_id/onboard to onboard. Fails if a user with the email already exists.","operationId":"AccessOwlApi.StaffController.create","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUser"}}},"description":"Create user parameters","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Create a user","tags":["users"]}},"/api/v1/users/onboard":{"post":{"callbacks":{},"description":"Creates a new user with the given identity, org info and manager, and onboards them via the Zero-Touch (access-template) flow in one step. Omit scheduled_at to provision now; a future timestamp defers provisioning. Nothing is created when onboarding cannot start. Fails if a user with the email already exists — onboard an existing user with POST /users/{user_id}/onboard.","operationId":"AccessOwlApi.StaffController.create_and_onboard","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAndOnboardUser"}}},"description":"Create and onboard parameters","required":false},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User created and onboarding triggered"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Create and onboard a user","tags":["users"]}},"/api/v1/users/{id}":{"get":{"callbacks":{},"description":"Returns a single user in your organization by their ID.","operationId":"AccessOwlApi.StaffController.show","parameters":[{"description":"User ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Unauthorized"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"}},"summary":"Get a user by ID","tags":["users"]},"patch":{"callbacks":{},"description":"Updates the given fields of the user; omitted fields stay untouched and null clears a field. A user managed by an HRIS directory integration gets its name and org info from the directory, so these fields are refused. Its manager can only be changed together with manager_override set to true, which stops the directory sync from changing the manager; manager_override false hands the manager back to the directory.","operationId":"AccessOwlApi.StaffController.update (2)","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"User ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUser"}}},"description":"Update user parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Update a user","tags":["users"]},"put":{"callbacks":{},"description":"Updates the given fields of the user; omitted fields stay untouched and null clears a field. A user managed by an HRIS directory integration gets its name and org info from the directory, so these fields are refused. Its manager can only be changed together with manager_override set to true, which stops the directory sync from changing the manager; manager_override false hands the manager back to the directory.","operationId":"AccessOwlApi.StaffController.update","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"User ID","in":"path","name":"id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUser"}}},"description":"Update user parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Update a user","tags":["users"]}},"/api/v1/users/{user_id}/offboard":{"post":{"callbacks":{},"description":"Runs the full offboarding process (offboarding notice + revocations) for the user. Omit scheduled_at to offboard immediately; provide a future timestamp to schedule it. Calling again with a new scheduled_at reschedules an existing planned offboarding. A user already being offboarded or already offboarded returns a validation error.","operationId":"AccessOwlApi.StaffController.offboard","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"User ID","in":"path","name":"user_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OffboardUser"}}},"description":"Offboard parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User offboarded or scheduled"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Offboard a user","tags":["users"]}},"/api/v1/users/{user_id}/onboard":{"post":{"callbacks":{},"description":"Onboards the user via the Zero-Touch (access-template) flow: provisions the access the template rules match for the user's org info. Does not change the user — set org info and manager beforehand with PATCH /users/{user_id}; onboarding requires the user to have a manager. Omit scheduled_at to provision now; a future timestamp defers provisioning. Calling again for a user already onboarding reschedules the planned provisioning to the new scheduled_at (omit it to provision now); an onboarding already being provisioned can no longer be rescheduled.","operationId":"AccessOwlApi.StaffController.onboard","parameters":[{"description":"Optional key (1–255 chars) for safely retrying a request. Reusing the same key for the same request returns `409 Conflict` and is not processed again — this confirms the request was already received. Keys are retained for 14 days.","in":"header","name":"Idempotency-Key","required":false,"schema":{"maxLength":255,"minLength":1,"type":"string"}},{"description":"User ID","in":"path","name":"user_id","required":true,"schema":{"format":"uuid","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardUser"}}},"description":"Onboard parameters","required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}},"description":"User onboarding triggered"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Bad request"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedError"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenError"}}},"description":"Forbidden"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictError"}}},"description":"Conflict"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}},"description":"Validation error"},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitError"}}},"description":"Too many requests","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer"},"style":"simple"}}}},"summary":"Onboard a user","tags":["users"]}}},"security":[{"bearer":[]}],"servers":[{"url":"https://app.accessowl.io","variables":{}}],"tags":[]}