캠페인 API

알림톡 캠페인을 생성·조회하고, 제목·상태·발송 설정·기존 템플릿·상품필터를 안전하게 변경합니다.

전체 캠페인 객체를 덮어쓰지 않습니다 각 변경 API는 요청한 영역만 수정합니다. 상품필터를 변경해도 기존 템플릿, 변수 매핑, 쿠폰 조건, 발신프로필, 트리거와 활성 상태는 보존됩니다. 같은 템플릿 코드를 다시 지정한 경우에도 기존 캠페인 매핑은 그대로 유지됩니다.
동시 수정 보호 변경 전 조회 응답의 revision을 If-Match 헤더로 보내야 합니다. 그 사이 콘솔이나 다른 요청이 설정을 바꾸면 4092로 거절됩니다. 최신 상태를 다시 조회한 뒤 재시도하세요.

공통 요청 정보

Base URL필수string

https://docs.almani-center.com/open/v1

Authorization필수header

Bearer ak_live_xxxx 형식의 API 키입니다. 조회는 campaign:read, 변경은 campaign:write 스코프가 필요합니다.

X-Site-Id필수header

캠페인이 속한 알마니 사이트 ID입니다. 다른 사이트의 캠페인은 존재 여부를 노출하지 않고 4040을 반환합니다.

If-Match수정 시 필수header

조회 응답의 revision입니다. 상태·캠페인 설정·템플릿 변경에는 cp_, 상품필터 PATCH·PUT에는 pf_ revision을 사용합니다. 생성 요청에는 사용하지 않습니다.

Idempotency-Key생성 시 필수header

네트워크 재시도로 같은 캠페인이 중복 생성되지 않도록 요청마다 고유한 값을 사용합니다. 수정 요청에도 사용을 권장합니다. 최대 100자이며 동일 키에 다른 요청 본문을 사용할 수 없습니다.

revision을 구분해서 사용하세요 캠페인 상세의 cp_ revision은 상태·캠페인 설정·템플릿용이고, 상품필터 조회의 pf_ revision은 상품필터용입니다. 서로 바꿔 보내면 4092가 반환됩니다.

권장 작업 순서

  1. 상품 검색으로 추가할 productId와 옵션을 확인합니다.
  2. 캠페인 또는 상품필터를 조회해 현재 조건과 revision을 저장합니다.
  3. 조회한 revision을 If-Match에 넣고 고유한 Idempotency-Key와 함께 변경 요청을 보냅니다.
  4. 적용 후 다시 조회해 캠페인 설정과 상품 수를 확인합니다.

캠페인 생성

POST/campaigns

필요 스코프: campaign:write

사이트에서 사용할 수 있는 트리거와 기존 승인 템플릿으로 새 알림톡 캠페인을 만듭니다.

생성된 캠페인은 항상 꺼진 상태입니다 요청에 활성 상태를 받지 않으며 응답의 active는 항상 false입니다. 생성 결과를 확인한 뒤 응답의 revision으로 캠페인 켜기·끄기 API를 호출하세요.

Request Body

title필수string

콘솔에 표시할 제목입니다. 최대 200자이며 같은 사이트의 미삭제 캠페인 제목과 중복될 수 없습니다. 앞뒤 공백과 영문 대소문자는 중복 검사에서 구분하지 않습니다.

triggerEvent필수string

결제 완료·배송 시작 등 발송 트리거 코드입니다. 현재 사이트 전용 또는 사이트 플랫폼에서 활성화된 트리거만 사용할 수 있습니다.

templateCode필수string

해당 사이트에서 사용할 수 있는 승인(APR)·활성(A) 템플릿 코드입니다. 템플릿의 변수 매핑과 이미지 유형을 캠페인에 적용합니다.

sendTiming필수object

type은 IMMEDIATE 또는 DELAYED입니다. 지연 발송이면 delay.unit(MINUTE/HOUR/DAY)과 1 이상의 delay.value가 필요합니다.

productFilter선택object | null

상품필터 전체 교체와 같은 mode·groupJoin·groups 구조입니다. 생략하거나 null이면 모든 상품이 대상입니다. 상품과 옵션은 현재 사이트 데이터로 검증합니다.

quietHours선택object

생략하면 발송 제한시간을 사용하지 않습니다. 활성화 시 start, end, behavior가 필요합니다.

adminSendEnabled선택boolean

