API

API Key

작성일 2026.02.27 | 수정일 2026.02.27

REST API를 요청할 때 HTTP 헤더에 Authorization 정보를 추가하여 인증받을 수 있습니다. API를 요청한 계정의 소유자를 확인하는데 필수적인 절차입니다.

솔라피 API Key 관리 페이지에서 API Key와 API Secret을 생성하여 REST API 호출에 사용하실 수 있습니다.
Authorization 헤더 정보를 전달하는 방식은 HTTP에서 인증을 위한 수단으로 널리 사용되고 있습니다.
Basic access authentication을 참고하세요.

Authorization 헤더 형식

Authorization: <AuthenticationMethod> apiKey=<API Key>, date=<Date Time>, salt=<Salt>, signature=<Signature>
curl -X GET https://api.solapi.com/messages/v4/list \
  --header "Authorization: HMAC-SHA256 apiKey=NCSAYU7YDBXYORXC, date=2019-07-01T00:41:48Z, salt=jqsba2jxjnrjor, signature=1779eac71a24cbeeadfa7263cb84b7ea0af1714f5c0270aa30ffd34600e363b4"

파라미터 설명

파라미터제약사항설명
AuthenticationMethodHMAC-SHA256, HMAC-MD5 중 선택Signature 생성 알고리즘
API Key솔라피 콘솔에서 생성발급받은 API Key
Date TimeISO 8601 규격 (예: 2019-07-01T00:41:48Z)요청 시간
Salt12~64바이트의 불규칙적인 문자열랜덤 문자열
SignatureDate Time + Salt를 데이터로 하고 API Secret을 Key로 생성

Signature 생성 방법

Signature는 다음과 같은 방식으로 생성됩니다

  1. 데이터 준비: <Date Time> + <Salt> 문자열 연결

  2. HMAC 생성: API Secret을 Key로 사용하여 HMAC 해시 생성

  3. 알고리즘: HMAC-SHA256 또는 HMAC-MD5 선택 가능

error

API Secret은 Signature 생성 시에만 사용하고 외부에 노출되지 않도록 주의하세요.

보안 제약사항

제약사항목적Description
시간 제한Replay Attack 방지서버 시간 기준 ±15분 이내
중복 방지재사용 공격 차단15분 내 동일한 Signature 재사용 불가
Salt 변경Signature 고유성 보장매 요청마다 다른 Salt 사용 필수

메시지의 무결성 검증을 위해 Hash 기반의 MAC 알고리즘을 사용합니다.
Hash-based message authentication code를 참고하세요.


언어별 구현 예제

Node.js 20.19.0
const crypto = require('crypto');

// """HMAC-SHA256 시그니처 생성""" function generateSignature(apiSecret, dateTime, salt) { const data = dateTime + salt; return crypto .createHmac('sha256', apiSecret) .update(data) .digest('hex'); }

// """Authorization 헤더 생성""" function createAuthHeader(apiKey, apiSecret) { const dateTime = new Date().toISOString(); const salt = crypto.randomBytes(16).toString('hex'); const signature = generateSignature(apiSecret, dateTime, salt);

return HMAC-SHA256 apiKey=${apiKey}, date=${dateTime}, salt=${salt}, signature=${signature}; }

const axios = require('axios');

async function sendMessage(apiKey, apiSecret, messageData) { const authHeader = createAuthHeader(apiKey, apiSecret);

try { const response = await axios.post('https://api.solapi.com/messages/v4/send-many/detail', messageData, { headers: { 'Authorization': authHeader, 'Content-Type': 'application/json' } });

return response.data;

} catch (error) { console.error('API 요청 실패:', error.response?.data || error.message); throw error; } }

Java 17+
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.time.Instant;
import java.time.format.DateTimeFormatter;

