샌드고 API 인증 — 액세스 키와 Bearer 토큰
accessKey/secretKey 로 토큰을 발급받아 Bearer 인증으로 호출하는 방법. v1 과 v2 의 차이, 토큰 캐싱, 401/403 처리까지.
POST /api/v2/token샌드고 인증은 두 단계입니다. 키로 토큰을 받고, 토큰으로 발송한다.
거의 모든 경우 이 문서를 읽을 필요가 없습니다 — 공식 SDK 가 전부 대신 처리합니다. REST 를 직접 호출하거나, SDK 가 없는 언어에서 클라이언트를 만들 때만 필요합니다.
준비물
샌드고 콘솔 → 연동 관리 → 앱에서 발급받은 accessKey 와 secretKey.
export SENDGO_ACCESS_KEY=your_access_key
export SENDGO_SECRET_KEY=your_secret_key
두 값은 계정의 발송 권한 전체를 가집니다. 저장소에 커밋하지 마세요. 실수로 커밋했다면 콘솔에서 폐기 후 재발급해야 합니다 — 커밋을 되돌리는 것만으로는 노출이 사라지지 않습니다.
토큰 발급
accessKey:secretKey 를 Base64 로 인코딩해 Basic 인증 헤더로 보냅니다.
curl -X POST https://sendgo.io/api/v2/token \
-H "Authorization: Basic $(printf '%s:%s' "$SENDGO_ACCESS_KEY" "$SENDGO_SECRET_KEY" | base64)"
{
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
발급받은 토큰으로 호출
이후 모든 요청은 Bearer 인증을 씁니다. v1 과 v2 의 값이 다릅니다.
| 버전 | 헤더 |
|---|---|
| v1 | Authorization: Bearer base64(token) |
| v2 | Authorization: Bearer token |
v1 에서 토큰을 한 번 더 인코딩하지 않으면 401 이 돌아옵니다. 신규 연동은 v2 를 쓰세요.
curl -X POST https://sendgo.io/api/v2/notices/send \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"templateCode": "ORDER_CONFIRM_001",
"scheduleType": "DIRECTLY",
"kakaoSenderKey": "your_kakao_sender_key",
"senderKey": "your_sms_sender_key",
"contacts": [{ "contact": "01012345678", "var1": "ORD-001" }]
}'
SDK 를 쓸 때
키만 넘기면 끝입니다. 토큰 발급, 캐싱, 만료 시 재발급, 401/403 재시도가 모두 안에서 처리됩니다.
import Sendgo from '@sendgo/node';
const sendgo = new Sendgo({
accessKey: process.env.SENDGO_ACCESS_KEY!,
secretKey: process.env.SENDGO_SECRET_KEY!,
apiVersion: 'v2',
});
// 토큰 관련 코드는 없습니다. 첫 발송 때 알아서 받아옵니다.
from sendgo import Sendgo
client = Sendgo(
access_key=os.environ["SENDGO_ACCESS_KEY"],
secret_key=os.environ["SENDGO_SECRET_KEY"],
api_version="v2",
)
<?php
$sendgo = new Sendgo\Php\Sendgo([
'access_key' => $_ENV['SENDGO_ACCESS_KEY'],
'secret_key' => $_ENV['SENDGO_SECRET_KEY'],
'api_version' => 'v2',
]);
client, err := sendgo.New(sendgo.Config{
AccessKey: os.Getenv("SENDGO_ACCESS_KEY"),
SecretKey: os.Getenv("SENDGO_SECRET_KEY"),
ApiVersion: "v2",
})
클라이언트는 한 번 만들어 재사용하세요. 요청마다 새로 만들면 캐시된 토큰이 버려지고 매번 토큰을 새로 발급받게 됩니다. Laravel·Spring·NestJS 확장은 싱글턴으로 등록하므로 이 문제가 없습니다.
인증 오류
| 코드 | HTTP | 원인 |
|---|---|---|
INVALID_ACCESS_KEY |
401 | 액세스 키가 존재하지 않거나 시크릿이 틀림 |
ACCESS_KEY_NOT_APPROVED |
403 | 앱이 아직 승인 대기 상태 |
IP_NOT_ALLOWED |
403 | 앱에 설정한 허용 IP 밖에서 호출 |
IP_NOT_ALLOWED 는 로컬에서 개발할 때 자주 만납니다. 개발 환경에서는 허용 IP 를 비워 두거나 개발자 IP 를 추가하세요. 서버 IP 는 배포 후 실제 아웃바운드 IP 로 확인해야 합니다 — NAT 게이트웨이나 로드밸런서 뒤라면 인스턴스 IP 와 다릅니다.
다음 단계
자주 묻는 질문
- v1 과 v2 의 인증은 무엇이 다른가요?
- 토큰 발급 방식은 같지만 Bearer 값이 다릅니다. v1 은 Authorization: Bearer base64(token) 으로 토큰을 한 번 더 Base64 인코딩해 보내고, v2 는 Authorization: Bearer token 으로 원본을 그대로 보냅니다. 신규 연동은 v2 를 쓰세요.
- 요청할 때마다 토큰을 새로 발급받아야 하나요?
- 아니요. 발급받은 토큰은 만료 전까지 재사용합니다. 공식 SDK 는 토큰을 캐시하고 만료 시 자동 재발급하며, 401/403 을 받으면 갱신 후 1회 재시도합니다. 직접 구현할 경우에도 매 요청 발급은 피하세요.
- 401 과 403 은 어떻게 다른가요?
- 401 은 인증 실패(INVALID_ACCESS_KEY 등)로 키 자체가 틀렸거나 토큰이 만료된 경우입니다. 403 은 인증은 됐지만 권한이 없는 경우로, ACCESS_KEY_NOT_APPROVED(앱 미승인)나 IP_NOT_ALLOWED(허용 IP 밖) 가 대표적입니다.