메인 콘텐츠로 건너뛰기

Base URL

https://api.lexq.io/api/v1/execution
실행 API의 Base URL(/api/v1/execution)은 관리 API(/api/v1/partners)와 다릅니다. 각 API에 맞는 Base URL을 사용하세요.

인증

관리 API와 동일한 API Key를 사용합니다. 모든 요청에 포함하세요:
x-api-key: YOUR_API_KEY

실행 모드

모드엔드포인트용도
단일 그룹POST /groups/{groupId}일반적인 단건 주문 평가
특정 버전POST /groups/{groupId}/versions/{versionId}A/B 테스트, 롤백 테스트
배치POST /groups/{groupId}/batch장바구니 계산, 상품 목록 혜택 표기
복합POST /composite다중 그룹 동시 평가 (할인 + 쿠폰 + 배송비)

단일 그룹 실행

현재 배포된 버전의 모든 활성 규칙을 평가합니다.
POST /groups/{groupId}

요청

curl -X POST https://api.lexq.io/api/v1/execution/groups/{groupId} \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-12345" \
  -d '{
    "facts": {
      "user_id": "user_abc",
      "payment_amount": 150000,
      "customer_tier": "VIP"
    },
    "context": {
      "channel": "mobile-app"
    }
  }'
필드타입필수설명
factsobject규칙 평가를 위한 입력 변수
contextobject추가 메타데이터 (조건에 사용되지 않으며 액션에 전달)

응답

{
  "result": "SUCCESS",
  "data": {
    "traceId": "2e31f2b8-...",
    "inputFacts": {
      "user_id": "user_abc",
      "payment_amount": 150000,
      "customer_tier": "VIP"
    },
    "mutatedFacts": {
      "payment_amount": 135000
    },
    "generatedVariables": {
      "payment_amount__delta": -15000
    },
    "executionTraces": [
      {
        "tenantId": "acme-corp",
        "policyGroupId": "01f2b274-...",
        "policyVersionId": "a6062090-...",
        "ruleId": "3b16ced1-...",
        "ruleName": "VIP 10% 할인",
        "executedAt": "2026-04-27T09:44:10Z",
        "matched": true,
        "matchExpression": "(customer_tier == 'VIP') && (payment_amount >= 100000)",
        "inputFacts": {
          "customer_tier": "VIP",
          "payment_amount": 150000
        },
        "generatedActions": [
          {
            "type": "MUTATE_FACT",
            "parameters": { "refVar": "payment_amount", "operator": "SUB", "method": "PERCENTAGE", "rate": 10 }
          }
        ]
      }
    ],
    "decisionTraces": [
      {
        "ruleId": "3b16ced1-...",
        "ruleName": "VIP 10% 할인",
        "policyGroupId": "01f2b274-...",
        "policyVersionId": "a6062090-...",
        "status": "SELECTED",
        "reasonCode": "FINAL_WINNER",
        "reasonDetail": null
      }
    ]
  }
}
data.traceId는 이 실행의 감사 핸들입니다 — 나중에 이 실행을 추적하려면 자체 레코드와 함께 저장하세요. 응답의 data 객체는 상태를 세 층위로 분리합니다:
  • inputFacts — 요청에서 받은 입력 팩트 (정규화 후).
  • mutatedFacts — 규칙 액션에 의해 값이 변경된 팩트만.
  • generatedVariables — 규칙 액션이 새로 생성한 변수 (입력에 없었던 것). 액션별 변화 키도 포함됩니다 — {refVar}__delta(MUTATE_FACT의 부호 포함 변화량)와 {targetVar}__delta(INCREMENT_FACT의 0 이상 증분량).
이렇게 분리하면 감사·재현·디버그가 결정적입니다 — 어떤 값이 어디서 왔는지가 항상 명확합니다. 합본이 필요하면 { ...inputFacts, ...mutatedFacts, ...generatedVariables }로 재구성하세요.

멱등성

Idempotency-Key 헤더를 포함하면 중복 실행을 방지합니다. 동일한 키로 이미 처리된 요청이 있으면, 정책을 재실행하지 않고 원래 응답을 반환합니다.

특정 버전 실행

트래픽 라우팅을 우회하여 정책 그룹의 특정 버전을 실행합니다. A/B 테스트 후보 버전 검증이나 롤백 전 이전 버전 테스트에 유용합니다.
POST /groups/{groupId}/versions/{versionId}
요청과 응답 형식은 단일 그룹 실행과 동일합니다. 현재 배포된 버전 대신 지정된 버전을 사용하는 것만 다릅니다.
버전은 ACTIVE (발행됨) 상태여야 합니다. DRAFT 버전은 Engine API로 실행할 수 없습니다 — DRAFT 테스트에는 드라이런을 사용하세요.

배치 실행

여러 팩트 세트를 동일한 정책 그룹에 대해 한 번의 호출로 실행합니다. 일관성을 위해 배치 내 모든 요청이 동일 버전으로 평가됩니다.
POST /groups/{groupId}/batch

요청

curl -X POST https://api.lexq.io/api/v1/execution/groups/{groupId}/batch \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "requests": [
      { "facts": { "user_id": "user_1", "payment_amount": 50000 } },
      { "facts": { "user_id": "user_2", "payment_amount": 150000 } },
      { "facts": { "user_id": "user_3", "payment_amount": 300000 } }
    ],
    "sharedContext": {
      "channel": "batch-job"
    }
  }'
필드타입필수설명
requestsarray평가할 팩트 세트 목록
sharedContextobject모든 요청에 병합되는 공유 컨텍스트

응답

