Overview
Fikra API is an OpenAI-compatible AI inference API. You send chat-completions requests to POST https://api.fikraapi.co.ke/v1/chat/completions and authenticate with Authorization: Bearer <Fikra API key>. Responses follow the OpenAI chat-completions shape, and streaming is supported.
Sometimes the upstream model provider is momentarily busy and the endpoint answers with HTTP 503. The correct handling is a bounded retry with exponential backoff and jitter, applied only to 503. This page shows how to do that with the Python OpenAI SDK pointed at the Fikra API base URL.
Prerequisites
- A Fikra API key, exported as the environment variable
FIKRA_API_KEY. Keep the secret server-side; do not paste keys into client-side code. - Python with the
openaiSDK installed. - Your client configured with
base_url="https://api.fikraapi.co.ke/v1". - Awareness of your rate limit: 30 requests/min while unverified, 100 requests/min once trusted. Backoff and jitter help you stay inside it.
Step-by-step
1. Create the client from the environment variable.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.fikraapi.co.ke/v1",
api_key=os.environ["FIKRA_API_KEY"],
)
2. Wrap the chat call in a bounded retry loop that only reacts to 503.
import os
import random
import time
from openai import OpenAI, APIStatusError
client = OpenAI(
base_url="https://api.fikraapi.co.ke/v1",
api_key=os.environ["FIKRA_API_KEY"],
)
def chat_with_retry(messages, model="deepseek-v4-flash-0731", max_attempts=5):
for attempt in range(1, max_attempts + 1):
try:
return client.chat.completions.create(
model=model,
messages=messages,
)
except APIStatusError as err:
if err.status_code != 503 or attempt == max_attempts:
raise
base = min(2 ** (attempt - 1), 30) # 1, 2, 4, 8, 16 ... capped at 30
delay = base + random.uniform(0, 0.5) # jitter avoids lockstep retries
time.sleep(delay)
3. Keep the retry scope narrow. Retry 503 only. A 401 will not fix itself, and a 400 usually means the model name is not supported. Let those surface to your caller immediately.
4. Separate retries from your rate budget. Each retry is another request against your limit (30 requests/min unverified, 100 requests/min trusted), so keep max_attempts small and cap the backoff as shown.
5. Choose a model from the available list. Examples: deepseek-v4-flash-0731, deepseek-v4.1-flash, deepseek-v4.1-flash-1017, fikra-auto, fikra-auto-pro, fikra-code-35b.
6. Log the attempt number and the delay so you can see how often 503 occurs in your own traffic.
Verify it works
Run a chat request through the helper and confirm the response has the usual OpenAI-style shape:
resp = chat_with_retry([{"role": "user", "content": "Reply with the word ready."}])
print(resp.choices[0].message.content)
To confirm the retry path without waiting for a real outage, temporarily raise inside the except block when err.status_code == 503 and log attempt and delay; you should see attempts increase, delays grow, and the loop stop at max_attempts instead of spinning forever.
Costs
Pricing starts at 0.09 USD per 1M input tokens and 0.15 USD per 1M output tokens, and is billed per model:
| Model | Input (USD / 1M tokens) | Output (USD / 1M tokens) |
|---|---|---|
| deepseek-v4-flash-0731 | 0.09 | 0.15 |
| deepseek-v4.1-flash | 0.25 | 0.80 |
| deepseek-v4.1-flash-1017 | 0.30 | 0.85 |
| fikra-auto | 0.40 | 0.40 |
| fikra-auto-pro | 6.00 | 12.00 |
| fikra-code-35b | 1.00 | 1.00 |
Payment runs through a token-credit wallet, with M-Pesa and card top-ups via Paystack, and x402 USDC on Base for agents. Retries do send additional requests; how failed 503 attempts are billed is not stated here, so check the pricing page before sizing retry budgets.
Common errors
- 401 Unauthorized , the key is bad or inactive. Do not retry; check the value in
FIKRA_API_KEY. - 400 Bad Request , often an unsupported model. Use one of the model names listed above and do not retry.
- 429 Too Many Requests , you have exceeded your rate limit (30 requests/min unverified, 100 requests/min trusted). Slow down rather than retrying immediately.
- 503 Service Unavailable , upstream busy. Retry with exponential backoff and jitter, bounded by a small
max_attempts, and let the final failure propagate.