curl https://api.apimart.ai/v1/messages \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2025-10-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, world"}
]
}'
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello, world"}
]
)
print(message.content)
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.API_KEY,
baseURL: 'https://api.apimart.ai'
});
const message = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Hello, world' }
]
});
console.log(message.content);
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/messages"
payload := map[string]interface{}{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": []map[string]string{
{
"role": "user",
"content": "Hello, world",
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("x-api-key", os.Getenv("API_KEY"))
req.Header.Set("anthropic-version", "2025-10-01")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/messages";
String apiKey = System.getenv("API_KEY");
String payload = """
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("x-api-key", apiKey)
.header("anthropic-version", "2025-10-01")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/messages";
$apiKey = getenv('API_KEY');
$payload = [
"model" => "claude-sonnet-4-6",
"max_tokens" => 1024,
"messages" => [
[
"role" => "user",
"content" => "Hello, world"
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"x-api-key: " . $apiKey,
"anthropic-version: 2025-10-01",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/messages")
api_key = ENV['API_KEY']
payload = {
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [
{
role: "user",
content: "Hello, world"
}
]
}
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["anthropic-version"] = "2025-10-01"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/messages")!
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] ?? ""
let payload: [String: Any] = [
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
[
"role": "user",
"content": "Hello, world"
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
request.setValue("2025-10-01", forHTTPHeaderField: "anthropic-version")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/messages";
var apiKey = Environment.GetEnvironmentVariable("API_KEY");
var payload = @"{
""model"": ""claude-sonnet-4-6"",
""max_tokens"": 1024,
""messages"": [
{
""role"": ""user"",
""content"": ""Hello, world""
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
client.DefaultRequestHeaders.Add("anthropic-version", "2025-10-01");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
int main(void) {
CURL *curl;
CURLcode res;
const char *api_key = getenv("API_KEY");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/messages";
const char *payload = "{"
"\"model\":\"claude-sonnet-4-6\","
"\"max_tokens\":1024,"
"\"messages\":[{\"role\":\"user\",\"content\":\"Hello, world\"}]"
"}";
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "x-api-key: %s", api_key);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, auth_header);
headers = curl_slist_append(headers, "anthropic-version: 2025-10-01");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/messages"];
NSString *apiKey = [NSProcessInfo processInfo].environment[@"API_KEY"];
NSDictionary *payload = @{
@"model": @"claude-sonnet-4-6",
@"max_tokens": @1024,
@"messages": @[
@{
@"role": @"user",
@"content": @"Hello, world"
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:apiKey forHTTPHeaderField:@"x-api-key"];
[request setValue:@"2025-10-01" forHTTPHeaderField:@"anthropic-version"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/messages"
let api_key = Sys.getenv "API_KEY"
let payload = {|{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "x-api-key" api_key
|> fun h -> Header.add h "anthropic-version" "2025-10-01"
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/messages');
final apiKey = Platform.environment['API_KEY'];
final payload = {
'model': 'claude-sonnet-4-6',
'max_tokens': 1024,
'messages': [
{
'role': 'user',
'content': 'Hello, world'
}
]
};
final response = await http.post(
url,
headers: {
'x-api-key': apiKey!,
'anthropic-version': '2025-10-01',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/messages"
api_key <- Sys.getenv("API_KEY")
payload <- list(
model = "claude-sonnet-4-6",
max_tokens = 1024,
messages = list(
list(
role = "user",
content = "Hello, world"
)
)
)
response <- POST(
url,
add_headers(
`x-api-key` = api_key,
`anthropic-version` = "2025-10-01",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
{
"model": "claude-sonnet-4-6",
"id": "msg_011CdfeHuC728oxqaLrRNbcB",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello! I'm Claude. Nice to meet you."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 0
},
"output_tokens": 18,
"service_tier": "standard",
"inference_geo": "global"
}
}
{
"error": {
"code": "model_not_found",
"message": "model not found (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Invalid API key (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Insufficient balance (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Too many requests (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Internal server error (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
텍스트 시리즈
Claude Messages API
- Anthropic Claude Messages 네이티브 프로토콜(
POST /v1/messages)과 완전 호환 - 다중 턴 대화, 스트리밍 SSE, 도구 호출, extended thinking 지원
- 텍스트·이미지 등 멀티모달 콘텐츠 지원
- 응답은 업스트림을 그대로 투과하며
{code, data}외부 래퍼 없음
POST
/
v1
/
messages
curl https://api.apimart.ai/v1/messages \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2025-10-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, world"}
]
}'
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello, world"}
]
)
print(message.content)
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.API_KEY,
baseURL: 'https://api.apimart.ai'
});
const message = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Hello, world' }
]
});
console.log(message.content);
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/messages"
payload := map[string]interface{}{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": []map[string]string{
{
"role": "user",
"content": "Hello, world",
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("x-api-key", os.Getenv("API_KEY"))
req.Header.Set("anthropic-version", "2025-10-01")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/messages";
String apiKey = System.getenv("API_KEY");
String payload = """
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("x-api-key", apiKey)
.header("anthropic-version", "2025-10-01")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/messages";
$apiKey = getenv('API_KEY');
$payload = [
"model" => "claude-sonnet-4-6",
"max_tokens" => 1024,
"messages" => [
[
"role" => "user",
"content" => "Hello, world"
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"x-api-key: " . $apiKey,
"anthropic-version: 2025-10-01",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/messages")
api_key = ENV['API_KEY']
payload = {
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [
{
role: "user",
content: "Hello, world"
}
]
}
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["anthropic-version"] = "2025-10-01"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/messages")!
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] ?? ""
let payload: [String: Any] = [
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
[
"role": "user",
"content": "Hello, world"
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
request.setValue("2025-10-01", forHTTPHeaderField: "anthropic-version")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/messages";
var apiKey = Environment.GetEnvironmentVariable("API_KEY");
var payload = @"{
""model"": ""claude-sonnet-4-6"",
""max_tokens"": 1024,
""messages"": [
{
""role"": ""user"",
""content"": ""Hello, world""
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
client.DefaultRequestHeaders.Add("anthropic-version", "2025-10-01");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
int main(void) {
CURL *curl;
CURLcode res;
const char *api_key = getenv("API_KEY");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/messages";
const char *payload = "{"
"\"model\":\"claude-sonnet-4-6\","
"\"max_tokens\":1024,"
"\"messages\":[{\"role\":\"user\",\"content\":\"Hello, world\"}]"
"}";
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "x-api-key: %s", api_key);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, auth_header);
headers = curl_slist_append(headers, "anthropic-version: 2025-10-01");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/messages"];
NSString *apiKey = [NSProcessInfo processInfo].environment[@"API_KEY"];
NSDictionary *payload = @{
@"model": @"claude-sonnet-4-6",
@"max_tokens": @1024,
@"messages": @[
@{
@"role": @"user",
@"content": @"Hello, world"
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:apiKey forHTTPHeaderField:@"x-api-key"];
[request setValue:@"2025-10-01" forHTTPHeaderField:@"anthropic-version"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/messages"
let api_key = Sys.getenv "API_KEY"
let payload = {|{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "x-api-key" api_key
|> fun h -> Header.add h "anthropic-version" "2025-10-01"
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/messages');
final apiKey = Platform.environment['API_KEY'];
final payload = {
'model': 'claude-sonnet-4-6',
'max_tokens': 1024,
'messages': [
{
'role': 'user',
'content': 'Hello, world'
}
]
};
final response = await http.post(
url,
headers: {
'x-api-key': apiKey!,
'anthropic-version': '2025-10-01',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/messages"
api_key <- Sys.getenv("API_KEY")
payload <- list(
model = "claude-sonnet-4-6",
max_tokens = 1024,
messages = list(
list(
role = "user",
content = "Hello, world"
)
)
)
response <- POST(
url,
add_headers(
`x-api-key` = api_key,
`anthropic-version` = "2025-10-01",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
{
"model": "claude-sonnet-4-6",
"id": "msg_011CdfeHuC728oxqaLrRNbcB",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello! I'm Claude. Nice to meet you."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 0
},
"output_tokens": 18,
"service_tier": "standard",
"inference_geo": "global"
}
}
{
"error": {
"code": "model_not_found",
"message": "model not found (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Invalid API key (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Insufficient balance (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Too many requests (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Internal server error (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
두 API를 혼용하지 마세요:
/v1/*는 추론 API(본 문서, 업스트림 그대로 투과·래퍼 없음); /api/*는 관리 API(잔액/로그 조회 등, 응답은 {success, message, data}). 다른 문서에서 /v1/messages가 {code, data}를 반환한다고 적혀 있어도 본 문서를 기준으로 하세요.curl https://api.apimart.ai/v1/messages \
-H "x-api-key: $API_KEY" \
-H "anthropic-version: 2025-10-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "Hello, world"}
]
}'
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello, world"}
]
)
print(message.content)
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.API_KEY,
baseURL: 'https://api.apimart.ai'
});
const message = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'Hello, world' }
]
});
console.log(message.content);
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
url := "https://api.apimart.ai/v1/messages"
payload := map[string]interface{}{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": []map[string]string{
{
"role": "user",
"content": "Hello, world",
},
},
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("x-api-key", os.Getenv("API_KEY"))
req.Header.Set("anthropic-version", "2025-10-01")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
String url = "https://api.apimart.ai/v1/messages";
String apiKey = System.getenv("API_KEY");
String payload = """
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("x-api-key", apiKey)
.header("anthropic-version", "2025-10-01")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
<?php
$url = "https://api.apimart.ai/v1/messages";
$apiKey = getenv('API_KEY');
$payload = [
"model" => "claude-sonnet-4-6",
"max_tokens" => 1024,
"messages" => [
[
"role" => "user",
"content" => "Hello, world"
]
]
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"x-api-key: " . $apiKey,
"anthropic-version: 2025-10-01",
"Content-Type: application/json"
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
require 'net/http'
require 'json'
require 'uri'
url = URI("https://api.apimart.ai/v1/messages")
api_key = ENV['API_KEY']
payload = {
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [
{
role: "user",
content: "Hello, world"
}
]
}
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["anthropic-version"] = "2025-10-01"
request["Content-Type"] = "application/json"
request.body = payload.to_json
response = http.request(request)
puts response.body
import Foundation
let url = URL(string: "https://api.apimart.ai/v1/messages")!
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] ?? ""
let payload: [String: Any] = [
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
[
"role": "user",
"content": "Hello, world"
]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
request.setValue("2025-10-01", forHTTPHeaderField: "anthropic-version")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: payload)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Error: \(error)")
return
}
if let data = data, let responseString = String(data: data, encoding: .utf8) {
print(responseString)
}
}
task.resume()
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var url = "https://api.apimart.ai/v1/messages";
var apiKey = Environment.GetEnvironmentVariable("API_KEY");
var payload = @"{
""model"": ""claude-sonnet-4-6"",
""max_tokens"": 1024,
""messages"": [
{
""role"": ""user"",
""content"": ""Hello, world""
}
]
}";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
client.DefaultRequestHeaders.Add("anthropic-version", "2025-10-01");
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
#include <stdio.h>
#include <curl/curl.h>
#include <stdlib.h>
int main(void) {
CURL *curl;
CURLcode res;
const char *api_key = getenv("API_KEY");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
const char *url = "https://api.apimart.ai/v1/messages";
const char *payload = "{"
"\"model\":\"claude-sonnet-4-6\","
"\"max_tokens\":1024,"
"\"messages\":[{\"role\":\"user\",\"content\":\"Hello, world\"}]"
"}";
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "x-api-key: %s", api_key);
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, auth_header);
headers = curl_slist_append(headers, "anthropic-version: 2025-10-01");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSURL *url = [NSURL URLWithString:@"https://api.apimart.ai/v1/messages"];
NSString *apiKey = [NSProcessInfo processInfo].environment[@"API_KEY"];
NSDictionary *payload = @{
@"model": @"claude-sonnet-4-6",
@"max_tokens": @1024,
@"messages": @[
@{
@"role": @"user",
@"content": @"Hello, world"
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:payload
options:0
error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:apiKey forHTTPHeaderField:@"x-api-key"];
[request setValue:@"2025-10-01" forHTTPHeaderField:@"anthropic-version"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
return;
}
NSString *result = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
}];
[task resume];
[[NSRunLoop mainRunLoop] run];
}
return 0;
}
(* Requires cohttp and yojson libraries *)
open Lwt
open Cohttp
open Cohttp_lwt_unix
let url = "https://api.apimart.ai/v1/messages"
let api_key = Sys.getenv "API_KEY"
let payload = {|{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Hello, world"
}
]
}|}
let () =
let headers = Header.init ()
|> fun h -> Header.add h "x-api-key" api_key
|> fun h -> Header.add h "anthropic-version" "2025-10-01"
|> fun h -> Header.add h "Content-Type" "application/json"
in
let body = Cohttp_lwt.Body.of_string payload in
let response = Client.post ~headers ~body (Uri.of_string url) >>= fun (resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body_str ->
print_endline body_str
in
Lwt_main.run response
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
void main() async {
final url = Uri.parse('https://api.apimart.ai/v1/messages');
final apiKey = Platform.environment['API_KEY'];
final payload = {
'model': 'claude-sonnet-4-6',
'max_tokens': 1024,
'messages': [
{
'role': 'user',
'content': 'Hello, world'
}
]
};
final response = await http.post(
url,
headers: {
'x-api-key': apiKey!,
'anthropic-version': '2025-10-01',
'Content-Type': 'application/json',
},
body: jsonEncode(payload),
);
print(response.body);
}
library(httr)
library(jsonlite)
url <- "https://api.apimart.ai/v1/messages"
api_key <- Sys.getenv("API_KEY")
payload <- list(
model = "claude-sonnet-4-6",
max_tokens = 1024,
messages = list(
list(
role = "user",
content = "Hello, world"
)
)
)
response <- POST(
url,
add_headers(
`x-api-key` = api_key,
`anthropic-version` = "2025-10-01",
`Content-Type` = "application/json"
),
body = toJSON(payload, auto_unbox = TRUE),
encode = "raw"
)
cat(content(response, "text"))
{
"model": "claude-sonnet-4-6",
"id": "msg_011CdfeHuC728oxqaLrRNbcB",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "Hello! I'm Claude. Nice to meet you."
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"stop_details": null,
"usage": {
"input_tokens": 12,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation": {
"ephemeral_5m_input_tokens": 0,
"ephemeral_1h_input_tokens": 0
},
"output_tokens": 18,
"service_tier": "standard",
"inference_geo": "global"
}
}
{
"error": {
"code": "model_not_found",
"message": "model not found (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Invalid API key (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Insufficient balance (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Too many requests (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
{
"error": {
"code": "",
"message": "Internal server error (request id: 20260803181903172761862QzohKPXF)",
"param": "",
"type": "apimart_error"
}
}
인증
인증은 다음 두 방식을 지원하며, 둘 중 하나를 사용합니다:string
string
Bearer Token 인증(
x-api-key와 택일)Authorization: Bearer YOUR_API_KEY
string
API 버전(선택. 생략해도 정상 응답)이후 Anthropic 공식 엔드포인트로 이전하기 쉽도록 포함을 권장합니다:예:
2025-10-01요청 본문
string
기본값:"claude-sonnet-4-6"
필수
Model name
claude-opus-4-8- Claude Opus 4.8 flagship modelclaude-opus-4-7- Claude Opus 4.7 flagship modelclaude-opus-4-6- Claude Opus 4.6 flagship modelclaude-sonnet-4-6- Claude Sonnet 4.6 balanced versionclaude-opus-4-5-20251101- Claude Opus 4.5 model
array
필수
메시지 목록모델이 다음 응답을 생성하기 위한 메시지 배열입니다. 각 메시지는
단일 사용자 메시지:다중 턴 대화:미리 채워진 어시스턴트 응답:
role과 content 두 필드를 포함합니다.💡 빠른 입력 (Try it 영역):- ”+ Add an item”을 클릭하여 메시지 추가
role입력:user(사용자 메시지) 또는assistant(AI 응답, 다중 턴용)content입력: 하고 싶은 말
표시 필드 상세
표시 필드 상세
[{"role": "user", "content": "안녕하세요, Claude"}]
[
{"role": "user", "content": "안녕하세요."},
{"role": "assistant", "content": "안녕하세요, 저는 Claude입니다. 어떻게 도와드릴까요?"},
{"role": "user", "content": "LLM을 쉽게 설명해주실 수 있나요?"}
]
[
{"role": "user", "content": "태양의 그리스 이름은? (A) Sol (B) Helios (C) Sun"},
{"role": "assistant", "content": "정답은 ("}
]
integer
필수
생성할 최대 토큰 수(필수, Anthropic 공식과 동일)중지하기 전에 생성할 최대 토큰 수입니다. 모델이 이 제한에 도달하기 전에 중지될 수 있습니다.모델마다 최대값이 다릅니다. 최소값: 1
object
Extended thinking 설정활성화하면 응답
content에 thinking 블록이 포함될 수 있습니다. 플랫폼의 -thinking 모델 별칭에 의존하기보다 표준 모델명 + 본 파라미터 사용을 권장합니다. 공식 엔드포인트로 코드 변경 없이 이전하기 쉽습니다.다중 턴 대화에서 thinking 블록을 다시 보낼 때는 signature를 그대로 반환해야 합니다. 그렇지 않으면 업스트림이 거부합니다.string | array
시스템 프롬프트시스템 프롬프트는 Claude의 역할, 성격, 목표 및 지시사항을 설정합니다.문자열 형식:구조화된 형식:
{
"system": "당신은 전문 Python 프로그래밍 튜터입니다"
}
{
"system": [
{
"type": "text",
"text": "당신은 전문 Python 프로그래밍 튜터입니다"
}
]
}
number
Temperature 매개변수, 범위 0-1출력의 무작위성을 제어합니다:
- 낮은 값 (예: 0.2): 더 결정적이고 보수적
- 높은 값 (예: 0.8): 더 무작위적이고 창의적
number
핵 샘플링 매개변수, 범위 0-1핵 샘플링을 사용합니다.
temperature 또는 top_p 중 하나만 사용하는 것을 권장합니다.기본값: 1.0integer
Top-K 샘플링상위 K개 옵션에서만 샘플링하여 확률이 낮은 “롱테일” 응답을 제거합니다.고급 사용 사례에만 권장됩니다.
boolean
스트리밍 활성화
true이면 Server-Sent Events (SSE)를 사용하여 응답을 스트리밍합니다.기본값: falsearray
중지 시퀀스모델이 생성을 중지하도록 하는 사용자 정의 텍스트 시퀀스입니다.최대 4개의 시퀀스.예:
["\n\nHuman:", "\n\nAssistant:"]object
메타데이터요청에 대한 메타데이터 객체입니다.포함:
user_id: 사용자 식별자
array
도구 정의모델이 작업을 완료하는 데 사용할 수 있는 도구 목록입니다.함수 도구 예:지원되는 도구 유형:
{
"tools": [
{
"name": "get_weather",
"description": "주어진 위치의 현재 날씨 가져오기",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "도시 및 주, 예: San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "온도 단위"
}
},
"required": ["location"]
}
}
]
}
- 사용자 정의 함수 도구
- 컴퓨터 사용 도구 (computer_20241022)
- 텍스트 편집기 도구 (text_editor_20241022)
- Bash 도구 (bash_20241022)
object
도구 선택 전략모델이 도구를 사용하는 방법을 제어합니다:
{"type": "auto"}: 자동 결정 (기본값){"type": "any"}: 도구를 반드시 사용해야 함{"type": "tool", "name": "tool_name"}: 특정 도구 사용
응답
string
고유 메시지 식별자예:
"msg_013Zva2CMHLNnXjNJJKqJ2EF"string
객체 유형항상
"message"string
역할항상
"assistant"array
콘텐츠 블록 배열tool_use 블록:thinking 블록(요청 본문에
content는 type으로 블록 종류를 구분합니다. 한 번의 응답에 여러 블록이 포함될 수 있습니다(예: thinking 활성화 시 thinking + text 두 블록).text 블록:{ "type": "text", "text": "OK" }
{
"type": "tool_use",
"id": "toolu_01QgsazxKXSfQVj9Q1XxjYXo",
"name": "get_weather",
"input": { "city": "Beijing" },
"caller": { "type": "direct" }
}
caller는 업스트림이 추가한 필드로, 공식 문서에는 아직 수록되지 않았습니다. 파싱 시 무시하면 됩니다.thinking 파라미터가 있을 때 등장):{
"type": "thinking",
"thinking": "推理过程文本...",
"signature": "<约 500+ 字符的签名串>"
}
다중 턴 대화에서 thinking 블록을 다시 보낼 때는
signature를 그대로 반환해야 합니다. 그렇지 않으면 업스트림이 거부합니다.content[0]이 텍스트라고 가정하지 마세요. thinking을 켜면 content[0]이 thinking 블록일 수 있습니다. 다음처럼 순회하여 필터링하세요:text = "".join(b.text for b in resp.content if b.type == "text")
string
요청을 처리한 모델예:
"claude-sonnet-4-6"string
중지 이유가능한 값:
end_turn: 자연스러운 완료max_tokens: 최대 토큰 도달stop_sequence: 중지 시퀀스 도달tool_use: 도구 호출됨
string | null
트리거된 중지 시퀀스중지 시퀀스로 인해 중지된 경우 해당 시퀀스. 그렇지 않으면
nullobject | null
Anthropic의 비교적 새로운 필드. 일반 요청에서는
nullobject
사용 예제
기본 대화
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "양자 컴퓨팅의 기초를 설명해주세요"}
]
)
print(message.content[0].text)
다중 턴 대화
messages = [
{"role": "user", "content": "머신러닝이 무엇인가요?"},
{"role": "assistant", "content": "머신러닝은 AI의 한 분야입니다..."},
{"role": "user", "content": "실용적인 예를 들어주실 수 있나요?"}
]
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=messages
)
시스템 프롬프트 사용
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="당신은 코드 리뷰와 최적화 전문가인 시니어 Python 개발자입니다.",
messages=[
{"role": "user", "content": "이 코드를 어떻게 최적화할 수 있나요?\n\n[code]"}
]
)
스트리밍 응답
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "AI에 대한 짧은 에세이를 작성해주세요"}
]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
도구 사용
tools = [
{
"name": "get_stock_price",
"description": "실시간 주식 가격 가져오기",
"input_schema": {
"type": "object",
"properties": {
"ticker": {
"type": "string",
"description": "주식 티커 심볼, 예: AAPL"
}
},
"required": ["ticker"]
}
}
]
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "테슬라의 주식 가격은 얼마인가요?"}
]
)
# 도구 호출 처리
if message.stop_reason == "tool_use":
tool_use = next(block for block in message.content if block.type == "tool_use")
print(f"도구 호출: {tool_use.name}")
print(f"인수: {tool_use.input}")
비전 이해
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://example.com/image.jpg"
}
},
{
"type": "text",
"text": "이 이미지를 설명해주세요"
}
]
}
]
)
Base64 이미지
import base64
with open("image.jpg", "rb") as image_file:
image_data = base64.b64encode(image_file.read()).decode("utf-8")
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": image_data
}
},
{
"type": "text",
"text": "이 이미지를 분석해주세요"
}
]
}
]
)
모범 사례
1. 프롬프트 엔지니어링
명확한 역할 정의:system = """당신은 다음을 전문으로 하는 경험 많은 데이터 과학자입니다:
- 통계 분석 및 데이터 시각화
- 머신러닝 모델 개발
- Python 및 R 프로그래밍
전문적이고 정확한 조언을 제공하세요."""
message = "분석 결과를 summary, key_findings, recommendations 필드가 포함된 JSON 형식으로 반환해주세요."
2. 오류 처리
from anthropic import APIError, RateLimitError
try:
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "안녕하세요"}]
)
except RateLimitError:
print("요청 한도 초과, 나중에 다시 시도해주세요")
except APIError as e:
print(f"API 오류: {e}")
3. 토큰 최적화
# 더 짧은 프롬프트 사용
messages = [
{"role": "user", "content": "핵심 포인트 요약:\n\n[긴 텍스트]"}
]
# 출력 길이 제한
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=500, # 출력 제한
messages=messages
)
4. 응답 미리 채우기
# 모델을 특정 형식으로 안내
messages = [
{"role": "user", "content": "Python 모범 사례 5가지를 나열해주세요"},
{"role": "assistant", "content": "Python 모범 사례 5가지:\n\n1."}
]
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=messages
)
스트리밍 응답 처리
Python 스트리밍
import anthropic
client = anthropic.Anthropic(
api_key="YOUR_API_KEY",
base_url="https://api.apimart.ai"
)
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Python 데코레이터 예제를 작성해주세요"}
]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
JavaScript 스트리밍
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.API_KEY,
baseURL: 'https://api.apimart.ai'
});
const stream = await client.messages.stream({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
messages: [
{ role: 'user', content: 'React 컴포넌트 예제를 작성해주세요' }
]
});
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta' &&
chunk.delta.type === 'text_delta') {
process.stdout.write(chunk.delta.text);
}
}
플랫폼 차이 및 연동 주의사항
응답 래퍼 없음
POST /v1/messages 성공 시 Anthropic message 객체를 직접 반환합니다. {code, data} 외부 래퍼는 없습니다. 공식 SDK, Claude Code, Cline 등과 1:1 호환됩니다.
오류 형식(공식과의 유일한 실질적 차이)
{
"error": {
"code": "model_not_found",
"message": "... (request id: ...)",
"param": "",
"type": "apimart_error"
}
}
"type": "error"가 없고, error.type은 invalid_request_error 등 의미론적 유형이 아니라 항상 apimart_error입니다.
연동 권장: error.type으로 재시도 분기하지 마세요. **HTTP 상태 코드 + error.code**를 사용하세요:
| 상태 코드 | 의미 | 권장 동작 |
|---|---|---|
| 400 | 요청 파라미터 오류 | 재시도하지 않음. 요청 본문 확인 |
| 401 | Key 무효 | 재시도하지 않음 |
| 402 | 잔액 부족 | 재시도하지 않음. 충전 안내 |
| 429 | 요청 제한 | 백오프 후 재시도 |
| 5xx | 업스트림/게이트웨이 이상 | 지수 백오프로 재시도 |
error.message 끝의 request id와 응답 헤더 x-oneapi-request-id를 제공하세요.
스트리밍 SSE
요청에"stream": true를 추가합니다. 이벤트 순서는 공식과 동일합니다:
message_start → content_block_start → ping → content_block_delta(여러 번) → content_block_stop → message_delta → message_stop
⚠️ 스트리밍과 비스트리밍의 usage 구조가 다릅니다: message_delta.usage는 보통 4개의 토큰 필드만 있으며 cache_creation, service_tier, inference_geo는 없습니다. 분리해서 파싱하거나 모두 선택 필드로 처리하세요.
미구현 엔드포인트
POST /v1/messages/count_tokens는 미구현이며 404를 반환합니다. 공식 SDK의 client.messages.count_tokens()는 실패합니다. 토큰을 미리 추정하려면 로컬에서 계산하거나 응답의 usage.input_tokens를 읽으세요.
알 수 없는 필드는 반드시 무시
본 API는 업스트림을 투과하므로 Anthropic이 언제든 필드를 추가할 수 있습니다(예:stop_details, inference_geo, caller, output_tokens_details). 엄격한 schema를 사용하지 마세요:
- Go:
DisallowUnknownFields()사용 금지 - Pydantic:
extra="forbid"사용 금지 - TypeScript / Zod:
.strict()대신.passthrough()사용
모델명 권장
-thinking 접미사가 붙은 동명 모델은 플랫폼 확장 별칭입니다. 권장은 접미사 없는 표준 모델명 + 요청 본문의 thinking 파라미터로, 공식 엔드포인트 이전이 쉽습니다.
요청 본문의 기타 필드는 공식과 동일합니다: model, messages, max_tokens(필수), system, temperature, top_p, top_k, stop_sequences, stream, tools, tool_choice, thinking, metadata. 의미는 Anthropic Messages API를 따릅니다.
중요 참고사항
-
API 키 보안:
- API 키를 환경 변수에 저장하세요
- 소스 코드에 키를 하드코딩하지 마세요
- 정기적으로 키를 교체하세요
-
요청 제한:
- API 요청 제한에 유의하세요
- 재시도 메커니즘을 구현하세요(HTTP 상태 코드 기준)
- 지수 백오프를 사용하세요
-
토큰 관리:
- 토큰 사용량을 모니터링하세요(
usage읽기) - 프롬프트 길이를 최적화하세요
- 적절한
max_tokens값을 사용하세요 - thinking 활성화 시
output_tokens에 thinking이 이미 포함됩니다. 중복 과금하지 마세요
- 토큰 사용량을 모니터링하세요(
-
모델 선택:
- Opus: 복잡한 작업, 깊은 사고 필요
- Sonnet: 균형 잡힌 성능과 비용
- Haiku: 빠른 응답, 간단한 작업
-
콘텐츠 파싱:
content를 순회해type == "text"를 가져오세요.content[0].text를 고정으로 쓰지 마세요- 모델이 Markdown 코드 블록으로 JSON을 감싸 반환하면 모델 출력이며 API 래퍼가 아닙니다(아래 FAQ 참고)
-
콘텐츠 필터링:
- 사용자 입력을 검증하세요
- 민감한 정보를 필터링하세요
- 콘텐츠 조정을 구현하세요
FAQ
응답 content의 text가 ```json ... ``` 코드 블록인데, 어떻게 제거하나요?
API 구조 문제가 아닙니다. text 필드에는 모델이 생성한 원본 내용이 들어갑니다. 모델이 JSON을 원한다고 판단하면 Markdown 코드 블록으로 감쌉니다. API는 모델 출력을 바꾸지 않으며, 바꿔서도 안 됩니다.
깨끗한 구조화 데이터를 얻는 올바른 방법은 세 가지입니다(권장 순):
- tools로 구조화 출력을 강제——가장 안정적이며,
input필드가 바로 파싱된 객체입니다:
{
"tools": [{
"name": "emit_result",
"input_schema": {
"type": "object",
"properties": { "answer": { "type": "string" } }
}
}],
"tool_choice": { "type": "tool", "name": "emit_result" }
}
- assistant 메시지를 prefill하여 모델이
{부터 이어 쓰게 하기:
{
"messages": [
{ "role": "user", "content": "..." },
{ "role": "assistant", "content": "{" }
]
}
- system prompt에서 「JSON만 출력하고 Markdown 코드 블록을 붙이지 말 것」을 명시하기.
⌘I