캠페인 등록 및 수정¶
예약 발송 캠페인을 등록하거나 이미 등록된 캠페인을 수정합니다.
'캠페인 등록 및 수정' API는 앱 서버에서 Hive 노티피케이션 서버로 직접 호출하는 Server-to-Server 통신 방식으로 동작하며, 요청의 id 필드로 신규 등록과 수정을 구분합니다. id를 1 이상으로 전달하면 기존 캠페인을 수정하고, 생략하면 캠페인을 새로 등록합니다.
Note
이 API를 연동하려면 OAuth 2.0 Access Token을 발급받아야 합니다. 토큰을 이미 발급받았다면 추가 권한만 요청합니다. OAuth Token 발급하기를 참고하세요.
Request URL¶
| 상용 URL | https://notification.withhive.com/v2/push/campaigns https://notification.qpyou.cn/v2/push/campaigns |
|---|---|
| Sandbox URL | https://sandbox-notification.withhive.com/v2/push/campaigns https://sandbox-notification.qpyou.cn/v2/push/campaigns |
| HTTP Method | POST |
| Content-Type | application/json |
| Data Format | JSON |
Request header¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| X-Access-Token | 앱 서버 인증을 위한 OAuth 2.0 Access Token (OAuth Token 발급하기 참고) | String | Y |
Note
JWT의 project_id가 요청 본문의 game.gameid와 일치해야 합니다. project 유형의 토큰을 사용할 때 적용됩니다. game.apps에 지정한 앱은 모두 해당 게임에 속해야 하며, 하나라도 조건을 만족하지 않으면 요청 전체가 실패합니다.
Request body¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| id | 캠페인 ID. 1 이상이면 기존 캠페인 수정, 생략하면 신규 등록 | Integer | N |
| status | 캠페인 상태. 신규 등록 시에는 전달해도 무시되며 서버가 1로 설정하고, 수정 시에는 전달한 값이 그대로 저장되므로 반드시 함께 전달
| Integer | 조건부 |
| description | 캠페인 설명 | String | Y |
| type | 발송 구분
| String | Y |
| targeting_id | 타게팅 ID. type이 T이면 1 이상의 값이 필요함타게팅 데이터 등록 API의 응답으로 확인 | Integer | 조건부 |
| notice | 공지 알림 여부(기본값: true). 공지 알림 동작 방식 참고 | Boolean | N |
| reservation | 예약 발송 설정. Reservation 구조 참고 | Object | Y |
| distribution | 분산 발송 설정. Distribution 구조 참고 | Object | N |
| countries | 발송 대상 국가 코드 목록(최소 1개). 국가 코드 참고 | Array | Y |
| game | 발송 대상 게임 정보. Game 구조 참고 | Object | Y |
| default_language | 기본 언어 코드. 언어 코드 참고 | String | Y |
| notification | 언어 코드별 메시지(최소 1개). 각 값은 Message 구조와 동일 | Object | Y |
| option | 발송 옵션. Option 구조 참고 | Object | N |
Reservation 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| localizing | 사용자 현지 시간대 적용 여부
| Boolean | Y |
| start_date | 발송 시작 날짜(YYYY-MM-DD). end_date보다 늦을 수 없음 | String | Y |
| end_date | 발송 종료 날짜(YYYY-MM-DD) | String | Y |
| time | 발송 시각(HH:mm:00). 초는 00으로 작성 | String | Y |
| repeat | 발송 기간 내 반복 발송 여부 | Boolean | Y |
| weekday | 반복 발송할 요일 목록. 요일 코드 참고 | Array | N |
| skip | 반복 발송 기간 중 발송을 건너뛸 날짜 목록(YYYY-MM-DD) | Array | N |
| gmt_offset | 기준 시간대와 UTC의 차이(단위: 초). -43200~50400 사이의 값이며 기본값은 한국 표준시(KST)인 32400 | Long | N |
요일 코드¶
| 코드값 | 설명 |
|---|---|
| 1 | 월요일 |
| 2 | 화요일 |
| 3 | 수요일 |
| 4 | 목요일 |
| 5 | 금요일 |
| 6 | 토요일 |
| 7 | 일요일 |
Distribution 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| enable | 분산 발송 사용 여부(기본값: false) | Boolean | N |
| count | 구간당 발송 건수 | Integer | 조건부 |
| interval | 구간 길이(단위: 초) | Integer | 조건부 |
Note
enable을 true로 설정하면 count와 interval이 모두 0보다 커야 하고, 초당 발송량(count / interval)이 50000 이상이어야 합니다.
Game 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| gameid | 게임 ID | String | Y |
| server_ids | 발송 대상 서버 ID 목록. 지정하면 토큰에 저장된 서버 ID가 일치하는 사용자에게만 발송하며, 생략하면 서버를 구분하지 않음 | Array | N |
| apps | 발송 대상 앱 목록(최소 1개) | Array | Y |
| apps[].appid | App ID | String | Y |
| apps[].versions | 발송 대상 앱 버전 목록. 생략하면 모든 버전이 대상 | Array | N |
Note
게임 인덱스와 앱 인덱스는 요청에서 받지 않습니다. 서버가 gameid와 appid로 조회하여 응답에 채워 반환합니다.
Message 구조¶
notification에 지정한 언어 코드마다 Android와 iOS 메시지를 작성합니다.
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| android.title | Android 알림 제목(최대 240 UTF-8 bytes) | String | 조건부 |
| android.message | Android 알림 본문(최대 420 UTF-8 bytes) | String | 조건부 |
| android.message_expanded | 알림을 펼쳤을 때 표시할 본문(최대 1,800 UTF-8 bytes) | String | N |
| android.image_url | 알림에 표시할 이미지 URL | String | N |
| android.ticker | 알림 도착 시 표시할 티커 문구(최대 90 UTF-8 bytes) | String | N |
| android.summary_text | 본문을 간략하게 표시할 요약 문구(최대 90 UTF-8 bytes) | String | N |
| ios.title | iOS 알림 제목(최대 240 UTF-8 bytes) | String | 조건부 |
| ios.message | iOS 알림 본문(최대 420 UTF-8 bytes) | String | 조건부 |
| ios.media_url | 리치 알림에 표시할 미디어 URL | String | N |
Note
notification에는 default_language와 동일한 언어 코드 키가 있어야 합니다. 각 언어 코드의 메시지는 Android와 iOS 중 최소 한쪽의 title과 message를 모두 입력해야 합니다.
Option 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| badge | 푸시를 수신할 때 앱 아이콘 위에 표시할 숫자(기본값: 1) | Integer | N |
| overwrite | Android 푸시 덮어쓰기 기능 사용 여부(기본값: false) | Boolean | N |
| collapse_key | 푸시 덮어쓰기 기능을 사용할 때 사용하는 키 값. 숫자를 문자열 형식으로 작성(예: "123") | String | N |
| comment | 푸시 덮어쓰기 기능을 사용할 때 함께 저장할 설명 문구 | String | N |
| engagement | 푸시 알림을 눌렀을 때 SDK가 수행할 유저 인게이지먼트 Scheme URL(예: push://hive/...). 푸시 페이로드의 action 필드로 전달됨표기 방식은 하이브가 사용하는 Scheme URL 표기법 참고 | String | N |
| group_key | 알림을 같은 그룹으로 묶어 표시하기 위한 그룹 키 값. 기기 OS에 설정된 알림 옵션이 기본 적용됨 자세한 내용은 iOS, Android 문서 참고 | String | N |
| android.icon | 푸시 알림에 표시할 아이콘 이미지 파일 이름. 이미지 파일은 앱의 /src/main/res/drawable에 있어야 하며, 지원하는 파일 형식은 Android 문서를 참고웹에 있는 이미지를 사용하려면 파일 이름 대신 이미지 URL을 입력 비워 두면 앱 아이콘 이미지를 사용 | String | N |
| android.sound | 푸시 알림에 재생할 음원 파일 이름. 음원 파일은 앱의 /src/main/res/raw에 있어야 함비워 두면 시스템 기본 음원을 사용 | String | N |
| android.priority | Android 기기로 전송할 메시지의 우선순위(기본값: NORMAL). 메시지 전송 시기를 제어하는 FCM 개념이며 자세한 내용은 Firebase 가이드 참고
| String | N |
| ios.sound | 푸시 알림에 재생할 음원 파일 이름. 음원 파일은 앱 컨테이너의 Library/Sounds 또는 앱 메인 번들에 있어야 함비워 두면 default로 설정되어 시스템 기본 음원을 사용 | String | N |
Request example¶
신규 등록¶
{
"description": "8월 복귀 유저 대상 캠페인",
"type": "T",
"targeting_id": 1024,
"notice": true,
"reservation": {
"localizing": false,
"start_date": "2026-08-01",
"end_date": "2026-08-01",
"time": "10:00:00",
"repeat": false,
"gmt_offset": 32400
},
"countries": ["KR", "JP"],
"game": {
"gameid": "com.com2us.mygame",
"apps": [
{
"appid": "com.com2us.mygame.normal.freefull.google.global.android.common"
}
]
},
"default_language": "ko",
"notification": {
"ko": {
"android": {
"title": "복귀 보상",
"message": "우편함을 확인하세요"
},
"ios": {
"title": "복귀 보상",
"message": "우편함을 확인하세요"
}
}
},
"option": {
"badge": 1
}
}
기존 캠페인 수정¶
{
"id": 8821,
"status": 1,
"description": "8월 복귀 유저 대상 캠페인 (수정)",
"type": "B",
"reservation": {
"localizing": false,
"start_date": "2026-08-02",
"end_date": "2026-08-02",
"time": "11:00:00",
"repeat": false,
"gmt_offset": 32400
},
"countries": ["KR"],
"game": {
"gameid": "com.com2us.mygame",
"apps": [
{
"appid": "com.com2us.mygame.normal.freefull.google.global.android.common"
}
]
},
"default_language": "ko",
"notification": {
"ko": {
"android": {
"title": "복귀 보상",
"message": "우편함을 확인하세요"
}
}
}
}
Response body¶
| 필드명 | 설명 | 타입 |
|---|---|---|
| result_code | 응답 코드 자세히 | Integer |
| result_msg | 결과 메시지 | String |
| token_validation | JWT 검증 결과 (JWT 검증 에러) | Object |
| token_validation.result_code | JWT 검증 결과 코드 | Integer |
| token_validation.result_msg | JWT 검증 결과 메시지 | String |
| data.uuid | 요청 추적 ID | String |
| data.id | 캠페인 ID. 신규 등록이면 서버에서 생성한 값 | Integer |
| data.status | 캠페인 상태 | Integer |
| data.modify | 수정 가능 여부. 요청으로 설정할 수 없으며, 이 API로 저장한 캠페인은 항상 true | Boolean |
| data.type | 발송 구분 | String |
| data.notice | 공지 알림 여부 | Boolean |
| data.description | 캠페인 설명 | String |
| data.targeting_id | 타게팅 ID. type이 T가 아니면 0 | Integer |
| data.is_analytics | 애널리틱스 캠페인 여부. 이 API로 저장한 캠페인은 항상 false | Boolean |
| data.reservation | 예약 발송 설정 | Object |
| data.distribution | 분산 발송 설정 | Object |
| data.countries | 발송 대상 국가 코드 목록 | Array |
| data.last_end_time | 캠페인의 마지막 발송이 종료되는 시각(단위: 초). data.tasks의 end_time 중 가장 큰 값이며, 서버는 이 시각이 지나면 캠페인을 완료 상태로 변경 | Long |
| data.last_end_timestamp | 캠페인의 마지막 발송이 종료되는 시각(UTC 기준 epoch seconds). data.tasks의 end_timestamp 중 가장 큰 값 | Long |
| data.tasks | 예약 설정으로부터 서버가 계산한 발송 작업. Task 구조 참고 | Object |
| data.game | 발송 대상 게임 정보. 서버가 조회한 game_index와 app_index가 채워짐 | Object |
| data.default_language | 기본 언어 코드 | String |
| data.notification | 언어 코드별 메시지 | Object |
| data.option | 발송 옵션 | Object |
| data.registrant | 등록자. 이 API로 등록한 캠페인은 항상 SYSTEM | Object |
| data.timestamp | 저장 시각. date는 문자열, time은 epoch milliseconds | Object |
Task 구조¶
tasks는 발송 시각 문자열(HH:mm:00)을 키로 갖는 객체이며, 각 값은 아래 구조입니다. 같은 시각에 발송되는 국가는 하나의 작업으로 묶입니다.
| 필드명 | 설명 | 타입 |
|---|---|---|
| time | 발송 시각(HH:mm:00). 객체의 키와 같은 값 | String |
| gmt_offset | 이 작업에 적용된 시간대와 UTC의 차이(단위: 초) | Long |
| zones | 이 작업으로 묶인 국가의 시간대 이름 목록 | Array |
| start_time | 발송 시작 시각을 한국 표준시(KST) 기준으로 환산한 값. start_timestamp에 KST 오프셋(32400)을 더한 값 | Long |
| end_time | 발송 종료 시각을 한국 표준시(KST) 기준으로 환산한 값. end_timestamp에 KST 오프셋(32400)을 더한 값 | Long |
| start_timestamp | 발송 시작 시각(UTC 기준 epoch seconds) | Long |
| end_timestamp | 발송 종료 시각(UTC 기준 epoch seconds) | Long |
Note
reservation.localizing이 false이면 모든 국가에 reservation.gmt_offset이 적용되므로 작업이 하나로 묶입니다. true이면 국가의 현지 시간대별로 작업이 나뉘며, 같은 오프셋을 쓰는 국가끼리 묶여 zones에 함께 표시됩니다.
응답 코드¶
| 코드값 | 설명 |
|---|---|
| 0 | 성공 |
| 1400 | 유효하지 않은 요청
|
| 1401 | 요청한 앱에 대한 권한이 없음 |
| 1500 | 서버 내부 오류 |
| 2499 | JWT 검증 실패 (token_validation 참고) |
Response example¶
성공¶
{
"result_code": 0,
"result_msg": "success",
"token_validation": {
"result_code": 0,
"result_msg": "success"
},
"data": {
"uuid": "2f8c1b90-4a77-4d31-9c6e-1b0e5a7d3c42",
"id": 9001,
"status": 1,
"modify": true,
"type": "B",
"description": "test",
"targeting_id": 0,
"is_analytics": false,
"default_language": "en",
"reservation": {
"localizing": false,
"start_date": "2026-08-01",
"end_date": "2026-09-25",
"time": "05:10:00",
"repeat": true,
"weekday": [3, 4, 5],
"gmt_offset": 32400
},
"countries": ["KR", "SE"],
"last_end_time": 1790313000,
"last_end_timestamp": 1790280600,
"tasks": {
"05:10:00": {
"time": "05:10:00",
"gmt_offset": 32400,
"zones": ["Asia/Seoul", "Europe/Stockholm"],
"start_time": 1785561000,
"end_time": 1790313000,
"start_timestamp": 1785528600,
"end_timestamp": 1790280600
}
},
"game": {
"gameid": "com.com2us.mygame",
"game_index": 1234,
"apps": [
{
"app_index": 5001,
"appid": "com.com2us.mygame.normal.freefull.google.global.android.common"
}
]
},
"notification": {
"en": {
"android": {
"title": "test",
"message": "test"
},
"ios": {
"title": "test",
"message": "test"
}
}
},
"option": {
"badge": 1
},
"registrant": {
"id": "SYSTEM",
"name": "SYSTEM"
},
"timestamp": {
"date": "2026-07-31 18:57:23.193",
"time": 1785491843193
}
}
}
실패¶
{
"result_code": 1400,
"result_msg": "description field is required.",
"token_validation": {
"result_code": 0,
"result_msg": "success"
}
}
JWT 검증 실패¶
{
"result_code": 2499,
"result_msg": "JWT validation failed.",
"token_validation": {
"result_code": 2408,
"result_msg": "The access token is expired. Please refresh your token."
}
}
국가 코드¶
countries에 사용할 수 있는 국가 코드는 아래와 같습니다.
| Continent | Country | Code | Country | Code |
|---|---|---|---|---|
| Africa | Angola | AO | Madagascar | MG |
| Burkina Faso | BF | Mali | ML | |
| Burundi | BI | Mauritania | MR | |
| Benin | BJ | Mauritius | MU | |
| Botswana | BW | Malawi | MW | |
| Democratic Republic of the Congo | CD | Mozambique | MZ | |
| Central African Republic | CF | Namibia | NA | |
| Republic of the Congo | CG | Niger | NE | |
| Ivory Coast | CI | Nigeria | NG | |
| Cameroon | CM | Reunion | RE | |
| Cape Verde | CV | Rwanda | RW | |
| Djibouti | DJ | Seychelles | SC | |
| Algeria | DZ | Sudan | SD | |
| Egypt | EG | Saint Helena | SH | |
| Western Sahara | EH | Sierra Leone | SL | |
| Eritrea | ER | Senegal | SN | |
| Ethiopia | ET | Somalia | SO | |
| Gabon | GA | South Sudan | SS | |
| Ghana | GH | Sao Tome and Principe | ST | |
| Gambia | GM | Swaziland | SZ | |
| Guinea | GN | Chad | TD | |
| Equatorial Guinea | GQ | French Southern Territories | TF | |
| Guinea-Bissau | GW | Togo | TG | |
| British Indian Ocean Territory | IO | Tunisia | TN | |
| Kenya | KE | Tanzania | TZ | |
| Comoros | KM | Uganda | UG | |
| Liberia | LR | Mayotte | YT | |
| Lesotho | LS | South Africa | ZA | |
| Libya | LY | Zambia | ZM | |
| Morocco | MA | Zimbabwe | ZW | |
| Americas | Antigua and Barbuda | AG | Honduras | HN |
| Anguilla | AI | Haiti | HT | |
| Argentina | AR | Jamaica | JM | |
| Aruba | AW | Saint Kitts and Nevis | KN | |
| Barbados | BB | Cayman Islands | KY | |
| Saint Barthélemy | BL | Saint Lucia | LC | |
| Bermuda | BM | Saint Martin | MF | |
| Bolivia | BO | Martinique | MQ | |
| Bonaire, Saint Eustatius and Saba | BQ | Montserrat | MS | |
| Brazil | BR | Mexico | MX | |
| Bahamas | BS | Nicaragua | NI | |
| Belize | BZ | Panama | PA | |
| Canada | CA | Peru | PE | |
| Chile | CL | Saint Pierre and Miquelon | PM | |
| Colombia | CO | Puerto Rico | PR | |
| Costa Rica | CR | Paraguay | PY | |
| Cuba | CU | Suriname | SR | |
| Curaçao | CW | El Salvador | SV | |
| Dominica | DM | Sint Maarten | SX | |
| Dominican Republic | DO | Turks and Caicos Islands | TC | |
| Ecuador | EC | Trinidad and Tobago | TT | |
| Falkland Islands | FK | United States Minor Outlying Islands | UM | |
| Grenada | GD | United States | US | |
| French Guiana | GF | Uruguay | UY | |
| Greenland | GL | Saint Vincent and the Grenadines | VC | |
| Guadeloupe | GP | Venezuela | VE | |
| South Georgia and the South Sandwich Islands | GS | British Virgin Islands | VG | |
| Guatemala | GT | U.S. Virgin Islands | VI | |
| Guyana | GY | |||
| Asia | United Arab Emirates | AE | Lebanon | LB |
| Afghanistan | AF | Sri Lanka | LK | |
| Armenia | AM | Myanmar | MM | |
| Azerbaijan | AZ | Mongolia | MN | |
| Bangladesh | BD | Macao | MO | |
| Bahrain | BH | Maldives | MV | |
| Brunei | BN | Malaysia | MY | |
| Bhutan | BT | Nepal | NP | |
| China | CN | Oman | OM | |
| Georgia | GE | Philippines | PH | |
| Hong Kong | HK | Pakistan | PK | |
| Indonesia | ID | Palestinian Territory | PS | |
| Israel | IL | Qatar | QA | |
| India | IN | Saudi Arabia | SA | |
| Iraq | IQ | Singapore | SG | |
| Iran | IR | Syria | SY | |
| Jordan | JO | Thailand | TH | |
| Japan | JP | Tajikistan | TJ | |
| Kyrgyzstan | KG | East Timor | TL | |
| Cambodia | KH | Turkmenistan | TM | |
| North Korea | KP | Turkey | TR | |
| South Korea | KR | Taiwan | TW | |
| Kuwait | KW | Uzbekistan | UZ | |
| Kazakhstan | KZ | Vietnam | VN | |
| Laos | LA | Yemen | YE | |
| Europe | Andorra | AD | Iceland | IS |
| Albania | AL | Italy | IT | |
| Austria | AT | Jersey | JE | |
| Aland Islands | AX | Liechtenstein | LI | |
| Bosnia and Herzegovina | BA | Lithuania | LT | |
| Belgium | BE | Luxembourg | LU | |
| Bulgaria | BG | Latvia | LV | |
| Belarus | BY | Monaco | MC | |
| Switzerland | CH | Moldova | MD | |
| Cyprus | CY | Montenegro | ME | |
| Czech Republic | CZ | Macedonia | MK | |
| Germany | DE | Malta | MT | |
| Denmark | DK | Netherlands | NL | |
| Estonia | EE | Norway | NO | |
| Spain | ES | Poland | PL | |
| Finland | FI | Portugal | PT | |
| Faroe Islands | FO | Romania | RO | |
| France | FR | Serbia | RS | |
| United Kingdom | GB | Russia | RU | |
| Guernsey | GG | Sweden | SE | |
| Gibraltar | GI | Slovenia | SI | |
| Greece | GR | Svalbard and Jan Mayen | SJ | |
| Croatia | HR | Slovakia | SK | |
| Hungary | HU | San Marino | SM | |
| Ireland | IE | Ukraine | UA | |
| Isle of Man | IM | Vatican | VA | |
| Oceania | American Samoa | AS | Niue | NU |
| Australia | AU | New Zealand | NZ | |
| Cocos Islands | CC | French Polynesia | PF | |
| Cook Islands | CK | Papua New Guinea | PG | |
| Christmas Island | CX | Pitcairn | PN | |
| Fiji | FJ | Palau | PW | |
| Micronesia | FM | Solomon Islands | SB | |
| Guam | GU | Tokelau | TK | |
| Kiribati | KI | Tonga | TO | |
| Marshall Islands | MH | Tuvalu | TV | |
| Northern Mariana Islands | MP | Vanuatu | VU | |
| New Caledonia | NC | Wallis and Futuna | WF | |
| Norfolk Island | NF | Samoa | WS | |
| Nauru | NR | |||
| Polar | Antarctica | AQ |
언어 코드¶
default_language와 notification의 키에 사용할 수 있는 언어 코드는 아래와 같습니다.
| 언어 코드 | 언어 |
|---|---|
| ko | 한국어 |
| zh-hans | 중문간체 |
| zh-hant | 중문번체 |
| en | 영어 |
| ja | 일본어 |
| ar | 아랍어 |
| fr | 프랑스어 |
| de | 독일어 |
| es | 스페인어 |
| pt | 포르투갈어 |
| th | 태국어 |
| it | 이탈리아어 |
| ru | 러시아어 |
| id | 인도네시아어 |
| vi | 베트남어 |
| tr | 터키어 |
| tl | 필리핀어 |
공지 알림 동작 방식¶
공지 알림은 앱 사용자가 공지 알림 수신에 동의한 경우에만 발송됩니다.
- 사용자가 공지 알림 수신에 동의하지 않으면
notice를true로 설정한 메시지는 발송되지 않습니다. - 발송 시각이 야간(
21:00~익일 08:00)인 경우 야간 알림 수신 동의가 추가로 필요합니다.
Warning
한국 사용자를 대상으로 공지 알림을 발송하면 광고성 알림으로 간주되어 「정보통신망법」 제50조를 따라야 합니다. 광고성 알림 메시지에는 광고임을 알리는 문구와 수신 거부 안내를 포함해야 합니다.
- 광고성 알림 메시지 예시: (광고) {메시지_본문} (수신거부: 설정에서 변경 가능)
Note
JWT 검증 실패 시, token_validation 필드로 자세한 오류 정보를 확인할 수 있습니다. 자세한 내용은 JWT 검증 에러 코드를 참고하세요.