관리자 발송 사용 여부이며 기본값은 false입니다.

저장 전에 플랫폼·트리거 정합성, 발신프로필 상태, 템플릿 승인·활성 상태, 상품과 옵션을 모두 검사합니다. 하나라도 유효하지 않으면 캠페인은 생성되지 않습니다.

요청 예시
curl -X POST "https://docs.almani-center.com/open/v1/campaigns" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467" \
  -H "Idempotency-Key: 864ba612-5c53-4f08-9d12-3029b4d9e272" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "결제 완료 고객 안내",
  "triggerEvent": "cafe24Purchase",
  "templateCode": "TPL_4593319557",
  "sendTiming": {
    "type": "DELAYED",
    "delay": {"unit": "HOUR", "value": 1}
  },
  "productFilter": {
    "mode": "INCLUDE",
    "groupJoin": "OR",
    "groups": [{
      "operator": "OR",
      "products": [
        {"productId": "27", "variantIds": []},
        {"productId": "49", "variantIds": ["49-A"]}
      ]
    }]
  }
}'
응답 data 예시
{
  "campaignId": 8112,
  "title": "결제 완료 고객 안내",
  "active": false,
  "triggerEvent": "cafe24Purchase",
  "channel": "AT",
  "template": {
    "templateCode": "TPL_4593319557",
    "templateName": "결제 완료 안내",
    "approveStatus": "APR",
    "templateStatus": "A",
    "sendable": true
  },
  "settings": {
    "sendTiming": {"type":"DELAYED","delay":{"unit":"HOUR","value":1}},
    "quietHours": {"enabled":false,"start":null,"end":null,"behavior":null},
    "adminSendEnabled": false
  },
  "productFilterSummary": {
    "mode":"INCLUDE","groupCount":1,"productCount":2,"variantCount":1
  },
  "revision": "cp_3eb7...",
  "createdAt": "2026-09-04T16:20:00+09:00"
}

캠페인 목록 조회

GET/campaigns

필요 스코프: campaign:read

선택한 사이트의 자동 알림톡 캠페인만 반환합니다. 테스트 캠페인과 직접 API 발송용 캠페인은 제외됩니다.

Query 파라미터

active선택boolean

활성 여부 필터.

triggerEvent선택string

결제완료·배송시작 등 저장된 트리거 코드의 정확 일치.

templateCode선택string

현재 사용 중인 템플릿 코드.

hasProductFilter선택boolean

상품필터 저장 여부.

keyword / limit / cursor선택

제목 또는 캠페인 ID 검색과 커서 페이지네이션. 기본 20, 최대 100.

주요 응답 필드

items[].campaignId / titleinteger / string

캠페인 ID와 콘솔에 표시되는 제목입니다.

items[].active / triggerEvent / channelboolean / string

활성 여부, 트리거 이벤트와 채널 코드(AT 또는 AI)입니다.

items[].templateobject

현재 템플릿의 코드·이름·승인 상태·활성 상태와 발송 가능 여부입니다.

items[].productFilterSummaryobject

필터 모드와 그룹·상품·지정 옵션 수를 요약합니다.

items[].revisionstring

제목·상태·설정·템플릿 변경에 사용할 cp_ revision입니다.

nextCursorstring | null

다음 페이지가 없으면 null입니다.

요청 예시
curl "https://docs.almani-center.com/open/v1/campaigns?active=true" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467"
응답 예시
{
  "code": "0000",
  "data": {
    "items": [{
      "campaignId": 3541,
      "title": "결제 완료",
      "active": true,
      "triggerEvent": "PAY_COMPLETE",
      "channel": "AT",
      "template": {
        "templateCode": "MEARI_ORDER",
        "templateName": "주문 안내",
        "approveStatus": "APR",
        "templateStatus": "A",
        "sendable": true
      },
      "productFilterSummary": {
        "mode": "INCLUDE",
        "groupCount": 1,
        "productCount": 1,
        "variantCount": 0
      },
      "revision": "cp_91a3..."
    }],
    "nextCursor": null
  }
}

캠페인 상세 조회

GET/campaigns/{campaignId}

필요 스코프: campaign:read

제목, 상태, 트리거, 현재 템플릿과 발송 설정을 조회합니다. 반환된 revision은 제목·상태·설정·템플릿 변경의 If-Match 값입니다.

