
# 초대 일괄 생성

`POST /v1/invitations:batch` · 권한 `invitations:write`

초대를 1~100개(`items`) 생성합니다. 각 항목은 `POST /v1/invitations`의 규칙을 따르며 개별적으로 처리됩니다. 한 항목이 실패해도 다른 항목은 계속 처리됩니다. 응답은 `200 OK`이며 `items`는 요청 순서를 유지합니다. 항목의 `status`는 `201`(새 초대), `200`(대기 중인 초대를 다시 보냄) 또는 오류의 HTTP 상태입니다. 실패한 항목에는 `code`, `status`, `/items/<i>/…` 형식의 필드 포인터가 담긴 `error`가 포함됩니다. `link_only` 항목의 `accept_url`은 이 응답에서만 반환되며(`Cache-Control: no-store`), `Idempotency-Key`로 다시 재생된 응답에는 링크가 없고 `secret_redacted: true`가 반환됩니다. `organization_id`가 없는 항목은 환경 초대입니다. `email` 항목은 이메일로 발송됩니다. 배포 환경에서 초대 이메일이 구성되어 있지 않으면 `501 not_implemented` 항목 오류가 발생하며, 이 환경에 존재하지 않는 `application_id`는 `404 not_found` 항목 오류가 됩니다. 작성된 각 초대는 `invitation.created`로 감사 기록됩니다.

## 요청

| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
| `items` | object[] | 예 | `POST /v1/invitations`의 필드를 가진 초대 1~100개. |
| `Idempotency-Key` | header | 아니요 | 재시도 시 링크 없이 저장된 결과를 반환하게 합니다. |

## 응답

`200 OK`이며 항목마다 결과 하나가 포함됩니다.

```json
{
  "items": [
    {
      "status": 201,
      "invitation": {
        "id": "inv_01j9xt9v3w4y8z0a2b4c6d8e0g",
        "organization_id": "org_01j9xk3m7q8r2s4t6v8w0y2z4a",
        "email": "ada@example.com",
        "role_ids": [
          "rol_01j9xr7s1t2w6x8y0z2a4b6c8e"
        ],
        "application_id": null,
        "delivery": "link_only",
        "delivery_status": "not_sent",
        "status": "pending",
        "send_count": 1,
        "last_sent_at": "2026-10-12T09:31:00.123456Z",
        "expires_at": "2026-10-19T09:31:00.123456Z",
        "accepted_user_id": null,
        "accepted_at": null,
        "revoked_at": null,
        "created_at": "2026-10-12T09:31:00.123456Z",
        "updated_at": "2026-10-12T09:31:00.123456Z",
        "version": 1,
        "accept_url": "https://acme.eu.keenauth.app/u/login?invitation=<token>"
      }
    },
    {
      "status": 422,
      "error": {
        "code": "validation_failed",
        "status": 422,
        "errors": [
          {
            "pointer": "/items/1/email",
            "code": "invalid_value"
          }
        ]
      }
    }
  ]
}
```

## 오류

| HTTP | code | 발생 조건 |
|---|---|---|
| 422 | `validation_failed` | `items`가 없거나, 비어 있거나, 100개를 초과합니다. |
| 401 | `unauthenticated` | 자격 증명이 없거나, 잘못되었거나, 폐기되었습니다. |
| 403 | `insufficient_permissions` | 자격 증명에 필요한 권한이 없습니다. 특권(`is_privileged`) 역할이 포함된 항목은 자격 증명에 `roles:write`가 없으면 이 항목 오류로 실패합니다. |
| 429 | `rate_limited` | 요청 한도를 초과했습니다. `Retry-After` 기간 후에 다시 시도하십시오. |
| 503 | `service_unavailable` | 의존 서비스를 일시적으로 사용할 수 없습니다. `Retry-After` 기간 후에 다시 시도하십시오. |

## 예시

```bash
curl -i -X POST "https://api.eu.keenauth.com/v1/invitations:batch" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0f6c1d2e3a4b5c6d7e8f9a0b" \
  -d '{"items":[{"organization_id":"org_01j9xk3m7q8r2s4t6v8w0y2z4a","email":"ada@example.com","delivery":"link_only"},{"organization_id":"org_01j9xk3m7q8r2s4t6v8w0y2z4a","email":"bob@example.com","delivery":"link_only"}]}'
```

## 개인정보

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