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

# 그룹 만들기

> 규칙으로 그룹 하나를 만듭니다. Idempotency-Key로 재시도가 안전합니다



## OpenAPI

````yaml api-reference/openapi.ko.yaml POST /api/preview/segments
openapi: 3.1.0
info:
  title: DocuRise 퍼블릭 API
  version: preview
  description: >
    DocuRise 프로그래매틱 접근입니다.


    **이 API는 프리뷰 단계입니다.** 모든 경로는 `/api/preview/` 하위에 버전이 지정되어 있으며,

    프리뷰 단계에서는 호환성을 보장하지 않습니다 — 필드, 값, 에러 코드가 추가, 변경 또는 제거될

    수 있습니다. 계약이 안정화되면 `/api/v1/`로 승격됩니다.

    변경 사항은 [변경 이력](/ko/changelog)에서 확인하세요.


    ### 접근 조건


    모든 라우트는 다음을 요구합니다:

    1. 유효한 API 키 (아래 인증 참고).

    2. 호출하는 계정의 요금제가 **Iconic 이상**이어야 합니다.

    3. 프리뷰 기간 동안 API는 일부 계정에서만 사용이 가능하며, 요금제와는 별개입니다.
       사용할 수 없는 계정은 아래 모든 라우트에서 `404`를 받습니다. 사용할 수 있어야
       하는 계정이라면 DocuRise 담당자에게 문의하세요.

    키 발급 및 관리는 대시보드의 **Settings → Developers**에서 할 수 있습니다.


    ### 멱등성(Idempotency)


    리소스를 생성하는 `POST` 엔드포인트는 `Idempotency-Key` 헤더가 필요합니다. 같은 키와 같은

    요청 본문으로 재요청하면 두 번째 리소스를 만드는 대신 원래 응답(동일한 상태 코드, 동일한

    본문)을 그대로 반환합니다 — 타임아웃이나 연결 끊김 시 안전하게 재시도할 수 있습니다. 키는

    7일 동안 기억되며, 그 이후에 같은 키로 요청하면 새 요청으로 처리됩니다. 같은

    키를 **다른** 본문으로 재사용하면 `IDEMPOTENCY_KEY_CONFLICT`로 거부됩니다. 매 논리적 작업마다

    새로운 키(UUID나 ULID면 충분)를 생성하세요 — HTTP 시도마다 새로 생성하지 마세요.


    예외: `POST /api/preview/tags`는 `Idempotency-Key`를 받지 않습니다. 같은 이름의 태그를 두 번

    만들어도 아무것도 바뀌지 않으므로(두 번째 호출은 기존 태그를 `created: false`로 반환), 재시도는

    항상 안전합니다.


    또 다른 예외: `POST /api/preview/segments/preview`는 `Idempotency-Key`를 받지 않습니다.

    아무것도 저장하지 않으므로 반복 호출해도 항상 안전합니다.


    ### 응답 호환성


    응답은 시간이 지나면서 필드가 추가될 수 있고, `type`/`code` 형태의 열거값(예를 들어 향후

    추가될 `LeadFormQuestion.type` 값이나 새로운 에러 `code`)도 새 값이 늘어날 수 있습니다.

    알지 못하는 필드나 열거값은 항상 무시하고 에러로 취급하지 마세요 — 이것이 `preview` 기간

    동안의 모든 추가적 변경을 하위 호환되게 만드는 원칙입니다.


    응답에서 필드가 아예 없는 것과 값이 `null`로 존재하는 것은 항상 같은 의미가 아닙니다. 타입에

    `null`이 전혀 포함되지 않는 필드는 해당하지 않을 때 아예 생략됩니다 — `null`로 전송되는 일은

    없습니다(예를 들어 `retryAfterSeconds`는 백오프 힌트가 없을 때 완전히 생략되며, `null`로

    설정되지 않습니다). 타입에 `null`을 명시적으로 허용하는 필드는 "값이 없음"과는 구분되는 실제

    의미로 `null`을 사용합니다(예를 들어 문서의 `expiresAt: null`은 "알 수 없음"이나 "해당

    없음"이 아니라, 고정 만료일이 없다는 뜻입니다).


    모든 필드명은 `notionUrl`, `leadFormQuestions`, `collectName` 등과 같이 모든 요청/응답 본문에서

    일관되게 `camelCase`를 사용합니다.


    ### 식별자


    `id` 값은 불투명한(opaque) 문자열입니다. 구조화되지 않은 토큰으로 저장하고 비교하세요 —

    파싱하거나 형식을 검증하거나 길이·문자 구성에 대해 어떤 가정도 하지 마세요.


    ### 에러


    모든 에러 응답은 동일한 형식을 갖습니다:


    ```json

    { "error": { "code": "STRING", "message": "human-readable", "retryable":
    false } }

    ```


    `message`가 아니라 `code`를 기준으로 분기하세요 — `message`는 로그/디버깅용 자유 텍스트이며

    예고 없이 문구가 바뀔 수 있습니다. `code`가 안정적인 계약입니다. `retryable`은 동일한 요청을

    그대로 재시도해도 되는지를 나타내며, 존재할 경우 `retryAfterSeconds`가 구체적인 백오프

    힌트를 제공합니다.


    요청 본문에 NUL 문자(`\u0000`)가 문자열 값이나 속성 이름에 들어 있으면 아무것도 저장하기 전에

    `400 VALIDATION_ERROR`로 거부됩니다.


    ### 속도 제한


    계정이 보유한 키 개수와 무관하게, 모든 `/api/preview/*` 라우트에 대해 계정당 분당 60회

    요청으로 제한됩니다. 초과 시 `Retry-After` 헤더와 함께 `429`가 반환됩니다.


    이와 별도로, 계정이 보유한 키 개수와 무관하게 이 라우트들에서 한 계정이 동시에 실행 중인

    요청은 최대 10개입니다. 11번째가 될 요청은 `code: TOO_MANY_CONCURRENT_REQUESTS`와

    `Retry-After: 1`이 담긴 `429`를 반환합니다. 실행 중인 요청 하나가 끝날 때까지 기다린 뒤

    재시도하세요. 이 제한은 아직 끝나지 않은 요청을 세므로, 분당 60회 이내여도 적용될 수 있습니다.
  contact:
    name: DocuRise
    url: https://docurise.io
servers:
  - url: https://docurise.io
    description: 프로덕션
security:
  - apiKey: []
tags:
  - name: Documents
    description: >-
      문서(노션 페이지, 포스트, 리드 수집 폼)를 생성하고, 내가 소유한 문서를 목록 조회하거나 읽고, 초안을 게시하며, 상태, 만료일,
      이메일 보호 설정을 변경합니다.
  - name: Analytics
    description: >-
      내 문서 하나의 조회, 방문자, 리드, 전환 집계 수치를 조회하고, 유입 채널별 분포, 이전 기간과의 비교, 폼 퍼널로도 확인하며,
      내 모든 문서를 조회, 방문자, 리드 기준으로 순위를 매겨 조회합니다.
  - name: Folders
    description: 폴더와 강의를 항목 수와 함께 조회합니다.
  - name: Products
    description: 상품 카탈로그를 조회합니다(읽기 전용).
  - name: Audiences
    description: >-
      태그와 그룹을 연락처 수와 함께 조회하고, 규칙으로 그룹을 만들고, 규칙에 맞는 연락처 수를 미리 세고, 그룹 하나를 규칙과 함께
      조회합니다. 수치만 제공하며 연락처 정보는 절대 반환하지 않습니다.
  - name: Contacts
    description: 내 연락처 하나에 태그를 추가하거나 제거합니다. 연락처 정보는 반환하지 않습니다.
  - name: Email
    description: 이메일 1회성 발송, 1회성 발송별 집계 수치, 자동화를 조회합니다. 이메일만 해당하며 카카오는 포함되지 않습니다.
  - name: Instagram
    description: Instagram 댓글-DM 자동화 규칙을 생성, 조회, 수정, 일시정지, 재개합니다.
  - name: Account
    description: 호출에 사용 중인 API 키를 확인합니다.
paths:
  /api/preview/segments:
    post:
      tags:
        - Audiences
      summary: 그룹 만들기
      description: >
        규칙으로 그룹 하나를 만들고 그 그룹을 반환합니다. `segments:write`

        범위가 필요합니다. 이 범위가 생기기 전에 만든 키에는 이 범위가 없으므로, Settings →

        Developers의 **Edit scopes**에서 추가하세요(키 자체는 바뀌지 않습니다).


        본문은 `name`과 `filter`입니다. `filter`는 누가 그룹에 속하는지 정하는 규칙입니다.

        규칙은 세 목록의 조건으로 만듭니다. `conditions`(`operator`인 `AND` 또는 `OR`로

        연결), `requiredConditions`(항상 AND로 추가 적용), `excludeConditions`(이 중 하나라도

        해당하는 연락처는 제외)입니다. 규칙에는 세 목록을 통틀어 조건이 하나 이상 있어야

        합니다. 일부 조건 형태는 특정 목록에서 거부됩니다(`422 CONDITION_NOT_SUPPORTED`,

        [그룹 조건](/ko/api-reference/group-conditions) 참고). 조건 타입, 각 조건의 키와 값, 조건에

        필요한 id를 찾는 방법은

        [그룹 조건](/ko/api-reference/group-conditions)에 있습니다. 저장하기 전에 규칙에 맞는

        연락처 수를 확인하려면 `POST /api/preview/segments/preview`를 사용하세요.


        그룹은 규칙에 맞는 모든 연락처 중 수신 거부 연락처를 뺀 사람으로 구성됩니다.

        수신 거부 연락처는 멤버가 되지 않습니다. 이름은 고유하지 않아 두 그룹이 같은

        이름을 가질 수 있으므로, 반환된 `id`를 보관하세요. 응답의 `name`은 저장된 이름으로,

        앞뒤 공백을 제거하고 유니코드 정규화(NFC)한 값입니다.


        그룹을 만들어도 아무것도 발송되지 않고 자동화도 시작되지 않습니다. 응답의 `memberCount`는 만든 시점에 규칙에 맞는
        연락처의 정확한 수입니다. `GET /api/preview/segments`의 `contactCount`는 잠시 뒤처질 수
        있습니다.


        한 계정은 API로 그룹을 최대 100개까지 만들 수 있습니다. 한도에 도달하면

        `422 GROUP_LIMIT_REACHED`이며 `details.limit`에 한도가 들어 있습니다.


        **`Idempotency-Key`가 필요합니다.** 같은 키와 같은 본문으로 다시 호출하면 첫 응답을

        그대로 반환하므로, 타임아웃 뒤에 재시도해도 그룹이 두 개 만들어지지 않습니다.

        거부된 요청은 키와 함께 기억됩니다. 같은 키와 같은 본문으로 다시 보내면, 원인을 고친 뒤에도

        (예: 없던 태그를 만들었거나, `GROUP_LIMIT_REACHED`를 풀려고 그룹을 삭제했더라도) 같은

        거부가 그대로 돌아옵니다. 원인을 고친 뒤에는 새 `Idempotency-Key`로 보내세요.
      operationId: createSegment
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          description: 이 생성 시도를 식별하는 클라이언트 생성 고유 문자열(255자 이하)입니다. 위의 "멱등성" 항목을 참고하세요.
          schema:
            type: string
            maxLength: 255
          example: 550e8400-e29b-41d4-a716-446655440000
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSegmentRequest'
            example:
              name: 뉴스레터 독자 중 최근 활동한 사람
              filter:
                operator: AND
                conditions:
                  - field: tag
                    operator: has
                    value: newsletter
                requiredConditions:
                  - field: consent
                    operator: active
                excludeConditions:
                  - field: last_active
                    operator: inactive_for_days
                    value: 90
      responses:
        '201':
          description: 그룹을 만들었습니다. `memberCount`는 생성 시점의 실시간 수입니다.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SegmentDetail'
              example:
                id: 3d2b8a64-5e0f-4c71-b9a2-1f7e6c4d8a05
                name: 뉴스레터 독자 중 최근 활동한 사람
                filter:
                  operator: AND
                  conditions:
                    - field: tag
                      operator: has
                      value: newsletter
                  requiredConditions:
                    - field: consent
                      operator: active
                  excludeConditions:
                    - field: last_active
                      operator: inactive_for_days
                      value: 90
                memberCount: 124
                createdAt: '2026-10-22T03:14:15.926Z'
        '400':
          description: >
            `INVALID_JSON`(본문이 JSON이 아님), `IDEMPOTENCY_KEY_REQUIRED`,

            `IDEMPOTENCY_KEY_TOO_LONG` 또는 `VALIDATION_ERROR`(`name`이나 `filter`가
            잘못됨.

            `message`는 잘못된 부분의 경로로 시작하며, 예를 들어 `name:`이나

            `filter.conditions.2.value:`입니다. 원인에는 `name`이 없거나 비어 있음, 이름이

            100자 초과, NUL 문자, 본문·규칙·조건의 알 수 없는 키, 잘못된 값이나 타입, 조건이

            20개를 넘는 목록, UUID가 아닌 id, 조건이 허용하지 않는 키 조합이 있습니다).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: VALIDATION_ERROR
                  message: >-
                    filter.conditions.0.value: Number must be less than or equal
                    to 365
                  retryable: false
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            `PAST_DUE_RESTRICTED`, `PLAN_REQUIRED` 또는 `INSUFFICIENT_SCOPE`(키에
            `segments:write` 범위가 없습니다).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          $ref: '#/components/responses/NotOnAllowlist'
        '409':
          description: |
            `IDEMPOTENCY_KEY_CONFLICT`(재시도 불가: 같은 키가 이미 다른 본문으로 사용되었습니다.
            새 키를 사용하세요) 또는 `IDEMPOTENCY_KEY_IN_PROGRESS`(재시도 가능: 이 키의 요청이
            아직 처리 중입니다. `retryAfterSeconds`가 대기 시간을 안내합니다).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >
            요청 형식은 올바르지만 규칙을 사용할 수 없습니다. 아무것도 만들어지지 않았으며,

            어느 것도 그대로 재시도해서는 해결되지 않습니다.

            `EMPTY_FILTER`: 규칙의 세 목록 어디에도 조건이 없습니다.

            `CONDITION_NOT_SUPPORTED`: API가 아직 받지 않는 조건 타입(`custom_field`)이거나,

            그 조건이 들어 있는 목록에서 일부 연락처에 잘못된 답을 내는 조건 형태입니다(그룹

            조건 문서 참고). `details`는 `{ field, path }`이고, 두 번째 경우에는

            `{ operator, invertTo }`가 더해집니다(대신 쓸 수 있는 연산자가 없으면 `invertTo`는

            없습니다).

            `REFERENCE_NOT_FOUND`: 조건에 내 계정에 없는 id가 들어 있습니다(알 수 없는 id,

            삭제되었거나 휴지통에 있는 id, 다른 사람의 id는 모두 구분되지 않습니다).

            `details`는 `{ path, kind }`이고 `kind`는 `document`, `product`, `tier`,
            `cta`,

            `folder`, `broadcast`, `step` 중 하나입니다.

            `TAG_NOT_FOUND`: `tag` 조건이 내 계정에 없는 태그 이름을 가리킵니다(이름은 대소문자를

            포함해 정확히 일치해야 합니다). `details`는 `{ tag }`입니다. 태그 이름은

            `GET /api/preview/tags`로 확인하세요.

            `GROUP_REFERENCE_NOT_FOUND`: `group_membership` 조건이 내 계정에 없는 그룹을

            가리킵니다. `details`는 `{ groupIds }`입니다.

            `GROUP_LIMIT_REACHED`: 계정이 그룹 100개 한도에 도달했습니다. `details`는

            `{ limit }`입니다. 쓰지 않는 그룹을 대시보드에서 삭제한 뒤 새

            `Idempotency-Key`로 다시 시도하세요.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                emptyFilter:
                  value:
                    error:
                      code: EMPTY_FILTER
                      message: >-
                        The filter has no conditions. Add at least one
                        condition, or the group would match every contact
                      retryable: false
                conditionNotSupported:
                  value:
                    error:
                      code: CONDITION_NOT_SUPPORTED
                      message: >-
                        The custom_field condition is not supported through the
                        API yet. Remove it from the filter
                      retryable: false
                      details:
                        field: custom_field
                        path: filter.conditions.1
                referenceNotFound:
                  value:
                    error:
                      code: REFERENCE_NOT_FOUND
                      message: >-
                        A condition refers to something that is not in your
                        account
                      retryable: false
                      details:
                        path: filter.conditions.0.documentId
                        kind: document
                tagNotFound:
                  value:
                    error:
                      code: TAG_NOT_FOUND
                      message: A tag condition names a tag that is not in your account
                      retryable: false
                      details:
                        tag: newsletter
                groupReferenceNotFound:
                  value:
                    error:
                      code: GROUP_REFERENCE_NOT_FOUND
                      message: >-
                        A group condition refers to a group that is not in your
                        account
                      retryable: false
                      details:
                        groupIds:
                          - 9c1e4a7b-2d3f-4e58-a6b0-5f8d7c3e1a24
                groupLimitReached:
                  value:
                    error:
                      code: GROUP_LIMIT_REACHED
                      message: This account has reached its group limit
                      retryable: false
                      details:
                        limit: 100
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          description: >-
            `INTERNAL_ERROR`(재시도 가능). 서버 측 오류이며 원인은 응답에 포함되지 않습니다. 같은
            `Idempotency-Key`로 재시도하세요.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: |
            서버 측 의존 서비스가 일시적으로 중단되었습니다(`RATE_LIMIT_UNAVAILABLE` 또는
            `SERVICE_UNAVAILABLE`). 요청이나 키의 문제가 아닙니다. 항상 재시도할 수 있으며,
            `retryAfterSeconds`가 있으면 그 시간만큼 기다리세요.
            서비스가 너무 바빠 생성을 시작하지 못한 경우에도 `SERVICE_UNAVAILABLE`이 반환됩니다.
            이때는 아무것도 만들어지지 않았으며, 같은 `Idempotency-Key`로 안전하게 재시도할 수
            있습니다. 그룹 엔드포인트는 매우 무거운 규칙의 인원을 약 10초 안에 셀 수 없을 때도
            이 코드를 반환합니다. 규칙을 단순하게 만들거나 다시 시도하세요.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKey: []
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X POST 'https://docurise.io/api/preview/segments' \
              -H 'Authorization: Bearer dr_live_<keyId>_<secret>' \
              -H 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
              -H 'Content-Type: application/json' \
              -d '{
                "name": "뉴스레터 독자 중 최근 활동한 사람",
                "filter": {
                  "operator": "AND",
                  "conditions": [{ "field": "tag", "operator": "has", "value": "newsletter" }],
                  "requiredConditions": [{ "field": "consent", "operator": "active" }],
                  "excludeConditions": [{ "field": "last_active", "operator": "inactive_for_days", "value": 90 }]
                }
              }'