settings.sendTiming.type은 IMMEDIATE 또는 DELAYED, 제한시간 처리 방식은 QUEUE 또는 CANCEL입니다.

상품필터 revision은 별도입니다상세의 revision으로 상품필터를 수정하지 마세요. 상품필터는 상품필터 조회에서 받은 pf_ revision을 사용합니다.
요청 예시
curl "https://docs.almani-center.com/open/v1/campaigns/3541" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467"
응답 data 예시
{
  "campaignId": 3541,
  "title": "결제 완료",
  "content": "#{고객명}님, 주문이 완료되었습니다.",
  "active": true,
  "triggerEvent": "PAY_COMPLETE",
  "channel": "AT",
  "template": {
    "templateCode": "MEARI_ORDER",
    "approveStatus": "APR",
    "templateStatus": "A",
    "sendable": true
  },
  "settings": {
    "sendTiming": {"type":"IMMEDIATE","delay":null},
    "quietHours": {
      "enabled": true,
      "start": "21:00",
      "end": "08:00",
      "behavior": "QUEUE"
    },
    "adminSendEnabled": true
  },
  "productFilterSummary": {
    "mode":"INCLUDE",
    "groupCount":1,
    "productCount":1,
    "variantCount":0
  },
  "revision": "cp_91a3...",
  "createdAt": "2026-08-01T10:00:00+09:00",
  "updatedAt": "2026-08-29T10:20:00+09:00"
}

캠페인 켜기·끄기

PATCH/campaigns/{campaignId}/status

필요 스코프: campaign:write

active만 변경합니다. 활성화할 때는 발신프로필, 승인·활성 템플릿, 상품과 옵션의 유효성을 다시 검증합니다.

Request Body

active필수boolean

true면 활성화하고 false면 중지합니다. 현재 값과 같으면 성공 응답의 result가 UNCHANGED입니다.

활성화 검증true로 바꿀 때 발신프로필·템플릿·상품·옵션 중 하나라도 사용할 수 없으면 4222로 거절되며 상태는 바뀌지 않습니다.
요청 예시
curl -X PATCH "https://docs.almani-center.com/open/v1/campaigns/3541/status" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467" \
  -H "If-Match: cp_91a3..." \
  -H "Idempotency-Key: 4ea45671-7b3d-44cc-84be-75cae7681109" \
  -H "Content-Type: application/json" \
  -d '{"active":false}'
응답 data 예시
{
  "campaignId": 3541,
  "previousActive": true,
  "active": false,
  "result": "UPDATED",
  "revision": "cp_a44d...",
  "updatedAt": "2026-08-29T11:10:00+09:00"
}

캠페인 설정 변경

PATCH/campaigns/{campaignId}/settings

필요 스코프: campaign:write

캠페인 제목, 발송 시점, 발송 제한시간, 관리자 발송 사용 여부 중 보낸 항목만 변경합니다. 트리거 이벤트는 이 API로 변경할 수 없습니다.

title선택string

새 캠페인 제목입니다. 앞뒤 공백을 제거한 뒤 최대 200자까지 저장합니다. 같은 사이트의 미삭제 캠페인과 중복될 수 없으며 공백과 영문 대소문자는 구분하지 않습니다.

sendTiming.typeIMMEDIATE | DELAYED

지연 발송이면 delay.unit(MINUTE/HOUR/DAY)과 1 이상의 delay.value가 필요합니다.

quietHoursobject

활성화 시 start, end(HH:mm), behavior(QUEUE/CANCEL)가 모두 필요합니다.

adminSendEnabled선택boolean

관리자 직접 발송 사용 여부입니다.

네 항목 중 하나 이상을 보내야 하며, 보내지 않은 설정은 기존 값을 유지합니다. 다른 사이트에는 같은 캠페인 제목을 사용할 수 있습니다.

요청 예시
curl -X PATCH "https://docs.almani-center.com/open/v1/campaigns/3541/settings" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467" \
  -H "If-Match: cp_91a3..." \
  -H "Idempotency-Key: 42aba62d-3fb4-42d7-8d50-3a0ab2f2a790" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "결제 완료 고객 안내",
  "sendTiming": {
    "type": "DELAYED",
    "delay": {"unit": "HOUR", "value": 1}
  },
  "quietHours": {
    "enabled": true,
    "start": "21:00",
    "end": "08:00",
    "behavior": "QUEUE"
  },
  "adminSendEnabled": true
}'
응답 data 예시
{
  "campaignId": 3541,
  "result": "UPDATED",
  "revision": "cp_0d32...",
  "updatedAt": "2026-08-29T11:15:00+09:00"
}