public class SolapiAuth {

// """HMAC-SHA256 시그니처 생성""" public static String generateSignature(String apiSecret, String dateTime, String salt) throws Exception { Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(apiSecret.getBytes(), "HmacSHA256")); byte[] hash = mac.doFinal((dateTime + salt).getBytes()); return HexFormat.of().formatHex(hash); } // """Authorization 헤더 생성""" public static String createAuthHeader(String apiKey, String apiSecret) throws Exception { String dateTime = Instant.now().toString(); String salt = UUID.randomUUID().toString().replace("-", ""); String signature = generateSignature(apiSecret, dateTime, salt);

	return "HMAC-SHA256 apiKey=%s, date=%s, salt=%s, signature=%s"
		.formatted(apiKey, dateTime, salt, signature);
}

}

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;

public class SolapiClient {

public static String sendMessage(String apiKey, String apiSecret, String messageJson) 
        throws Exception {
    String authHeader = SolapiAuth.createAuthHeader(apiKey, apiSecret);
    
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.solapi.com/messages/v4/send-many/detail"))
            .header("Authorization", authHeader)
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(messageJson))
            .build();
    
    HttpResponse&lt;String&gt; response = client.send(request, 
            HttpResponse.BodyHandlers.ofString());
    
    return response.body();
}

}

Kotlin 2.1
import java.time.Instant
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

object SolapiAuth {

/**
 * HMAC-SHA256 시그니처 생성
 */
@Throws(Exception::class)
fun generateSignature(apiSecret: String, dateTime: String, salt: String): String {
    val mac = Mac.getInstance("HmacSHA256")
    mac.init(SecretKeySpec(apiSecret.toByteArray(), "HmacSHA256"))
    val hash = mac.doFinal((dateTime + salt).toByteArray())
    return HexFormat.of().formatHex(hash)
}

/**
 * Authorization 헤더 생성
 */
@Throws(Exception::class)
fun createAuthHeader(apiKey: String, apiSecret: String): String {
    val dateTime = Instant.now().toString()
    val salt = UUID.randomUUID().toString().replace("-", "")
    val signature = generateSignature(apiSecret, dateTime, salt)
    
    return "HMAC-SHA256 apiKey=$apiKey, date=$dateTime, salt=$salt, signature=$signature"
}

}

import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse

object SolapiClient {

@Throws(Exception::class)
fun sendMessage(apiKey: String, apiSecret: String, messageJson: String): String {
    val authHeader = SolapiAuth.createAuthHeader(apiKey, apiSecret)
    
    val client = HttpClient.newHttpClient()
    val request = HttpRequest.newBuilder()
        .uri(URI.create("https://api.solapi.com/messages/v4/send-many/detail"))
        .header("Authorization", authHeader)
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString(messageJson))
        .build()
    
    val response = client.send(request, HttpResponse.BodyHandlers.ofString())
    
    return response.body()
}

}

Python 3.12.0
import hmac
import hashlib
import secrets
from datetime import datetime, timezone

def generate_signature(api_secret: str, date_time: str, salt: str) -> str: """HMAC-SHA256 시그니처 생성""" data = date_time + salt signature = hmac.new( api_secret.encode(), data.encode(), hashlib.sha256 ).hexdigest() return signature

def create_auth_header(api_key: str, api_secret: str) -> str: """Authorization 헤더 생성""" date_time = datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z') salt = secrets.token_hex(16) signature = generate_signature(api_secret, date_time, salt)

return f"HMAC-SHA256 apiKey={api_key}, date={date_time}, salt={salt}, signature={signature}"</code></pre><pre data-title="API 요청 예제"><code>import requests

from typing import Dict, Any

def send_message(api_key: str, api_secret: str, message_data: Dict[str, Any]) -> Dict[str, Any]: """메시지 전송 API 호출""" auth_header = create_auth_header(api_key, api_secret)

headers = {
    'Authorization': auth_header,
    'Content-Type': 'application/json'
}

response = requests.post(
    'https://api.solapi.com/messages/v4/send-many/detail',
    json=message_data,
    headers=headers
)

