1. Prérequis — Compte Anthropic et modèles 2026
Obtenir une clé API
- Créez un compte sur console.anthropic.com
- Dans API Keys, cliquez sur Create API Key
- Copiez la clé — elle n'est affichée qu'une seule fois
- Stockez-la dans une variable d'environnement :
ANTHROPIC_API_KEY
.env à votre .gitignore dès le départ.Choisir le bon modèle en 2026
La famille Claude 4 est la plus récente. Voici comment choisir :
| Modèle | ID API | Cas d'usage | Vitesse |
|---|---|---|---|
| Claude Haiku 4.5 | claude-haiku-4-5-20251001 |
Classification, résumés courts, réponses rapides | ⚡⚡⚡ |
| Claude Sonnet 4.6 ★ | claude-sonnet-4-6 |
Chat, génération, analyse — recommandé pour débuter | ⚡⚡ |
| Claude Opus 4.8 | claude-opus-4-8 |
Raisonnement complexe, code avancé, recherche | ⚡ |
claude-sonnet-4-6. Passez à claude-opus-4-8 uniquement si vos tâches l'exigent vraiment.2. Backend Python avec Flask
Installation
pip install anthropic flask flask-cors python-dotenv
Fichier .env
ANTHROPIC_API_KEY=sk-ant-votre_cle_api_ici
Application Flask — app.py
from flask import Flask, request, jsonify
from flask_cors import CORS
from anthropic import Anthropic, RateLimitError, APIConnectionError
import os
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
CORS(app) # Autorise les requêtes depuis votre frontend
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
@app.route("/api/ask-claude", methods=["POST"])
def ask_claude():
data = request.get_json()
prompt = data.get("prompt", "").strip()
if not prompt:
return jsonify({"error": "Le champ 'prompt' est requis."}), 400
if len(prompt) > 10_000:
return jsonify({"error": "Prompt trop long (max 10 000 car.)."}), 400
try:
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="Tu es un assistant intelligent. Réponds en français.",
messages=[{"role": "user", "content": prompt}]
)
return jsonify({
"response": response.content[0].text,
"tokens_used": response.usage.input_tokens + response.usage.output_tokens
})
except RateLimitError:
return jsonify({"error": "Limite d'appels atteinte. Réessayez."}), 429
except APIConnectionError:
return jsonify({"error": "Impossible de contacter l'API."}), 503
except Exception as e:
return jsonify({"error": str(e)}), 500
if __name__ == "__main__":
app.run(debug=True, port=5000)
Test avec cURL
python app.py
# Dans un autre terminal :
curl -X POST http://localhost:5000/api/ask-claude \
-H "Content-Type: application/json" \
-d '{"prompt": "Explique l'\''IA en 3 points."}'
3. Backend Node.js avec Express
Installation
npm install express @anthropic-ai/sdk dotenv cors
Serveur Express — server.js
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const Anthropic = require('@anthropic-ai/sdk');
const app = express();
app.use(express.json());
app.use(cors());
const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
app.post('/api/ask-claude', async (req, res) => {
const { prompt } = req.body;
if (!prompt?.trim()) {
return res.status(400).json({ error: "Le champ 'prompt' est requis." });
}
try {
const message = await anthropic.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: 'Tu es un assistant intelligent. Réponds en français.',
messages: [{ role: 'user', content: prompt }],
});
res.json({
response: message.content[0].text,
tokens_used: message.usage.input_tokens + message.usage.output_tokens,
});
} catch (err) {
const status = err.status || 500;
res.status(status).json({ error: err.message });
}
});
app.listen(3000, () => console.log('API démarrée sur http://localhost:3000'));
4. Frontend React
Création et installation
npx create-react-app claude-chat && cd claude-chat
npm install axios
Composant de chat — src/components/ClaudeChat.jsx
import { useState, useRef, useEffect } from 'react';
import axios from 'axios';
const API = process.env.REACT_APP_API_URL || 'http://localhost:5000';
export default function ClaudeChat() {
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
const endRef = useRef(null);
useEffect(() => endRef.current?.scrollIntoView({ behavior: 'smooth' }), [messages]);
const send = async (e) => {
e.preventDefault();
const prompt = input.trim();
if (!prompt || loading) return;
setMessages(m => [...m, { role: 'user', text: prompt }]);
setInput('');
setLoading(true);
try {
const { data } = await axios.post(`${API}/api/ask-claude`, { prompt });
setMessages(m => [...m, { role: 'claude', text: data.response }]);
} catch (err) {
setMessages(m => [...m, { role: 'error', text: err.message }]);
} finally {
setLoading(false);
}
};
return (
<div className="chat">
<div className="messages">
{messages.map((m, i) => (
<p key={i} className={m.role}>{m.text}</p>
))}
{loading && <p className="claude typing">Claude réfléchit…</p>}
<div ref={endRef} />
</div>
<form onSubmit={send}>
<input value={input} onChange={e => setInput(e.target.value)}
placeholder="Votre question…" disabled={loading} />
<button type="submit" disabled={loading || !input.trim()}>Envoyer</button>
</form>
</div>
);
}
.env à la racine React avec REACT_APP_API_URL=http://localhost:5000 en dev et votre URL de production pour le déploiement.5. Frontend Vue.js
npm create vue@latest claude-vue && cd claude-vue && npm install axios && npm install
Composant — src/components/ClaudeChat.vue
<script setup>
import { ref, nextTick } from 'vue';
import axios from 'axios';
const messages = ref([]);
const input = ref('');
const loading = ref(false);
const endRef = ref(null);
const scrollDown = async () => { await nextTick(); endRef.value?.scrollIntoView({ behavior:'smooth' }); };
const send = async () => {
const prompt = input.value.trim();
if (!prompt || loading.value) return;
messages.value.push({ role: 'user', text: prompt });
input.value = '';
loading.value = true;
await scrollDown();
try {
const { data } = await axios.post(
import.meta.env.VITE_API_URL + '/api/ask-claude', { prompt }
);
messages.value.push({ role: 'claude', text: data.response });
} catch (err) {
messages.value.push({ role: 'error', text: err.message });
} finally {
loading.value = false;
await scrollDown();
}
};
</script>
<template>
<div class="chat">
<div class="messages">
<p v-for="(m,i) in messages" :key="i" :class="m.role">{{ m.text }}</p>
<p v-if="loading" class="claude typing">Claude réfléchit…</p>
<div ref="endRef" />
</div>
<form @submit.prevent="send">
<input v-model="input" placeholder="Votre question…" :disabled="loading" />
<button type="submit" :disabled="loading || !input.trim()">Envoyer</button>
</form>
</div>
</template>
6. Streaming — réponses en temps réel
Le streaming affiche la réponse mot par mot, comme sur claude.ai, au lieu d'attendre la réponse complète. Indispensable pour une bonne UX sur les réponses longues.
Endpoint Flask (SSE)
from flask import Response, stream_with_context
import json
@app.route("/api/stream-claude", methods=["POST"])
def stream_claude():
data = request.get_json()
prompt = data.get("prompt", "").strip()
if not prompt:
return {"error": "Prompt requis"}, 400
def generate():
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}]
) as stream:
for text in stream.text_stream:
yield f"data: {json.dumps({'text': text})}\n\n"
yield "data: [DONE]\n\n"
return Response(
stream_with_context(generate()),
mimetype="text/event-stream",
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}
)
Consommation côté client (JavaScript)
const streamChat = async (prompt) => {
let buffer = '';
setLoading(true);
const response = await fetch('/api/stream-claude', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt })
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(l => l.startsWith('data: '));
for (const line of lines) {
const payload = line.slice(6);
if (payload === '[DONE]') { setLoading(false); return; }
const { text } = JSON.parse(payload);
buffer += text;
setResponse(buffer); // Mise à jour progressive de l'UI
}
}
};
7. Bonnes pratiques et optimisation des coûts
Sécurité — checklist
- ✅ Clé API uniquement dans les variables d'environnement serveur
- ✅
.envdans.gitignore - ✅ Validation et limite de longueur des prompts entrants
- ✅ Rate limiting par IP (ex:
flask-limiterouexpress-rate-limit) - ✅ HTTPS obligatoire en production
- ✅ CORS restreint à votre domaine frontend uniquement
Prompt Caching — jusqu'à 90 % d'économie
Si votre system prompt est long et identique d'un appel à l'autre (contexte métier, instructions fixes), activez le cache Anthropic :
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system=[{
"type": "text",
"text": "Vous êtes expert en droit fiscal français. [Contexte de 2000 tokens ici]",
"cache_control": {"type": "ephemeral"} # Ce bloc sera mis en cache
}],
messages=[{"role": "user", "content": prompt}]
)
# Les appels suivants avec le même system prompt économisent ~90% sur ces tokens
max_tokens au besoin réel (256 pour un résumé court, 2048 pour un article). Utilisez Claude Haiku pour les tâches de classification simples et Sonnet pour le reste.8. Déploiement
- Render — gratuit, simple, recommandé
- Railway — très rapide à déployer
- Heroku — solution historique
- Vercel — optimal pour React/Next.js
- Netlify — excellent pour Vue/statique
- GitHub Pages — pour les sites statiques
ANTHROPIC_API_KEY dans le dashboard de votre plateforme (Render → Environment, Railway → Variables). Ne déployez jamais de fichier .env.Checklist avant mise en ligne
- ☐
ANTHROPIC_API_KEYconfigurée en variable d'environnement - ☐
.envdans.gitignore✓ - ☐ CORS restreint au domaine de production
- ☐ HTTPS activé (automatique sur Vercel, Netlify, Render)
- ☐ Rate limiting activé
- ☐ Logs d'erreurs configurés (Sentry, Logtail…)
9. FAQ
Peut-on appeler l'API Claude depuis le navigateur ?
Non. Appeler l'API directement depuis le frontend exposerait votre clé dans le code source (visible via "Inspecter l'élément"). Utilisez toujours un backend pour faire le relais.
Quel modèle Claude choisir pour une PME en 2026 ?
Commencez par claude-sonnet-4-6 pour le meilleur équilibre. Pour les tâches simples (classification, réponses courtes), passez à claude-haiku-4-5-20251001 pour réduire les coûts. Réservez claude-opus-4-8 aux analyses complexes.
Comment réduire les coûts API ?
Activez le Prompt Caching sur les system prompts fixes (économie jusqu'à 90 %). Limitez max_tokens au besoin réel. Mettez en cache (Redis) les réponses aux questions fréquentes. Utilisez Haiku pour les tâches simples.
Comment afficher la réponse en temps réel ?
Utilisez le streaming : côté serveur avec client.messages.stream() et côté client avec la Fetch API (ReadableStream) ou EventSource. Voir section 6 ci-dessus.
Peut-on envoyer des images à Claude ?
Oui, tous les modèles Claude 4 supportent la vision. Encodez l'image en base64 et passez-la dans le tableau content du message avec type: "image". Voir la documentation vision.