캠페인에서 사용할 템플릿 변경

PATCH/campaigns/{campaignId}/template

필요 스코프: campaign:write

템플릿 내용을 수정하는 API가 아닙니다캠페인이 참조할 기존 템플릿을 다른 템플릿으로 교체합니다. 템플릿의 문구·버튼·검수 상태 자체는 변경하지 않습니다.

해당 사이트에서 사용할 수 있는 승인(APR)·활성(A) 템플릿만 지정할 수 있습니다. 다른 템플릿으로 교체하면 선택한 템플릿의 현재 변수 매핑과 이미지 유형을 캠페인에 적용합니다.

사용할 템플릿은 먼저 템플릿 목록 조회에서 승인 상태와 코드를 확인하세요.

Request Body

templateCode필수string

같은 사이트에서 사용할 수 있는 승인·활성 템플릿 코드입니다. 최대 100자입니다.

현재 템플릿 재선택현재와 같은 templateCode이면 UNCHANGED를 반환하고 기존 캠페인 변수 매핑을 건드리지 않습니다.
요청 예시
curl -X PATCH "https://docs.almani-center.com/open/v1/campaigns/3541/template" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467" \
  -H "If-Match: cp_91a3..." \
  -H "Idempotency-Key: c7e55bf9-0d82-424c-948d-d606f0fe28b7" \
  -H "Content-Type: application/json" \
  -d '{"templateCode":"MEARI_SHIPPING"}'
응답 data 예시
{
  "campaignId": 3541,
  "result": "UPDATED",
  "revision": "cp_602b...",
  "updatedAt": "2026-08-29T11:20:00+09:00"
}

상품필터 조회

GET/campaigns/{campaignId}/product-filter

필요 스코프: campaign:read

저장 형식의 차이를 숨기고 ALL, INCLUDE, EXCLUDE 구조로 정규화해 반환합니다. 이 응답의 revision은 상품필터 PATCH·PUT에 사용합니다.

filter.modeALL | INCLUDE | EXCLUDE

ALL은 모든 상품, INCLUDE는 포함 상품만, EXCLUDE는 지정 상품을 제외한 대상입니다.

filter.groupJoinOR | AND

여러 그룹을 결합하는 방식입니다.

filter.groups[].operatorOR | AND

한 그룹 안의 상품 조건 결합 방식입니다.

filter.groups[].products[].variantsarray

빈 배열이면 상품의 모든 옵션, 값이 있으면 해당 옵션만 대상입니다.

요청 예시
curl "https://docs.almani-center.com/open/v1/campaigns/3541/product-filter" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467"
응답 data 예시
{
  "campaignId": 3541,
  "revision": "pf_d19b...",
  "filter": {
    "version": 4,
    "mode": "INCLUDE",
    "groupJoin": "OR",
    "groups": [{
      "operator": "OR",
      "products": [{
        "productId": "27",
        "productCode": "P00000BB",
        "productName": "다이어리",
        "variants": []
      }]
    }]
  }
}

상품필터에 상품 추가·제거

PATCH/campaigns/{campaignId}/product-filter

필요 스코프: campaign:write

ADD_PRODUCTS 또는 REMOVE_PRODUCTS를 지정합니다. 중복 추가는 UNCHANGED로 처리됩니다.

ALL 모드는 부분 변경할 수 없으며 PUT으로 전체 필터를 정의해야 합니다. 마지막 상품 제거도 대상이 전체 상품으로 넓어지는 사고를 막기 위해 거절됩니다.

Request Body

operation필수ADD_PRODUCTS | REMOVE_PRODUCTS

상품 추가 또는 제거 작업입니다.

groupIndex필수integer

상품필터 조회 응답의 groups 배열 인덱스입니다. 0부터 시작합니다.

products필수array

1~100개 상품입니다. productId는 필수이고 variantIds는 최대 500개입니다.

products[].variantIds선택array of string

생략하거나 빈 배열이면 상품 전체 옵션입니다. 특정 옵션은 상품 옵션 조회 결과만 사용할 수 있습니다.

products[].variants선택array of object

