Web Applications
Integrate Addis AI into Next.js, React, PHP, and standard web apps.
You can build powerful web applications from customer support chatbots to voice-enabled educational tools, using standard HTTP requests.
SDKs Coming Soon
We are currently finalizing our official JavaScript/TypeScript SDK.
In the meantime, this guide demonstrates how to integrate using standard fetch and backend proxies to ensure security and performance.
Security: The Golden Rule
Do NOT use your sk_ key directly in client-side code (React Components, HTML scripts). Malicious users can steal your key and drain your credits.
Backend Integration (The Proxy)
Your frontend (React, Vue, Blade) should call your own backend, which then calls Addis AI. This keeps your secrets on the server.
Create a file at app/api/chat/route.ts.
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
try {
const { message } = await req.json();
const response = await fetch("https://api.addisassistant.com/api/v1/chat_generate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.ADDIS_AI_API_KEY!, // Key stored in .env.local
},
body: JSON.stringify({
model: "Addis-፩-አሌፍ",
prompt: message,
target_language: "am",
generation_config: { temperature: 0.7 }
}),
});
// Forward the exact status code from Addis AI
if (!response.ok) {
const errorData = await response.json();
return NextResponse.json(errorData, { status: response.status });
}
const data = await response.json();
return NextResponse.json(data);
} catch (error) {
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
}
}Standard Express.js proxy.
const express = require('express');
const app = express();
app.use(express.json());
const API_KEY = process.env.ADDIS_AI_KEY;
app.post('/api/proxy', async (req, res) => {
const { prompt } = req.body;
try {
const apiRes = await fetch("https://api.addisassistant.com/api/v1/chat_generate", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": API_KEY
},
body: JSON.stringify({
prompt: prompt,
target_language: "am"
})
});
const data = await apiRes.json();
res.status(apiRes.status).json(data);
} catch (error) {
res.status(500).json({ error: "Proxy Connection Failed" });
}
});Using Laravel's HTTP Client (Guzzle wrapper).
// In routes/api.php or a Controller
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Request;
Route::post('/chat', function (Request $request) {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'X-API-Key' => env('ADDIS_AI_KEY'),
])->post('https://api.addisassistant.com/api/v1/chat_generate', [
'prompt' => $request->input('message'),
'target_language' => 'am',
'model' => 'Addis-፩-አሌፍ',
'generation_config' => [
'temperature' => 0.7
]
]);
if ($response->failed()) {
return response()->json($response->json(), $response->status());
}
return $response->json();
});Frontend Integration
Now that your backend is secure, call it from your frontend.
"use client";
import { useState } from 'react';
export default function ChatBox() {
const [input, setInput] = useState('');
const [response, setResponse] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const handleSend = async () => {
setLoading(true);
setError('');
try {
// Call YOUR internal API route
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: input }),
});
const data = await res.json();
if (!res.ok) {
throw new Error(data.error?.message || "Something went wrong");
}
setResponse(data.response_text);
} catch (err: any) {
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<div className="p-4 space-y-4 max-w-md mx-auto border rounded-lg">
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
className="w-full border p-2 rounded bg-background"
placeholder="Ask something in Amharic..."
/>
<button
onClick={handleSend}
disabled={loading}
className="bg-blue-600 text-white px-4 py-2 rounded disabled:opacity-50"
>
{loading ? 'Thinking...' : 'Send'}
</button>
{error && <div className="text-red-500 text-sm">{error}</div>}
{response && (
<div className="bg-muted p-4 rounded mt-4">
<strong>AI:</strong> {response}
</div>
)}
</div>
);
}<input type="text" id="prompt" placeholder="Type here..." />
<button id="sendBtn">Send</button>
<div id="result"></div>
<script>
const btn = document.getElementById('sendBtn');
const result = document.getElementById('result');
btn.addEventListener('click', async () => {
const text = document.getElementById('prompt').value;
result.innerText = "Loading...";
try {
// Call your PHP or Node backend
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: text })
});
const data = await res.json();
if (!res.ok) throw new Error(data.error?.message);
result.innerText = data.response_text;
} catch (err) {
result.innerText = "Error: " + err.message;
result.style.color = 'red';
}
});
</script>Handling Errors
When building web apps, you should expect and handle these common scenarios.
| Status Code | Meaning | User-Facing Action |
|---|---|---|
| 401 | Unauthorized | "Service configuration error. Please contact support." (Your API Key is wrong on the server). |
| 429 | Rate Limit | "System busy. Please try again in a moment." (Implement a retry button). |
| 500 | Server Error | "Something went wrong on our end." |
| 503 | Overloaded | "Addis AI is currently experiencing high traffic." |
JSON Error Response
If an error occurs, the API returns:
{
"status": "error",
"error": {
"code": "rate_limit_exceeded",
"message": "You have exceeded your quota."
}
}Best Practices
CORS Handling
The Addis AI API does not allow calls directly from browsers (to protect your key). You will get a CORS error if you try. Always use a backend.
Timeouts
Generating long text can take 5-10 seconds. Ensure your web server (Nginx/Apache) and frontend fetch client have a timeout of at least 30 seconds.