response.raise_for_status()
return response.json()

if name == "main": message_data = { "message": { "to": "01012345678", "from": "01087654321", "text": "테스트 메시지입니다." } }

PHP 8.4.11
<?php

class SolapiAuth { // HMAC-SHA256 시그니처 생성 public static function generateSignature($apiSecret, $dateTime, $salt) { $data = $dateTime . $salt; return hash_hmac('sha256', $data, $apiSecret); }

// Authorization 헤더 생성
public static function createAuthHeader($apiKey, $apiSecret) {
    $dateTime = gmdate('Y-m-d\TH:i:s\Z');
    $salt = bin2hex(random_bytes(16));
    $signature = self::generateSignature($apiSecret, $dateTime, $salt);
    
    return "HMAC-SHA256 apiKey={$apiKey}, date={$dateTime}, salt={$salt}, signature={$signature}";
}

}

?>

<?php

function sendMessage($apiKey, $apiSecret, $messageData) { $authHeader = SolapiAuth::createAuthHeader($apiKey, $apiSecret);

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL =&gt; 'https://api.solapi.com/messages/v4/send-many/detail',
    CURLOPT_RETURNTRANSFER =&gt; true,
    CURLOPT_POST =&gt; true,
    CURLOPT_POSTFIELDS =&gt; json_encode($messageData),
    CURLOPT_HTTPHEADER =&gt; [
        'Authorization: ' . $authHeader,
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode !== 200) {
    throw new Exception("API 요청 실패: HTTP {$httpCode}");
}

return json_decode($response, true);

}

?>

Go 1.24.6
package main

import ( "crypto/hmac" "crypto/rand" "crypto/sha256" "encoding/hex" "fmt" "time" )

// HMAC-SHA256 시그니처 생성 func generateSignature(apiSecret, dateTime, salt string) string { data := dateTime + salt h := hmac.New(sha256.New, []byte(apiSecret)) h.Write([]byte(data)) return hex.EncodeToString(h.Sum(nil)) }

// Authorization 헤더 생성 func createAuthHeader(apiKey, apiSecret string) (string, error) { dateTime := time.Now().UTC().Format("2006-01-02T15:04:05Z")

saltBytes := make([]byte, 16)
if _, err := rand.Read(saltBytes); err != nil {
    return "", err
}
salt := hex.EncodeToString(saltBytes)

signature := generateSignature(apiSecret, dateTime, salt)

return fmt.Sprintf("HMAC-SHA256 apiKey=%s, date=%s, salt=%s, signature=%s",
    apiKey, dateTime, salt, signature), nil

}

package main

import ( "bytes" "encoding/json" "fmt" "io" "net/http" )

type MessageData struct { Message struct { To string json:"to" From string json:"from" Text string json:"text" } json:"message" }

func sendMessage(apiKey, apiSecret string, messageData MessageData) map[string]interface{} { authHeader := createAuthHeader(apiKey, apiSecret)

jsonData, _ := json.Marshal(messageData)

req, _ := http.NewRequest("POST", "https://api.solapi.com/messages/v4/send-many/detail", bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", authHeader)
req.Header.Set("Content-Type", "application/json")

client := &amp;http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)

var result map[string]interface{}
json.Unmarshal(body, &amp;result)

return result

}</code>


오류 처리

API 인증 과정에서 발생할 수 있는 오류들과 대응 방법입니다.

에러 코드HTTP 상태 코드해결 방법설명
InvalidAPIKey403API Key 확인 및 재발급유효하지 않은 API Key
SignatureDoesNotMatch403Signature 생성 로직 검토Signature 불일치
RequestTimeTooSkewed403시스템 시간 동기화시간 차이 초과 (±15분)
DuplicatedSignature403Salt 값 변경 및 재시도중복된 Signature 사용
warning

서버와 클라이언트 간의 시간 차이가 15분을 초과하면 인증이 실패합니다. 시스템 시간을 정확히 동기화해 주세요.