배치 운세 생성
curl --request POST \
--url https://sajuapi.dev/v1/fortunes/batch \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"profile_ids": [
{}
],
"fortune_type": "<string>",
"fortune_date": "<string>",
"model": "<string>",
"webhook_url": "<string>"
}
'import requests
url = "https://sajuapi.dev/v1/fortunes/batch"
payload = {
"profile_ids": [{}],
"fortune_type": "<string>",
"fortune_date": "<string>",
"model": "<string>",
"webhook_url": "<string>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
profile_ids: [{}],
fortune_type: '<string>',
fortune_date: '<string>',
model: '<string>',
webhook_url: '<string>'
})
};
fetch('https://sajuapi.dev/v1/fortunes/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sajuapi.dev/v1/fortunes/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'profile_ids' => [
[
]
],
'fortune_type' => '<string>',
'fortune_date' => '<string>',
'model' => '<string>',
'webhook_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sajuapi.dev/v1/fortunes/batch"
payload := strings.NewReader("{\n \"profile_ids\": [\n {}\n ],\n \"fortune_type\": \"<string>\",\n \"fortune_date\": \"<string>\",\n \"model\": \"<string>\",\n \"webhook_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sajuapi.dev/v1/fortunes/batch")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"profile_ids\": [\n {}\n ],\n \"fortune_type\": \"<string>\",\n \"fortune_date\": \"<string>\",\n \"model\": \"<string>\",\n \"webhook_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sajuapi.dev/v1/fortunes/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"profile_ids\": [\n {}\n ],\n \"fortune_type\": \"<string>\",\n \"fortune_date\": \"<string>\",\n \"model\": \"<string>\",\n \"webhook_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body배치 운세 생성
POST
/
v1
/
fortunes
/
batch
배치 운세 생성
curl --request POST \
--url https://sajuapi.dev/v1/fortunes/batch \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"profile_ids": [
{}
],
"fortune_type": "<string>",
"fortune_date": "<string>",
"model": "<string>",
"webhook_url": "<string>"
}
'import requests
url = "https://sajuapi.dev/v1/fortunes/batch"
payload = {
"profile_ids": [{}],
"fortune_type": "<string>",
"fortune_date": "<string>",
"model": "<string>",
"webhook_url": "<string>"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
profile_ids: [{}],
fortune_type: '<string>',
fortune_date: '<string>',
model: '<string>',
webhook_url: '<string>'
})
};
fetch('https://sajuapi.dev/v1/fortunes/batch', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://sajuapi.dev/v1/fortunes/batch",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'profile_ids' => [
[
]
],
'fortune_type' => '<string>',
'fortune_date' => '<string>',
'model' => '<string>',
'webhook_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://sajuapi.dev/v1/fortunes/batch"
payload := strings.NewReader("{\n \"profile_ids\": [\n {}\n ],\n \"fortune_type\": \"<string>\",\n \"fortune_date\": \"<string>\",\n \"model\": \"<string>\",\n \"webhook_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://sajuapi.dev/v1/fortunes/batch")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"profile_ids\": [\n {}\n ],\n \"fortune_type\": \"<string>\",\n \"fortune_date\": \"<string>\",\n \"model\": \"<string>\",\n \"webhook_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://sajuapi.dev/v1/fortunes/batch")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"profile_ids\": [\n {}\n ],\n \"fortune_type\": \"<string>\",\n \"fortune_date\": \"<string>\",\n \"model\": \"<string>\",\n \"webhook_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyv1 Enterprise API (Coming Soon)이 엔드포인트는 Enterprise 버전에서 제공될 예정입니다.
현재는 v0 API를 사용하세요.
배치 요청은 비동기로 처리됩니다. 요청 즉시
batch_id가 반환되며, 완료 시 웹훅으로 알림을 받거나 상태를 폴링할 수 있습니다.Request Body 파라미터
array
required
운세를 생성할 프로필 ID 배열입니다. 최소 1개, 최대 100개까지 지정할 수 있습니다.
string
required
운세 유형입니다.
daily, yearly, monthly 중 하나입니다.string
운세 날짜입니다. ISO 8601 형식(YYYY-MM-DD)입니다. 기본값은 오늘입니다.
string
default:"haiku"
사용할 AI 모델입니다. 배치 요청에서는 비용 효율성을 위해
haiku가 권장됩니다.string
배치 완료 시 알림을 받을 웹훅 URL입니다. 설정하면 완료 시 POST 요청이 전송됩니다.
Response
성공
배치 요청이 접수되면 Batch 객체가 반환됩니다.실패
| 상태 코드 | 에러 타입 | 설명 |
|---|---|---|
| 400 | validation_error | 요청 데이터가 유효하지 않음 |
| 401 | authentication_error | API 키가 유효하지 않음 |
| 413 | payload_too_large | 프로필 수가 100개를 초과함 |
| 429 | rate_limited | 요청 한도 초과 |
요청 예시
curl -X POST https://api.sajuapi.dev/v1/fortunes/batch \
-H "X-API-Key: bs_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"profile_ids": [
"prf_abc123",
"prf_def456",
"prf_ghi789"
],
"fortune_type": "daily",
"fortune_date": "2025-01-16",
"model": "haiku",
"webhook_url": "https://your-server.com/webhooks/batch-complete"
}'
const response = await fetch('https://api.sajuapi.dev/v1/fortunes/batch', {
method: 'POST',
headers: {
'X-API-Key': 'bs_live_xxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
profile_ids: ['prf_abc123', 'prf_def456', 'prf_ghi789'],
fortune_type: 'daily',
fortune_date: '2025-01-16',
model: 'haiku',
webhook_url: 'https://your-server.com/webhooks/batch-complete'
})
});
const batch = await response.json();
console.log(batch.id); // batch_xyz789
import requests
response = requests.post(
'https://api.sajuapi.dev/v1/fortunes/batch',
headers={'X-API-Key': 'bs_live_xxx'},
json={
'profile_ids': ['prf_abc123', 'prf_def456', 'prf_ghi789'],
'fortune_type': 'daily',
'fortune_date': '2025-01-16',
'model': 'haiku',
'webhook_url': 'https://your-server.com/webhooks/batch-complete'
}
)
batch = response.json()
응답 예시
{
"id": "batch_xyz789abc123",
"status": "processing",
"total_count": 3,
"completed_count": 0,
"failed_count": 0,
"fortune_type": "daily",
"fortune_date": "2025-01-16",
"model": "haiku",
"webhook_url": "https://your-server.com/webhooks/batch-complete",
"created_at": "2025-01-16T09:00:00Z",
"estimated_completion": "2025-01-16T09:02:00Z"
}
Batch 객체
| 필드 | 타입 | 설명 |
|---|---|---|
id | string | 배치 ID입니다. batch_ 접두사로 시작합니다. |
status | string | 상태입니다. pending, processing, completed, failed 중 하나입니다. |
total_count | integer | 전체 프로필 수입니다. |
completed_count | integer | 완료된 프로필 수입니다. |
failed_count | integer | 실패한 프로필 수입니다. |
fortune_type | string | 운세 유형입니다. |
fortune_date | string | 운세 날짜입니다. |
model | string | 사용된 AI 모델입니다. |
webhook_url | string | 웹훅 URL입니다. 설정한 경우에만 반환됩니다. |
created_at | string | 생성 시간입니다. |
estimated_completion | string | 예상 완료 시간입니다. |
completed_at | string | 완료 시간입니다. 완료 후에만 반환됩니다. |
results | array | 결과 배열입니다. 완료 후에만 반환됩니다. |
배치 상태 조회
배치 상태를 확인하려면GET /v1/fortunes/batch/{batch_id}를 호출합니다.
curl -X GET https://api.sajuapi.dev/v1/fortunes/batch/batch_xyz789abc123 \
-H "X-API-Key: bs_live_xxx"
완료된 배치 응답
{
"id": "batch_xyz789abc123",
"status": "completed",
"total_count": 3,
"completed_count": 3,
"failed_count": 0,
"results": [
{
"profile_id": "prf_abc123",
"fortune_id": "ftn_result1",
"status": "success"
},
{
"profile_id": "prf_def456",
"fortune_id": "ftn_result2",
"status": "success"
},
{
"profile_id": "prf_ghi789",
"fortune_id": "ftn_result3",
"status": "success"
}
],
"completed_at": "2025-01-16T09:01:45Z"
}
웹훅 페이로드
배치 완료 시 설정된webhook_url로 다음 페이로드가 전송됩니다.
{
"event": "batch.completed",
"batch_id": "batch_xyz789abc123",
"status": "completed",
"total_count": 3,
"completed_count": 3,
"failed_count": 0,
"completed_at": "2025-01-16T09:01:45Z"
}
사용 사례
매일 자정에 모든 사용자 운세 생성
// 매일 자정(KST)에 실행되는 크론 작업
async function generateDailyFortunes() {
// 활성 사용자 프로필 ID 조회
const profiles = await getActiveProfileIds();
// 100개씩 배치 처리
for (let i = 0; i < profiles.length; i += 100) {
const batch = profiles.slice(i, i + 100);
await fetch('/v1/fortunes/batch', {
method: 'POST',
headers: {
'X-API-Key': process.env.API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
profile_ids: batch,
fortune_type: 'daily',
model: 'haiku'
})
});
}
}
⌘I