문자 발송을
서비스에 연결해요.
API KEY 하나로 시작해요. 국가를 선택하고 한 번에 최대 1,000개 번호로 문자를 보내요. 번호별 결과도 확인할 수 있어요.
빠르게 시작하기
- API KEY를 만들어요
가입·승인·OTP 로그인 후API KEY 관리에서 발급해요.
- 크레딧을 준비해요
계정의 크레딧과 단가를 그대로 사용해요. 발송을 접수할 때 금액을 차감해요.
- 문자를 보내고 결과를 확인해요
발송 ID를 저장하고 상태 조회 API로 결과를 확인해요.
https://hexsms.com실제 연동은 HTTPS 서버에서 호출해주세요. 미리보기 환경에서는 실제 키 발급과 API 발송을 지원하지 않아요.
지원 국가
대표 커버리지 국가
- 미국
- 캐나다
- 영국
- 독일
- 프랑스
- 스페인
- 이탈리아
- 네덜란드
- 스웨덴
- 노르웨이
- 덴마크
- 폴란드
- 루마니아
- 체코
- 오스트리아
- 스위스
- 아일랜드
- 포르투갈
- 핀란드
- 일본
- 대한민국
- 중국
- 대만
- 홍콩(중국 특별행정구)
- 싱가포르
- 말레이시아
- 인도네시아
- 필리핀
- 태국
- 베트남
- 인도
- 방글라데시
- 파키스탄
- 오스트레일리아
- 뉴질랜드
- 브라질
- 멕시코
- 남아프리카
- 나이지리아
- 아랍에미리트
- 사우디아라비아
국가별 발송 가능 여부·단가·발신자 등록 조건은 계정과 현지 통신망에 따라 달라요. 발송 전 국가별 요금을 확인해주세요.
GET/api/v1/messages/countries
활성 국가와 실제 적용 단가를 API로 확인해요. 발송 요청은 country로 국가를 지정하고, 한 요청에는 같은 국가의 번호를 넣어주세요. 요금이 설정되지 않은 국가는 발송을 접수하지 않아요.
{ "currency": "USDT", "countries": [{ "country": "US", "unitPrice": 0.02 }] }API KEY로 인증해요
모든 외부 API 요청에 아래 헤더를 넣어주세요. 로그인 쿠키나 OTP 코드는 필요하지 않아요.
Authorization: Bearer hex_live_여기에_발급받은_키키 원문은 발급할 때 한 번만 보여드려요. 서버의 환경 변수에 보관하고, 프런트엔드 코드에 넣지 마세요. 키를 폐기하거나 계정이 정지되면 사용할 수 없어요. 키는 최대 5개까지 만들 수 있어요.
/api/v1/messages한 번에 1,000개 번호로 보내요
하나의 문자 내용을 여러 번호로 보내요. 요청을 검증한 뒤 발송 큐에 등록하고 바로 응답해요. 번호마다 다른 내용을 보내려면 별도 요청과 새로운 Idempotency-Key를 사용해주세요.
| 필드 | 형식 | 설명 |
|---|---|---|
country * | string | ISO 3166-1 alpha-2 국가코드. 예: US, GB, JP, KR. 기본 국가는 없어요. |
text * | string | 공백 제거 후 1~1,600자. 한 요청의 모든 번호에 같은 내용을 보내요. |
recipients * | string[] | 1~1,000개 휴대폰 번호. +국가번호 형식을 권장하며, 모든 번호는 country와 같은 국가여야 해요. |
Idempotency-Key * | header | 8~100자 영문·숫자·하이픈·밑줄. 요청마다 고유하게 정해주세요. |
잘못된 번호나 중복 번호가 하나라도 있으면 요청 전체를 거절해요. 이때는 발송하거나 차감하지 않아요. 중복은 국제 형식으로 변환한 번호를 기준으로 확인해요.
curl -X POST 'https://hexsms.com/api/v1/messages' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: notice-20261024-001' \
-d '{
"country": "US",
"text": "Your verification code is 482913.",
"recipients": ["+12025550123", "+12025550124"]
}'{
"id": "35bed356-b84a-452a-8e94-98b538972ecd",
"country": "US",
"state": "RUNNING",
"total": 2,
"segments": 1,
"unitPrice": 0.025,
"cost": 0.05,
"createdAt": 1792800000000,
"note": null,
"replayed": false
}같은 계정·같은 Idempotency-Key·같은 내용과 번호 순서로 재시도하면 추가 발송·차감 없이 기존 결과를 돌려줘요(200, replayed: true). 본문이 다르면 409예요. 키를 교체해도 중복 방지가 유지돼요. 요청 키는 만료 없이 보관해요.
금액은 이렇게 계산해요
번호 수 × 통수(segments) × 계정 단가로 계산해요. UCS-2 문자는 70자까지 1통, 이후 67자 단위예요. GSM-7 기본 문자는 160자까지 1통, 이후 153자 단위예요. 확장 문자는 2자리, 이모지는 UTF-16 길이로 계산해요. unitPrice와 cost는 USDT예요. 응답의 단가가 실제 적용 단가이며, 위 0.025는 예시예요.
/api/v1/messages/{id}번호별 발송 결과를 확인해요
발송 API에서 받은 id를 사용해요. 같은 계정으로 API에서 발송한 내역만 조회할 수 있어요. 조회는 저장된 결과를 반환해요. 통신사 최신 결과가 필요하면 다음 상태 갱신 API를 먼저 호출해주세요.
curl 'https://hexsms.com/api/v1/messages/35bed356-b84a-452a-8e94-98b538972ecd?limit=1&offset=0' \
-H 'Authorization: Bearer YOUR_API_KEY'{
"id": "35bed356-b84a-452a-8e94-98b538972ecd",
"country": "US",
"state": "DONE",
"total": 2, "segments": 1,
"unitPrice": 0.025, "cost": 0.05,
"createdAt": 1792800000000, "note": null,
"summary": { "DELIVERED": 1, "PENDING": 1 },
"messages": [
{
"id": "d2787184-d8b8-49c6-9c15-1db90a6d5516",
"to": "12025550123",
"status": "DELIVERED",
"statusName": "DELIVERED_TO_HANDSET",
"description": "Message delivered to handset",
"error": null,
"updatedAt": 1792800005000
}
],
"pagination": { "limit": 1, "offset": 0, "nextOffset": 1 }
}limit는 1~1,000(기본 100), offset은 0~1,000(기본 0)이에요. nextOffset이 null이면 마지막 페이지예요. summary는 전체 번호의 상태별 건수예요. to는 +를 제외한 국제 번호 형식, 시간은 Unix 밀리초로 반환해요. 최초 발송의 번호 순서와 조회 순서는 다를 수 있어요. 각 message의 id로 구분해주세요.
발송 큐 처리가 끝났다는 뜻이에요. 실제 도착 여부는 messages의 status가 DELIVERED인지 확인해주세요.
/api/v1/messages/{id}/refresh최신 수신 상태를 가져와요
통신사 로그를 조회해 저장된 결과를 갱신해요. 본문은 필요 없어요. 갱신 후 GET으로 결과를 다시 읽어주세요. 같은 발송은 30초에 한 번 갱신할 수 있어요. 통신사 로그는 발송 후 48시간 동안 조회할 수 있어요. 웹훅이 설정된 환경에서는 결과가 자동으로 반영될 수도 있어요.
curl -X POST 'https://hexsms.com/api/v1/messages/35bed356-b84a-452a-8e94-98b538972ecd/refresh' \
-H 'Authorization: Bearer YOUR_API_KEY'{ "id": "35bed356-b84a-452a-8e94-98b538972ecd", "updated": 2 }updated는 갱신한 행 수예요. 아직 발송 대기 중이거나 새 결과가 없으면 0일 수 있어요. 10초 이상 간격으로 GET을 호출하고, 필요할 때만 refresh를 요청하는 흐름을 권장해요.
상태 코드를 알아봐요
발송 요청 state
PREPARING 준비 중 · RUNNING 처리 중 · PAUSED 일시정지 · DONE 큐 처리 완료 · CANCELED 취소
| 번호별 status | 뜻 |
|---|---|
| QUEUED | 발송 대기 중이에요. |
| SENDING | 통신사에 요청 중이에요. |
| PENDING | 통신사가 접수했고, 최종 수신 결과를 기다려요. |
| DELIVERED | 수신 단말에 전달됐어요. |
| UNDELIVERABLE | 전달하지 못했어요. |
| EXPIRED | 전달 유효 시간이 지났어요. |
| REJECTED | 요청이 거부됐거나 처리 오류가 발생했어요. |
| CANCELED | 발송 대기가 취소됐어요. |
| UNKNOWN | 결과를 아직 확인하지 못했어요. |
통신사 상태 코드가 추가될 수 있으니 알 수 없는 status도 처리해주세요. 실패 사유는 statusName, description, error에서 확인할 수 있어요.
오류가 나면 이렇게 확인해요
{ "error": "크레딧이 부족해요. 충전 후 다시 요청해주세요.", "code": "INSUFFICIENT_CREDITS" }| HTTP | code | 확인할 내용 |
|---|---|---|
| 403 | COUNTRY_NOT_ENABLED | 국가별 발송 요금과 활성 여부를 확인해요. |
| 400 | INVALID_COUNTRY | country에 ISO 국가코드를 넣어주세요. |
| 400 | INVALID_BODY / INVALID_JSON / INVALID_TEXT | JSON 객체와 문자 내용을 확인해요. |
| 400 | INVALID_RECIPIENTS / INVALID_PHONE / DUPLICATE_PHONE | 번호 수·형식·중복을 확인해요. |
| 400 | INVALID_IDEMPOTENCY_KEY / INVALID_PAGINATION | 요청 키 또는 페이지 값을 확인해요. |
| 401 | UNAUTHORIZED | Bearer API KEY가 없거나 유효하지 않아요. |
| 402 | INSUFFICIENT_CREDITS | 크레딧을 충전해주세요. |
| 403 | ACCOUNT_INACTIVE | 승인된 활성 계정인지 확인해요. |
| 404 | NOT_FOUND | 발송 ID와 계정 소유권을 확인해요. |
| 409 | IDEMPOTENCY_CONFLICT | 같은 요청 키를 다른 본문에 사용했어요. |
| 413 / 415 | BODY_TOO_LARGE / UNSUPPORTED_MEDIA_TYPE | 128KiB 이하 JSON 본문을 보내주세요. |
| 429 | RATE_LIMITED / REFRESH_TOO_SOON | Retry-After 초만큼 기다렸다 다시 요청해요. |
| 500 / 502 | INTERNAL_ERROR / PROVIDER_UNAVAILABLE | 잠시 후 재시도해요. 발송 재시도는 같은 요청 키를 사용해요. |
| 503 | PREVIEW_ONLY | 미리보기에서는 실제 API를 호출할 수 없어요. |
발송·조회·갱신을 합쳐 API KEY당 분당 120회까지 요청할 수 있어요. 제한에 걸리면 Retry-After 헤더를 확인해주세요. API는 서버 간 연동용이며 브라우저 CORS 호출은 지원하지 않아요.
Node.js에서 연결해봐요
const response = await fetch('https://hexsms.com/api/v1/messages', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.HEXSMS_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': 'notice-20261024-001'
},
body: JSON.stringify({
country: 'US',
text: 'Your order is on its way.',
recipients: ['+12025550123', '+12025550124']
})
});
const result = await response.json();
if (!response.ok) throw new Error(result.code + ': ' + result.error);
console.log(result.id); // Use this ID to check delivery status.요청 키는 작업별로 한 번 만들고, 응답이 오지 않아 재시도할 때도 같은 값을 사용해주세요. 한 번 성공한 작업을 새 키로 다시 보내면 별도 발송으로 처리돼요.