Claude API — Get Started
Panggilan API Claude pertama: setup kredensial, struktur request, dan cara membaca respons dengan benar.
Intisari
- Semuanya lewat satu endpoint:
POST /v1/messages. Tool use dan structured output adalah fitur di endpoint yang sama. - API-nya stateless — riwayat percakapan kamu yang kirim ulang tiap kali, lewat array
messages. response.contentadalah list of block, bukan string. Selalu cek.type.- Cek
response.stop_reasonsebelum membaca isi — bisaend_turn,max_tokens,tool_use, ataurefusal. response.usageberisi jumlah token masuk dan keluar — dasar semua perhitungan biaya.
Setup
uv add anthropic
export ANTHROPIC_API_KEY=sk-ant-...
import anthropic
client = anthropic.Anthropic() # membaca ANTHROPIC_API_KEY dari environment
Jangan hardcode API key. Baca dari environment (lewat pydantic-settings
seperti di Fase 2). Key yang ter-commit ke git harus dianggap bocor dan wajib dicabut,
meskipun commit-nya sudah dihapus.
Panggilan pertama
response = client.messages.create(
model="claude-opus-5",
max_tokens=16000,
system="Kamu asisten yang menjawab ringkas dalam bahasa Indonesia.",
messages=[{"role": "user", "content": "Jelaskan apa itu RAG dalam 3 kalimat."}],
)
for block in response.content:
if block.type == "text":
print(block.text)
Anatomi request
| Parameter | Wajib | Keterangan |
|---|---|---|
model | ✅ | ID model, misal claude-opus-5 |
max_tokens | ✅ | Batas keras token keluar. Bukan target, tapi plafon. |
messages | ✅ | Riwayat percakapan, berselang-seling user/assistant |
system | — | Instruksi tingkat sistem. Parameter terpisah, bukan anggota messages. |
tools | — | Daftar tool yang boleh dipanggil model |
thinking | — | {"type": "adaptive"} — model menentukan sendiri kedalaman berpikirnya |
output_config | — | {"effort": "high"} dan/atau format keluaran terstruktur |
stream | — | Streaming; lebih enak lewat client.messages.stream() |
Empat hal yang harus benar-benar kamu internalisasi
1. API-nya stateless
messages = []
def kirim(teks: str) -> str:
messages.append({"role": "user", "content": teks})
r = client.messages.create(
model="claude-opus-5", max_tokens=16000, messages=messages,
)
jawaban = next(b.text for b in r.content if b.type == "text")
messages.append({"role": "assistant", "content": jawaban})
return jawaban
Tidak ada session di sisi server. Setiap request mengirim ulang seluruh percakapan. Konsekuensinya: biaya input tumbuh seiring panjangnya percakapan, dan kamulah yang bertanggung jawab memangkas riwayat sebelum menabrak batas context window. Ini juga alasan prompt caching begitu berdampak.
2. content adalah list of block
for block in response.content:
if block.type == "text":
print(block.text)
elif block.type == "thinking":
print("[berpikir]", block.thinking)
elif block.type == "tool_use":
print("minta tool:", block.name, block.input)
response.content[0].text akan pecah begitu kamu menyalakan thinking atau
tool use — blok pertamanya bukan teks lagi. Biasakan menelusuri list dan memeriksa
.type sejak awal.
3. stop_reason — periksa dulu
| Nilai | Artinya | Yang harus kamu lakukan |
|---|---|---|
end_turn | Selesai wajar | Baca teksnya |
max_tokens | Kena plafon | Naikkan max_tokens atau pakai streaming |
tool_use | Model minta tool dijalankan | Jalankan, kirim hasilnya kembali |
refusal | Ditolak oleh pengaman | Cek stop_details.category; jangan diulang begitu saja |
pause_turn | Tool sisi server berhenti sementara | Kirim ulang untuk melanjutkan |
if response.stop_reason == "refusal":
tangani_penolakan(response.stop_details)
elif response.stop_reason == "max_tokens":
logger.warning("respons terpotong")
else:
tampilkan(response.content)
4. usage — dasar perhitungan biaya
u = response.usage
u.input_tokens # token masuk yang dibayar penuh
u.output_tokens # token keluar
u.cache_read_input_tokens # dari cache — jauh lebih murah
u.cache_creation_input_tokens # ditulis ke cache
HARGA_IN, HARGA_OUT = 5.0, 25.0 # USD per juta token (Claude Opus 5)
biaya = (u.input_tokens * HARGA_IN + u.output_tokens * HARGA_OUT) / 1_000_000
print(f"${biaya:.6f}")
Adaptive thinking dan effort
response = client.messages.create(
model="claude-opus-5",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
output_config={"effort": "high"}, # low | medium | high | xhigh | max
messages=[{"role": "user", "content": "..."}],
)
effort | Untuk |
|---|---|
low | Klasifikasi, ekstraksi sederhana, tugas yang sensitif latensi |
medium | Beban kerja rutin yang perlu hemat token |
high | Default — keseimbangan yang baik untuk sebagian besar tugas |
xhigh | Coding dan pekerjaan agentic — biasanya pilihan terbaik di sana |
max | Saat kebenaran lebih penting daripada biaya |
Pada Claude Opus 5, thinking aktif secara default — menghilangkan parameter
thinking tetap membuat model berpikir. Karena max_tokens membatasi
thinking + teks jawaban sekaligus, sediakan ruang yang cukup atau jawabanmu bisa
terpotong di tengah.
Menangani error
import anthropic
try:
r = client.messages.create(...)
except anthropic.RateLimitError as e:
tunggu = int(e.response.headers.get("retry-after", "60"))
except anthropic.APIStatusError as e:
if e.status_code >= 500:
... # layak diulang
else:
raise # request-mu yang salah
except anthropic.APIConnectionError:
... # masalah jaringan
SDK sudah mengulang otomatis untuk 408, 409, 429, dan 5xx — default 2 kali. Ubah dengan anthropic.Anthropic(max_retries=5).
Versi async
client = anthropic.AsyncAnthropic()
async def tanya(prompt: str) -> str:
r = await client.messages.create(
model="claude-opus-5", max_tokens=16000,
messages=[{"role": "user", "content": prompt}],
)
return next(b.text for b in r.content if b.type == "text")
Inilah gunanya Fase 3 — asyncio.gather atas puluhan panggilan seperti ini.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.