상품필터 조회 응답을 다시 사용할 때 지정할 수 있습니다. 각 객체의 variantId만 적용하며 옵션 정보는 서버에서 다시 확인합니다. variantIds와 함께 보내면 두 값이 같아야 합니다.

추가 요청 예시
curl -X PATCH "https://docs.almani-center.com/open/v1/campaigns/3541/product-filter" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467" \
  -H "If-Match: pf_d19b..." \
  -H "Idempotency-Key: 79f99cf1-48a3-4f1e-8882-6176b0fae27b" \
  -H "Content-Type: application/json" \
  -d '{
    "operation":"ADD_PRODUCTS",
    "groupIndex":0,
    "products":[
      {"productId":"49","variantIds":[]},
      {"productId":"70","variantIds":["P00000XY000A"]}
    ]
  }'
응답 data 예시
{
  "campaignId": 3541,
  "operation": "ADD_PRODUCTS",
  "result": "UPDATED",
  "addedProductIds": ["49", "70"],
  "removedProductIds": [],
  "unchangedProductIds": [],
  "summary": {
    "mode":"INCLUDE",
    "groupCount":1,
    "productCount":3,
    "variantCount":1
  },
  "revision": "pf_43c8..."
}

상품필터 전체 교체

PUT/campaigns/{campaignId}/product-filter

필요 스코프: campaign:write

그룹 구조나 INCLUDE/EXCLUDE 모드를 바꿀 때 사용합니다. mode: ALL은 상품 제한을 제거하므로 명시적인 PUT에서만 허용됩니다.

mode필수ALL | INCLUDE | EXCLUDE

ALL은 필터를 제거합니다. INCLUDE·EXCLUDE는 하나 이상의 그룹이 필요합니다.

groupJoin선택OR | AND

그룹 간 결합 방식이며 생략하면 OR입니다.

groupsINCLUDE·EXCLUDEarray

최대 20개 그룹입니다. 각 그룹에는 operator와 1~100개의 products가 필요합니다.

조회 응답을 안전하게 다시 사용할 수 있습니다products[].variantIds 배열뿐 아니라 상품필터 조회에서 받은 products[].variants 객체 배열도 지원합니다. 두 형식을 함께 지정한 경우 옵션이 다르면 요청을 거절합니다.
ALL은 모든 상품을 대상으로 합니다mode: ALL은 상품 제한을 완전히 제거합니다. 의도한 변경인지 확인한 뒤 실행하고, 적용 후 반드시 다시 조회하세요.
요청 예시
curl -X PUT "https://docs.almani-center.com/open/v1/campaigns/3541/product-filter" \
  -H "Authorization: Bearer ak_live_xxxx" \
  -H "X-Site-Id: 467" \
  -H "If-Match: pf_d19b..." \
  -H "Idempotency-Key: 18a73926-e9ad-4a87-a750-b3ac84f1c46e" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "INCLUDE",
  "groupJoin": "OR",
  "groups": [{
    "operator": "OR",
    "products": [
      {"productId": "27", "variantIds": []},
      {"productId": "49", "variantIds": []}
    ]
  }]
}'
응답 data 예시
{
  "campaignId": 3541,
  "revision": "pf_f605...",
  "filter": {
    "version": 4,
    "mode": "INCLUDE",
    "groupJoin": "OR",
    "groups": [{
      "operator": "OR",
      "products": [
        {"productId":"27","variants":[]},
        {"productId":"49","variants":[]}
      ]
    }]
  }
}

캠페인 전용 에러

코드HTTP의미
4000400요청 본문, If-Match 또는 필드 값이 누락·오류.
4003400X-Site-Id 헤더 누락.
4004403API 키 소유자가 아닌 사이트 요청.
4005403campaign:read 또는 campaign:write 스코프 없음.
4040404사이트에서 캠페인을 찾을 수 없거나 지원 대상 캠페인이 아님.
4091409같은 사이트의 캠페인 제목 중복 또는 Idempotency-Key 충돌.
4092409revision 불일치. 최신 상태 재조회 필요.
4220422상품필터, 상품 또는 옵션이 유효하지 않음.
4221422템플릿이 미승인·비활성 또는 사이트에서 사용할 수 없음.
4222422플랫폼과 트리거가 일치하지 않거나 발신프로필·템플릿·상품필터 문제로 캠페인을 생성·활성화할 수 없음.