# Greenhouse 403 "On-behalf-of user does not have permission"

## TL;DR
The Harvest API key is fine, but the recruiter user the agent is acting for lacks permission for that action, so the call is rejected. Fix: grant the recruiter the needed job permissions in Greenhouse, or have the agent act as a user that already has them. On-behalf-of inherits the user's permissions, not the key's.

## Error
```text
403 Forbidden
"On-behalf-of user does not have permission"
```

## Steps
1. Identify the on-behalf-of user and the action: check the on-behalf-of header the agent sends and the endpoint that 403d.
   Expected: you know who and what, e.g. a recruiter moving a candidate on a specific job.
2. Check that user's permissions in Greenhouse: Site Admin, then Users, then the user's job permissions for the target job.
   Expected: you see the missing permission, e.g. no access to the job or no move-stage right.
3. Grant the permission (or ask a Greenhouse admin to): add the user to the job with the right role.
   Expected: the permission set now covers the action.
4. Retry the exact call with the same on-behalf-of user.
   Expected: 200 or 201; no more 403.
5. For service accounts, consider a dedicated integration user with exactly the permissions the agent needs, instead of borrowing recruiters' identities.
   Expected: permissions stay stable when recruiters change roles.

## Use this when
- Harvest API calls 403 only with on-behalf-of headers
- the agent acts for different recruiters
- permissions work for one user but not another
- a recruiter changed teams and calls started failing

## Not for this skill when
- the error is 401 (that is the rotated-key problem)
- every call 403s even without the header (check the API key's own permissions)
- the action succeeds but attributes to the wrong user (check which identity the header names)

## Variant phrasings
- "Greenhouse on behalf of permission denied"
- "on-behalf-of 403 Harvest API"
- "service account acting for recruiter 403"
- "on-behalf-of user lacks permission"

## Why it happens
On-behalf-of exists so actions are attributed to the right human, and the API enforces that human's actual permissions. The agent's key only gets it in the door; the named user decides what is allowed. When the recruiter's job access changes, the agent's calls start 403ing with no change in code.

## Edge cases
- Job permissions are per job; access to one req does not imply access to another.
- A deactivated user 403s everything; check user status, not just roles.
- Some actions need a higher role than the recruiter's current one; escalate deliberately, not by making everyone an admin.
- Log the on-behalf-of user on every call so 403s are diagnosable.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_7vS8jDUoXwNBA0A-Js0R0Q
