> ## Documentation Index
> Fetch the complete documentation index at: https://developers.jobhandy.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenant scope and resource placement

> Resolve tenant context, division placement, and API-key authorization without ambiguity.

Every protected request executes within the tenant and division scope assigned to the API key.

## Scope resolution

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart TD
    R[Protected request] --> K{Valid active API key?}
    K -- No --> E1[401 INVALID_API_KEY]
    K -- Yes --> H{X-Tenant-ID supplied?}
    H -- Yes --> S{Tenant in key scope?}
    S -- No --> E2[403 TENANT_NOT_IN_SCOPE]
    S -- Yes --> T[Use selected tenant]
    H -- No --> I{Operation can infer one tenant?}
    I -- Yes --> T
    I -- No --> E3[TENANT_CONTEXT_AMBIGUOUS]
```

## Collection operations

Collection endpoints can query every tenant in the key scope when `X-Tenant-ID` is omitted. Send the header to restrict results to one authorized tenant.

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl --request GET \
  --url 'https://api.jobhandy.io/v1/employees' \
  --header 'X-API-Key: YOUR_API_KEY' \
  --header 'X-Tenant-ID: {{tenantId}}'
```

## Create operations

| Operation       | Placement inputs                                         | Ambiguity handling                                                     |
| --------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- |
| Create employee | `X-Tenant-ID` and/or `divisionId`                        | The API must resolve one tenant and an allowed division where required |
| Create incident | Employee reference, optionally narrowed by `X-Tenant-ID` | Referenced employee must be accessible in the selected context         |
| Create division | `X-Tenant-ID` or `parentId` or unambiguous key scope     | Request fails if one target tenant cannot be resolved                  |

For a division-restricted key, an employee create request may omit `divisionId` only when the selected tenant has exactly one allowed division. Otherwise send an allowed division ID.

## Existing resources

For `GET` and `PATCH` by ID, `X-Tenant-ID` narrows the lookup. The resource and all referenced target resources must be accessible through that tenant.

## Placement rules

* `X-Tenant-ID` never expands access.
* A division belongs to one tenant.
* `divisionId` can assign or move an employee only within the same tenant.
* `divisionId: null` removes the division assignment; it does not transfer the employee.
* Tenant transfer of an assigned employee is not exposed by the public update endpoint.
* A create dry run can return a preview identifier that must not be used in later requests.

## Common failures

| Error code                     | Typical cause                                            | Corrective action                                      |
| ------------------------------ | -------------------------------------------------------- | ------------------------------------------------------ |
| `TENANT_CONTEXT_AMBIGUOUS`     | More than one tenant can satisfy the request             | Send `X-Tenant-ID` or a documented placement reference |
| `EMPLOYEE_PLACEMENT_AMBIGUOUS` | Division-restricted scope does not resolve one placement | Send an allowed `divisionId`                           |
| `TENANT_NOT_IN_SCOPE`          | Selected tenant is not authorized                        | Correct the header or API-key scope                    |
| `INVALID_REFERENCE_ID`         | Tenant, employee, or division ID has an invalid format   | Use an ID returned by JobHandy                         |
| `INVALID_REFERENCE`            | Referenced resource is missing or not allowed            | Re-read scope and referenced resource                  |

<Card title="Terminology" icon="book-open" horizontal href="/concepts/terminology">
  Review the distinction between company, tenant, division, portal permission, and API-key scope.
</Card>