components:
  schemas:
    CreateSegmentRequest:
      type: object
      required:
        - name
        - filter
      additionalProperties: false
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
          description: >-
            그룹 이름. 앞뒤 공백을 제거하고 유니코드 정규화(NFC)한 뒤 1~100자여야 하며 NUL 문자를 포함할 수 없습니다.
            이름은 고유하지 않아도 됩니다.
          example: 뉴스레터 독자 중 최근 활동한 사람
        filter:
          $ref: '#/components/schemas/GroupFilter'
    SegmentDetail:
      type: object
      required:
        - id
        - name
        - filter
        - memberCount
        - createdAt
      description: 규칙과 실시간 멤버 수를 가진 그룹. 멤버 정보는 절대 반환하지 않습니다.
      properties:
        id:
          type: string
          format: uuid
          description: 그룹 id.
        name:
          type: string
          description: 그룹 이름.
        filter:
          $ref: '#/components/schemas/StoredGroupFilter'
        memberCount:
          type: integer
          minimum: 0
          description: 지금 그룹에 속한 연락처의 실시간 수(수신 거부 연락처 제외). 수치만 제공하며 연락처 자체는 반환하지 않습니다.
        createdAt:
          type: string
          format: date-time
          description: 그룹을 만든 시각. UTC 기준 RFC 3339.
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - retryable
          properties:
            code:
              type: string
              description: 안정적인 기계 판독용 에러 코드입니다 — `message`가 아니라 이 값을 기준으로 분기하세요.
            message:
              type: string
              description: 사람이 읽을 수 있는 상세 설명입니다. 예고 없이 문구가 바뀔 수 있습니다.
            retryable:
              type: boolean
              description: 동일한 요청을 재시도했을 때 성공할 가능성이 있는지 여부입니다.
            retryAfterSeconds:
              type: integer
              description: 구체적인 백오프 힌트가 있는 경우에만 존재합니다.
            details:
              type: object
              description: >
                일부 특정 코드에만 존재합니다:

                - `PROTECTION_RULE_CONFLICT`: `{ rule: string }`, 요청을 거부한 보호
                규칙입니다
                  (`form`, `restricted_access`, `paid_lead_gate`, `free_lead_gate` 또는 `form_no_access_controls`).
                  열려 있는 값입니다. 새 값을 허용하세요.
                - `NEXT_POST_RULE_EXISTS`: `{ ruleId: string }`, 이미 있는 "다음 게시물"
                규칙입니다.

                - `NOTION_FETCH_FAILED`: `{ notionErrorCode: string }`, 다음 중
                하나입니다:
                  `NOTION_ERROR_PRIVATE`, `NOTION_ERROR_NOT_FOUND`,
                  `NOTION_ERROR_NETWORK`, `NOTION_ERROR_RATE_LIMIT`,
                  `NOTION_ERROR_TEMPORARILY_UNAVAILABLE`,
                  `NOTION_ERROR_PAGE_REJECTED`, `NOTION_ERROR_UNKNOWN`.
                - `HTML_REJECTED`: `{ reason: string }`, `too_large`,
                `css_rejected`, `invalid` 중 하나입니다.
                  열려 있는 값입니다. 새 값을 허용하세요.
                - `CONDITION_NOT_SUPPORTED`: `{ field: string, path: string }`,
                받지 않는 조건 타입과 그 조건이
                  요청에서 있는 위치입니다. 그 위치에서 거부된 조건 형태에는 `operator: string`이,
                  `requiredConditions`에서 대신 쓸 수 있는 연산자가 있으면 `invertTo: string`도 더해집니다.
                - `REFERENCE_NOT_FOUND`: `{ path: string, kind: string }`, 알 수
                없는 id가 요청에서 있는 위치와
                  그 id가 가리키는 대상(`document`, `product`, `tier`, `cta`, `folder`, `broadcast`, `step`)입니다.
                  열려 있는 값입니다. 새 값을 허용하세요.
                - `TAG_NOT_FOUND`(그룹 규칙에서): `{ tag: string }`, 존재하지 않는 태그 이름입니다.

                - `GROUP_REFERENCE_NOT_FOUND`: `{ groupIds: string[] }`, 계정에 없는
                그룹 id입니다.

                - `GROUP_LIMIT_REACHED`: `{ limit: integer }`, API로 계정이 만들 수 있는
                그룹의 최대 개수입니다.
          description: >-
            오류 정보입니다. API의 모든 오류 응답에 들어 있으며 `code`, `message`, `retryable`을 담고,
            일부 코드에는 `retryAfterSeconds`와 `details`도 담깁니다.
    GroupFilter:
      type: object
      required:
        - operator
        - conditions
      additionalProperties: false
      description: |
        누가 그룹에 속하는지 정하는 규칙입니다. 연락처는 `conditions`에 해당하고
        (`operator`로 연결), `requiredConditions`의 모든 조건에 해당하며,
        `excludeConditions`의 어느 것에도 해당하지 않을 때 그룹에 속합니다. 각 목록에는
        조건을 최대 20개까지 넣을 수 있고, 세 목록을 통틀어 조건이 하나 이상 있어야 합니다
        (없으면 `422 EMPTY_FILTER`). 수신 거부 연락처는 멤버가 되지 않습니다.
        [그룹 조건](/ko/api-reference/group-conditions)을 참고하세요.
      properties:
        operator:
          type: string
          enum:
            - AND
            - OR
          description: '`conditions`의 조건을 연결하는 방식. `AND`(모두 해당) 또는 `OR`(하나라도 해당).'
        conditions:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/GroupCondition'
          description: >-
            기본 조건 목록. `requiredConditions`나 `excludeConditions`에 조건이 있으면 비어 있어도
            됩니다.
        requiredConditions:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/GroupCondition'
          description: 모든 멤버가 추가로 만족해야 하는 조건. `operator`와 상관없이 항상 AND로 적용됩니다.
        excludeConditions:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/GroupCondition'
          description: >-
            연락처를 제외하는 조건. 하나라도 해당하는 연락처는 빠집니다. 일부 조건 형태는 여기서 거부됩니다(`422
            CONDITION_NOT_SUPPORTED`). [그룹
            조건](/ko/api-reference/group-conditions)을 참고하세요.
    StoredGroupFilter:
      type: object
      additionalProperties: true
      description: >
        저장된 규칙을 저장된 그대로 나타내며, `GET /api/preview/segments/{id}`가 반환하는

        값입니다. 보낼 수 있는 규칙인 `GroupFilter`와 달리 목록 길이에 제한이 없고, 조건은

        모든 타입일 수 있습니다(`StoredGroupCondition`). 저장된 그룹은 API의 규칙을 따르지 않기 때문입니다. 규칙
        없이 저장된 그룹은 `{}`로

        반환됩니다.
      properties:
        operator:
          type: string
          enum:
            - AND
            - OR
          description: '`conditions`의 조건을 연결하는 방식. `AND`(모두 해당) 또는 `OR`(하나라도 해당).'
        conditions:
          type: array
          items:
            $ref: '#/components/schemas/StoredGroupCondition'
          description: 기본 조건 목록.
        requiredConditions:
          type: array
          items:
            $ref: '#/components/schemas/StoredGroupCondition'
          description: 모든 멤버가 추가로 만족해야 하는 조건.
        excludeConditions:
          type: array
          items:
            $ref: '#/components/schemas/StoredGroupCondition'
          description: 연락처를 제외하는 조건.
    GroupCondition:
      type: object
      required:
        - field
      additionalProperties: true
      description: |
        규칙의 조건 하나입니다. 조건 타입을 나타내는 필수 `field`와 그 타입이 받는 키(예:
        `operator`, `value`)로 이루어진 객체입니다. 20가지 타입, 각 타입의 키와 허용 값, 필요한
        id를 찾는 방법은 [그룹 조건](/ko/api-reference/group-conditions)에 있습니다. 두 곳의
        내용이 어긋나지 않도록 이 스키마에는 `field`만 적었습니다. 서버는 모든 조건을
        엄격하게 검사합니다. 알 수 없는 키, 잘못된 값, 타입이 허용하지 않는 키 조합은 경로가
        표시된 `400 VALIDATION_ERROR`입니다. `custom_field` 조건은
        `422 CONDITION_NOT_SUPPORTED`로 거부되며, 들어 있는 목록에서 일부 연락처에 잘못된 답을
        내는 일부 조건 형태(그룹 조건 문서 참고)도 마찬가지입니다.
      properties:
        field:
          type: string
          enum:
            - tag
            - document_view
            - consent
            - cta_click
            - email_open
            - email_link_click
            - has_phone
            - form_submission
            - payment_status
            - first_seen
            - last_active
            - group_membership
            - tier_access
            - days_since_purchase
            - repeat_bounce
            - course_last_access
            - kakao_reachable
            - course_progress
            - location
            - checkout_abandoned
          description: 조건 타입.
      example:
        field: tag
        operator: has
        value: newsletter
    StoredGroupCondition:
      type: object
      required:
        - field
      additionalProperties: true
      description: |
        저장된 규칙의 조건 하나를 저장된 그대로 나타냅니다. 보낼 수 있는 조건인
        `GroupCondition`과 달리 `field`는 모든 조건 타입일 수 있으며, API가
        만들 수 없는 `custom_field`도 포함됩니다. 각 타입의 키는
        [그룹 조건](/ko/api-reference/group-conditions)에 있습니다.
      properties:
        field:
          type: string
          description: 조건 타입. 그룹 조건 문서의 20가지 타입 중 하나이거나 `custom_field`입니다.
      example:
        field: custom_field
        questionId: q9f2k1x7ab
        operator: exists
  responses:
    Unauthorized:
      description: '누락되었거나 형식이 잘못되었거나 폐기된 API 키입니다(`code: UNAUTHORIZED`).'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotOnAllowlist:
      description: |
        API는 일부 계정에서만 사용이 가능하며, 요금제와는 별개입니다. 사용할 수
        있어야 하는 계정이라면 DocuRise 담당자에게 문의하세요 (`code: NOT_FOUND`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: >-
        속도 제한에 걸렸습니다 (`code: RATE_LIMITED`, 항상 재시도 가능): `Retry-After` 헤더와
        `X-RateLimit-*` 헤더를 참고하세요. 또는 동시에 실행 중인 요청이 너무 많습니다 (`code:
        TOO_MANY_CONCURRENT_REQUESTS`, 항상 재시도 가능): `Retry-After`는 `1`이고
        `X-RateLimit-*` 헤더는 없습니다.
      headers:
        Retry-After:
          schema:
            type: integer
        X-RateLimit-Limit:
          schema:
            type: integer
        X-RateLimit-Remaining:
          schema:
            type: integer
        X-RateLimit-Reset:
          schema:
            type: integer
          description: 제한이 초기화되는 유닉스 타임스탬프(초)입니다.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: dr_live_<keyId>_<secret>
      description: |
        Settings → Developers에서 발급한 키를 `Authorization: Bearer
        dr_live_<12자리 16진수>_<64자리 16진수>` 형태로 전송합니다. 키는 명시적인 범위를
        가지며 — 각 엔드포인트에 필요한 범위가 해당 엔드포인트에 명시되어 있습니다. 전체 키는 발급 시점에 딱 한
        번만 표시되며 다시 조회할 수 없습니다 — 이후에는 `keyId` 접두어만 표시됩니다. 폐기된
        키는 바로 다음 요청부터 인증에 실패합니다.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.