Sendgo API authentication — access keys and bearer tokens
Exchange an accessKey and secretKey for a bearer token, and call the Sendgo API with it. Differences between v1 and v2, token caching, and the 401/403 codes.
POST /api/v2/tokenSendgo authentication is two steps: exchange keys for a token, send with the token.
Most of the time you never need this page — the SDKs handle all of it. It matters when you call REST directly or build a client for a language with no SDK.
What you need
An accessKey and secretKey from Integration → Apps in the Sendgo console.
export SENDGO_ACCESS_KEY=your_access_key
export SENDGO_SECRET_KEY=your_secret_key
These carry the full sending permission for the account. Do not commit them. If you already did, revoking and reissuing in the console is the only fix — reverting the commit does not un-leak anything.
Issue a token
Base64-encode accessKey:secretKey and send it as Basic auth.
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..."
}
}
Call with the token
Everything after this uses bearer auth, and v1 and v2 differ.
| Version | Header |
|---|---|
| v1 | Authorization: Bearer base64(token) |
| v2 | Authorization: Bearer token |
Forgetting the second encode on v1 gives you a 401. Use 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" }]
}'
With an SDK
Pass the keys and stop thinking about it. Issuance, caching, refresh on expiry and the 401/403 retry all happen inside.
import Sendgo from '@sendgo/node';
const sendgo = new Sendgo({
accessKey: process.env.SENDGO_ACCESS_KEY!,
secretKey: process.env.SENDGO_SECRET_KEY!,
apiVersion: 'v2',
});
// No token code. It fetches one on the first send.
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",
})
Build the client once and reuse it. A new client per request throws away the cached token and fetches a new one every time. The Laravel, Spring and NestJS extensions register a singleton, so they avoid this by construction.
Authentication errors
| Code | HTTP | Cause |
|---|---|---|
INVALID_ACCESS_KEY |
401 | Key does not exist, or the secret is wrong |
ACCESS_KEY_NOT_APPROVED |
403 | App is still pending approval |
IP_NOT_ALLOWED |
403 | Called from outside the app's IP allowlist |
IP_NOT_ALLOWED shows up constantly during local development. Leave the allowlist empty on a development app, or add your own IP. For production, check the actual outbound IP — behind a NAT gateway or load balancer it is not the instance IP.
Next
자주 묻는 질문
- How does authentication differ between v1 and v2?
- Token issuance is identical; the bearer value is not. v1 expects Authorization: Bearer base64(token), with the token Base64-encoded a second time. v2 expects the raw token. Use v2 for new integrations.
- Do I need a fresh token for every request?
- No. Reuse the token until it expires. Every official SDK caches it, refreshes it on expiry and retries once after a 401 or 403. If you implement the client yourself, avoid issuing a token per request.
- What is the difference between 401 and 403?
- 401 is an authentication failure — the key is wrong or the token expired (INVALID_ACCESS_KEY). 403 means you authenticated but lack permission: ACCESS_KEY_NOT_APPROVED for an unapproved app, or IP_NOT_ALLOWED when calling from outside the allowlist.
- Where do I get an access key?
- Create an app under Integration → Apps in the Sendgo console. The accessKey and secretKey are issued together and carry the full sending permission for the account.