---
title: "Approve a member into a tier"
method: POST
path: "/api/tier/approve"
tags: ["membership"]
---

# Approve a member into a tier

`POST /api/tier/approve`

## Request

- Base URL: `https://www.immersivecommons.com`
- URL: `https://www.immersivecommons.com/api/tier/approve`
- Auth: one of:
  - API key in cookie `__session`
  - HTTP bearer

Clerk operator session OR an agt_ token carrying `admin:tier_review`, live tier re-checked. With no `tier` the member's own pending request is approved as-is; passing `tier` approves them into that ring instead (an operator override — this is the only path that can hand out `operator`). Sister of the /floor10/admin/members server action: both call one applyTier, so behaviour is identical.

## Request body

- TierApproveRequest
  - `user_id` string, required: Clerk user id of the member being approved.
  - `tier` string: Optional override ring. Omit to approve the member's own pending request as filed.
  - `reason` string: Free text for the audit trail; trimmed to 400 characters.

## Response `200`

The applied tier move.

- TierApplyResponse
  - `ok` boolean, required
  - `user_id` string, required
  - `from` string, required: The ring the member held before this call.
  - `to` string, required: The ring they hold now.
  - `action` string, required: The audit verb recorded for the move.

## Other responses

- `400`: Invalid JSON, missing user_id, an unknown tier override, or no pending request to approve.
- `401`: No auth.
- `403`: Not an operator / scope not authorized.
- `500`: Clerk lookup or write failed.

---

[API](https://skmtc.dev/immersivecommons/apis/immersive-commons-agent-rest-api.md) · [All operations](https://skmtc.dev/immersivecommons/apis/immersive-commons-agent-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/immersivecommons/apis/immersive-commons-agent-rest-api/revisions/be67c1f67c27?raw)
