
# 사용자를 조직에 추가

`POST /v1/organizations/{org_id}/memberships` · 권한 `organizations:write`

기존 사용자를 조직에 직접 추가합니다(소스 `admin_api`, 상태 `active`). `role_ids`를 지정하지 않으면 조직의 기본 구성원 역할이 부여됩니다. 각 역할은 환경 역할이거나 이 조직의 역할이어야 합니다. 응답에는 `ETag`가 포함되며, 이 쓰기 작업은 `organization_membership.created`로 감사 기록됩니다. `Idempotency-Key`는 선택 사항입니다.

## 요청

| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
| `org_id` | path | 예 | 조직 ID(`org_…`)입니다. |
| `user_id` | string | 예 | 사용자 ID(`usr_…`)입니다. |
| `role_ids` | string[] | 아니요 | 역할 ID(`rol_…`)이며, 최대 50개입니다. |
| `expires_at` | string | 아니요 | 멤버십이 종료되는 미래 시점의 RFC 3339 시간입니다. |

## 응답

멤버십이 포함된 `201 Created`가 반환됩니다.

```json
{
  "id": "mem_01j9xn5p9s0t4v6w8x0y2z4a6c",
  "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
  "user_id": "usr_01j9xh2k6p7q1r3s5t7v9w1x3y",
  "status": "active",
  "source": "admin_api",
  "reason": null,
  "roles": [
    {
      "role_id": "rol_01j9xr7s1t2w6x8y0z2a4b6c8e",
      "source": "admin_api",
      "assigned_at": "2026-10-12T09:31:00.123456Z"
    }
  ],
  "expires_at": null,
  "created_at": "2026-10-12T09:31:00.123456Z",
  "activated_at": "2026-10-12T09:31:00.123456Z",
  "suspended_at": null,
  "removed_at": null,
  "updated_at": "2026-10-12T09:31:00.123456Z",
  "version": 1
}
```

## 오류

| HTTP | code | 발생 조건 |
|---|---|---|
| 404 | `not_found` | 이 환경에 조직 또는 사용자가 없습니다. |
| 403 | `role_not_assignable` | 역할이 환경 역할이 아니거나 이 조직의 역할이 아닙니다. |
| 403 | `user_not_active` | 사용자가 활성 상태가 아닙니다. |
| 409 | `membership_already_exists` | 사용자가 이미 조직의 구성원입니다. |
| 409 | `organization_disabled` | 조직이 비활성화되어 있습니다. |
| 409 | `organization_membership_limit_reached` | 조직의 멤버십 한도에 도달했습니다. |
| 409 | `membership_limit_reached` | 사용자의 멤버십 한도에 도달했습니다. |
| 422 | `anonymous_user_not_allowed` | 사용자가 익명 사용자입니다. |
| 422 | `validation_failed` | 필드가 없거나 잘못되었습니다. |
| 401 | `unauthenticated` | 자격 증명이 없거나, 잘못되었거나, 취소되었습니다. |
| 403 | `insufficient_permissions` | 자격 증명에 필요한 권한이 없습니다. 권한이 필요한 역할(`is_privileged`)을 부여하려면 `roles:write`도 필요하며, 없으면 아무것도 기록되지 않고 `required_permissions`에 두 권한이 모두 표시됩니다. |
| 429 | `rate_limited` | 요청 한도를 초과했습니다. `Retry-After` 기간 이후에 다시 시도하십시오. |
| 503 | `service_unavailable` | 종속 서비스를 일시적으로 사용할 수 없습니다. `Retry-After` 기간 이후에 다시 시도하십시오. |

## 예시

```bash
curl -i -X POST "https://api.eu.keenauth.com/v1/organizations/org_01j9xk3m7q8r2s4t6v8w0y2z4a/memberships" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"usr_01j9xh2k6p7q1r3s5t7v9w1x3y","role_ids":["rol_01j9xr7s1t2w6x8y0z2a4b6c8e"]}'
```

## 개인정보

이 엔드포인트는 개인정보를 다룹니다. 조직 멤버십과 초대가 해당합니다. [KeenAuth API의 개인정보](/docs/policies/personal-data)에서 저장되는 항목, 보관 기간, 삭제 방식을 설명합니다. 어떤 필드에도 특수 범주의 개인정보(건강, 생체 정보, 종교, 정치적 견해, 성적 지향)를 보내지 마십시오.