{
  "result": "SUCCESS",
  "data": {
    "results": [
      { "inputFacts": { ... }, "mutatedFacts": { ... }, "generatedVariables": { ... }, "executionTraces": [ ... ], "decisionTraces": [ ... ] },
      { "inputFacts": { ... }, "mutatedFacts": { ... }, "generatedVariables": { ... }, "executionTraces": [ ... ], "decisionTraces": [ ... ] },
      { "inputFacts": { ... }, "mutatedFacts": { ... }, "generatedVariables": { ... }, "executionTraces": [ ... ], "decisionTraces": [ ... ] }
    ],
    "totalProcessingTimeMs": 45
  }
}
결과는 입력 요청과 동일한 순서로 반환됩니다. 각 요청의 context는 sharedContext와 병합됩니다 (개별 요청 컨텍스트가 충돌 시 우선).
배치 실행은 TPS 스로틀링에서 아이템 수와 관계없이 1회 API 호출로 계산됩니다. 단, 과금은 총 아이템 수 기준입니다.

복합 실행

동일한 팩트를 여러 정책 그룹에 대해 한 번의 호출로 평가합니다. 하나의 거래가 여러 정책 검사를 동시에 통과해야 할 때 사용합니다 (예: 상품할인 + 장바구니쿠폰 + 배송비 + 멤버십적립).
POST /composite

요청

curl -X POST https://api.lexq.io/api/v1/execution/composite \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-12345-composite" \
  -d '{
    "targetGroupIds": ["group-discount-id", "group-coupon-id", "group-shipping-id"],
    "facts": {
      "user_id": "user_abc",
      "payment_amount": 250000
    },
    "context": {
      "channel": "checkout"
    }
  }'
필드타입필수설명
targetGroupIdsarray평가할 정책 그룹 ID 목록
factsobject모든 그룹에 공유되는 입력 팩트
contextobject모든 그룹에 공유되는 컨텍스트
응답에는 평가된 모든 그룹의 inputFacts, mutatedFacts, generatedVariables, executionTraces, decisionTraces가 병합되어 포함됩니다. 모든 대상 그룹이 ACTIVE 상태여야 합니다.

필수 팩트 조회

실행 엔드포인트를 호출하기 전에 배포된 버전이 어떤 입력 팩트를 필요로 하는지 확인합니다.
GET /groups/{groupId}/requirements
curl https://api.lexq.io/api/v1/execution/groups/{groupId}/requirements \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept-Language: ko"
Accept-Language 헤더로 usedBy 설명의 언어를 제어합니다 (en 또는 ko).

응답

{
  "result": "SUCCESS",
  "data": {
    "groupId": "01f2b274-...",
    "versionId": "a6062090-...",
    "versionNo": 5,
    "requiredFacts": [
      {
        "key": "payment_amount",
        "type": "NUMBER",
        "displayName": "결제 금액",
        "usedBy": [
          "조건 [GREATER_THAN_OR_EQUAL] (규칙: VIP 10% 할인)",
          "MUTATE_FACT 액션 (규칙: VIP 10% 할인)"
        ]
      },
      {
        "key": "customer_tier",
        "type": "STRING",
        "displayName": "고객 등급",
        "usedBy": [
          "조건 [EQUALS] (규칙: VIP 10% 할인)"
        ]
      }
    ],
    "exampleRequest": {
      "facts": { "payment_amount": 50000, "customer_tier": "" },
      "context": { "reqTime": "2025-01-01T00:00:00Z" }
    }
  }
}
첫 연동 전에 이 엔드포인트를 호출하여 필요한 팩트를 확인하세요. exampleRequest를 시작 템플릿으로 복사하고 실제 값을 채워 넣으면 됩니다.

시스템 팩트

모든 테넌트는 계정 생성 시 3개의 시스템 팩트가 자동 등록됩니다. 수동 생성이 필요 없습니다:
타입설명
user_idSTRING사용자 ID
emailSTRING이메일 주소
user_tagsLIST_STRING사용자 태그
각 팩트가 실제 실행에서 필수인지는 배포된 버전의 어떤 규칙이 그 팩트를 참조하느냐에 달려 있습니다. 정확히 어떤 팩트가 필요한지는 GET /groups/{groupId}/requirements를 호출해 확인하세요. 그 외 모든 팩트(예: payment_amount, customer_tier, order_region)는 사용자가 정의하며, 사용 전에 팩트 정의에서 등록해야 합니다.

오류 처리

모든 오류는 동일한 envelope 형태를 따릅니다:
{ "result": "ERROR", "code": "P-001", "message": "정책 그룹을 찾을 수 없습니다." }
실행 엔드포인트에서 가장 자주 마주치는 오류:
HTTP코드발생 조건
401A-003x-api-key 헤더가 누락되거나 변조·폐기됨
404P-001groupId가 존재하지 않거나 다른 tenant 소속
403P-009그룹은 존재하지만 DISABLED 상태
400P-019그룹에 배포된 버전이 없음 — 먼저 버전을 배포해야 함
404P-002(특정 버전 모드) versionId가 존재하지 않음
400P-016(특정 버전 모드) 버전이 대상 그룹에 속하지 않음
400P-015필수 입력 팩트 누락 — /requirements로 확인
400C-001요청 본문 형식 오류 또는 검증 실패
400P-003평가 도중 액션 실행에서 오류 발생
409I-001Idempotency-Key로 이미 처리됨 (원본 응답 반환)
409I-002동일 키 요청이 처리 중 — 잠시 후 재시도
403B-008현재 플랜의 월 실행 한도 도달
429C-007플랜의 최대 TPS 초과
전체 도메인(인증·빌링·시뮬레이션 등)에 걸친 코드 레지스트리는 에러 레퍼런스를 참조하세요.

다음 단계

드라이런

라이브 전에 부작용 없이 규칙을 테스트합니다.

팩트 정의

규칙에 사용할 커스텀 입력 변수를 등록합니다.