Sendgo API authentication — access keys and bearer tokens

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/token

Sendgo 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.

이 문서에서 쓰는 패키지

관련 문서