싱글 푸시 발송¶
지정한 식별자에게 푸시 알림을 즉시 발송합니다.
'싱글 푸시 발송' API는 앱 서버에서 Hive 노티피케이션 서버로 직접 호출하는 Server-to-Server 통신 방식으로 동작하며, 요청 검증 후 발송은 비동기로 처리됩니다. 응답 코드 0은 발송 요청이 정상 접수되었다는 의미이며 발송 완료를 보장하지 않습니다.
Note
이 API를 연동하려면 OAuth 2.0 Access Token을 발급받아야 합니다. 토큰을 이미 발급받았다면 추가 권한만 요청합니다. OAuth Token 발급하기를 참고하세요.
Request URL¶
| 상용 URL | https://notification.withhive.com/v2/push/send https://notification.qpyou.cn/v2/push/send |
|---|---|
| Sandbox URL | https://sandbox-notification.withhive.com/v2/push/send https://sandbox-notification.qpyou.cn/v2/push/send |
| 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 유형의 토큰을 사용할 때 적용됩니다.
Request body¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| identifiers | 발송 대상 목록. 유효한 항목이 1~100개여야 함 Identifier 구조 참고 | Array | Y |
| game | 발송 대상 게임 정보. Game 구조 참고 | Object | Y |
| enable_locale | 언어 로케일 적용 여부
| Boolean | Y |
| payload | 메시지 페이로드. Payload 구조 참고 | Object | Y |
| notice | 공지 알림 여부(기본값: false) | Boolean | N |
| action_info | 액션 버튼 정보. ActionInfo 구조 참고 | Object | N |
Note
푸시가 지연 없이 도달하도록 아래 사항을 지켜 주세요.
identifiers와game.appids에는 각각 한 건씩 지정하는 것을 권장합니다. 여러 건을 함께 전달하면 조회 조건을 특정할 수 없어 발송이 지연될 수 있습니다.identifiers에는 우선순위가 높은player_id를 지정하고,did값만으로 구성하는 것은 지양합니다.game에gameid만 지정하는 것은 지양합니다.appids가 비어 있으면 해당 게임에 속한 모든 앱을 대상으로 조회하므로 발송이 지연될 수 있습니다.
Identifier 구조¶
player_id와 did 중 최소 하나는 0보다 큰 값이어야 합니다. 두 값을 모두 전달하면 player_id가 우선 적용됩니다.
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| player_id | Player ID | Long | 조건부 |
| did | 기기 ID | Long | 조건부 |
Note
유효하지 않은 항목은 검증 과정에서 제거된 후 개수를 검사합니다. 100개를 전달하더라도 모두 유효하지 않으면 1400 응답을 반환합니다.
Game 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| gameid | 게임 ID | String | Y |
| appids | 발송 대상 App ID 목록. 생략하면 gameid에 속한 모든 앱이 대상 | Array | N |
Payload 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| single | enable_locale이 false일 때 사용할 메시지. Message 구조 참고 | Object | 조건부 |
| default_language | enable_locale이 true일 때 기본 언어 코드. 소문자로 작성하며 언어 코드 참고 | String | 조건부 |
| locale | enable_locale이 true일 때 언어 코드별 메시지. 키는 소문자로 작성하며 default_language와 동일한 키가 있어야 함각 값은 Message 구조와 동일 | Object | 조건부 |
| option | 발송 옵션. Option 구조 참고 | Object | N |
Message 구조¶
android와 ios 중 최소 한쪽은 title과 message가 모두 채워져야 합니다.
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| android.title | Android 알림 제목 | String | 조건부 |
| android.message | Android 알림 본문 | String | 조건부 |
| android.message_expanded | 알림을 펼쳤을 때 표시할 본문 | String | N |
| android.image_url | 알림에 표시할 이미지 URL | String | N |
| android.ticker | 알림 도착 시 표시할 티커 문구 | String | N |
| android.summary_text | 본문을 간략하게 표시할 요약 문구 | String | N |
| ios.title | iOS 알림 제목 | String | 조건부 |
| ios.message | iOS 알림 본문 | String | 조건부 |
| ios.media_url | 리치 알림에 표시할 미디어 URL | String | N |
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 |
ActionInfo 구조¶
| 필드명 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| android.category | 액션 푸시 카테고리 식별자 | String | N |
| android.actions | 액션 버튼 목록(최대 3개). 각 항목에 titles.default가 있어야 함 | Array | N |
| ios.category | 액션 푸시 카테고리 식별자. iOS 액션을 사용하면 필수 | String | 조건부 |
| ios.actions | 액션 버튼 목록(최대 3개). 각 항목에 action_id가 있어야 함 | Array | 조건부 |
| actions[].action_id | 버튼 식별자 | String | 조건부 |
| actions[].action_type | 버튼 동작. 대소문자를 구분하지 않으며, 아래에 없는 값이나 빈 값을 전달하면 오류 없이 CLOSE로 처리됨
| String | N |
| actions[].action | 버튼을 눌렀을 때 실행할 옵션. action_type이 CURL이면 이 값을 URL로 호출함action_type이 CLOSE가 아니면 반드시 입력 | String | 조건부 |
| actions[].titles | 언어 코드별 버튼 문구. Titles 구조 참고 | Object | 조건부 |
Titles 구조¶
언어 코드를 키로, 버튼에 표시할 문구를 값으로 갖는 객체입니다. default 키는 대상 언어에 해당하는 키가 없을 때 사용할 기본 문구입니다.
| 키 | 설명 | 타입 | 필수 여부 |
|---|---|---|---|
| default | 기본 버튼 문구. Android 액션에서는 필수이며, 비어 있으면 1400을 반환 | String | 조건부 |
| <언어 코드> | 해당 언어로 표시할 버튼 문구. 언어 코드 참고 | String | N |
문구는 발송 시점에 다음 순서로 결정됩니다.
enable_locale이true이고 발송 대상 언어의 키가 있으면 그 값을 사용- 그 외에는
default값을 사용
Note
category와 actions를 모두 비워서 전달하면 해당 플랫폼의 액션이 없는 것으로 간주하고 검증을 건너뜁니다.
iOS 액션은 titles를 검증하지 않지만, 버튼 문구는 Android와 같은 방식으로 결정되므로 함께 입력하세요.
Request example¶
단일 언어 발송¶
{
"identifiers": [
{ "player_id": 20000044768 },
{ "did": 40000098765 }
],
"game": {
"gameid": "com.com2us.mygame",
"appids": ["com.com2us.mygame.normal.freefull.google.global.android.common"]
},
"enable_locale": false,
"notice": true,
"payload": {
"option": {
"badge": 1,
"group_key": "notice"
},
"single": {
"android": {
"title": "점검 안내",
"message": "오늘 02시부터 서버 점검이 있습니다."
},
"ios": {
"title": "점검 안내",
"message": "오늘 02시부터 서버 점검이 있습니다."
}
}
}
}
다국어 발송¶
{
"identifiers": [
{ "player_id": 20000044768 }
],
"game": {
"gameid": "com.com2us.mygame",
"appids": [
"com.com2us.mygame.normal.freefull.google.global.android.common",
"com.com2us.mygame.normal.freefull.apple.global.ios.universal"
]
},
"enable_locale": true,
"payload": {
"default_language": "ko",
"locale": {
"ko": {
"android": { "title": "점검 안내", "message": "오늘 02시 점검" }
},
"en": {
"android": { "title": "Maintenance", "message": "Server maintenance at 2 AM" }
}
}
}
}
액션 버튼 발송¶
{
"identifiers": [
{ "player_id": 20000044768 }
],
"game": {
"gameid": "com.com2us.mygame",
"appids": ["com.com2us.mygame.normal.freefull.apple.global.ios.universal"]
},
"enable_locale": false,
"payload": {
"single": {
"ios": {
"title": "보상 도착",
"message": "우편함을 확인하세요"
}
}
},
"action_info": {
"ios": {
"category": "REWARD",
"actions": [
{
"action_id": "open_mail",
"action_type": "CURL",
"action": "https://example.com/mail",
"titles": {
"default": "열기",
"ko": "열기",
"en": "Open"
}
},
{
"action_id": "dismiss",
"action_type": "CLOSE",
"titles": {
"default": "닫기",
"ko": "닫기",
"en": "Close"
}
}
]
}
}
}
Response header¶
| 필드명 | 설명 | 타입 |
|---|---|---|
| UUID | 요청 추적 ID. 요청 헤더로 전달한 값이 있으면 그 값, 없으면 서버에서 생성한 값 | String |
Response body¶
이 API는 발송 요청을 접수만 하므로 data 필드를 반환하지 않습니다.
| 필드명 | 설명 | 타입 |
|---|---|---|
| result_code | 응답 코드 자세히 | Integer |
| result_msg | 결과 메시지 | String |
| token_validation | JWT 검증 결과 (JWT 검증 에러) | Object |
| token_validation.result_code | JWT 검증 결과 코드 | Integer |
| token_validation.result_msg | JWT 검증 결과 메시지 | String |
응답 코드¶
| 코드값 | 설명 |
|---|---|
| 0 | 성공 |
| 1400 | 유효하지 않은 요청
|
| 1401 | 요청한 앱에 대한 권한이 없음 |
| 1500 | 서버 내부 오류 |
| 2499 | JWT 검증 실패 (token_validation 참고) |
Response example¶
성공¶
{
"result_code": 0,
"result_msg": "success",
"token_validation": {
"result_code": 0,
"result_msg": "success"
}
}
실패¶
{
"result_code": 1400,
"result_msg": "identifiers 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."
}
}
언어 코드¶
payload.default_language와 payload.locale의 키에 사용할 수 있는 언어 코드는 아래와 같습니다.
| 언어 코드 | 언어 |
|---|---|
| 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 검증 에러 코드를 참고하세요.