Tips API
v1Read Infojara's daily tips in your own app or website. The API is read-only, returns JSON and needs an API key issued by us.
Quick start
curl https://www.dev.infojara.com.ng/api/v1/tips/today \ -H "Authorization: Bearer YOUR_API_KEY"
Base URL and authentication
Base URL: https://www.dev.infojara.com.ng/api/v1
Send your key in one of two headers. Never put it in a web page or app that other people can read; call the API from your server.
Authorization: Bearer YOUR_API_KEY X-API-Key: YOUR_API_KEY
Endpoints
| Request | What it returns |
|---|---|
GET /tips/today | Tips published today. Optional: access, category, limit |
GET /tips | Published tips, newest first, paginated. Optional: date, from, to (YYYY-MM-DD), category, access, q, page, per_page (max 100) |
GET /tips/{id} | One tip |
GET /tips/{id}/image | The tip's picture (PNG or JPEG), when one exists |
GET /categories | Categories with their number of published tips |
GET /me | Your key's access, limits and usage |
GET /webhooks | Your registered webhooks |
POST /webhooks | Register a webhook: JSON body {"url": "https://..."}. The signing secret is returned once. |
POST /webhooks/{id}/delete | Remove one of your webhooks |
Download the OpenAPI description (JSON). Import it into Postman, Insomnia or a code generator.
Add ?pretty=1 to any request for readable JSON. access is free, vip or all; keys without VIP access only receive free tips.
Example response
{
"data": [
{
"id": 42,
"title": "Turn on two-factor authentication",
"summary": "A stolen password alone should never unlock your accounts.",
"steps": [
{ "title": "Open security settings", "text": "Go to Settings or Security in your account." }
],
"benefits": ["Stops stolen password logins"],
"pro_tip": "Start with your email account.",
"category": { "slug": "cybersecurity", "name": "Cybersecurity" },
"access": "free",
"published_on": "2026-10-14",
"url": "https://www.dev.infojara.com.ng/tip/42",
"image_url": "https://www.dev.infojara.com.ng/api/v1/tips/42/image"
}
],
"meta": { "date": "2026-10-14", "timezone": "Africa/Lagos", "count": 1, "generated_at": "2026-10-14T08:00:00+01:00" }
}
Code examples
// PHP
$ch = curl_init('https://www.dev.infojara.com.ng/api/v1/tips/today');
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $apiKey]]);
$tips = json_decode(curl_exec($ch), true)['data'];
// JavaScript (Node 18+, server side)
const res = await fetch('https://www.dev.infojara.com.ng/api/v1/tips/today', { headers: { Authorization: `Bearer ${process.env.TIPS_API_KEY}` } });
const { data } = await res.json();
# Python
import requests
tips = requests.get('https://www.dev.infojara.com.ng/api/v1/tips/today', headers={'Authorization': f'Bearer {key}'}).json()['data']
Webhooks (get tips pushed to you)
Instead of asking every day, register an HTTPS address and we will POST the new tips to it as soon as they are published. Keys without VIP access only receive free tips.
POST https://your-server.example.com/hooks/tips
Content-Type: application/json
X-Webhook-Event: tips.published
X-Webhook-Id: 1042
X-Webhook-Timestamp: 1760430000
X-Webhook-Signature: sha256=3f1c...
{ "event": "tips.published", "created_at": "2026-10-14T08:00:00+01:00", "data": { "tips": [ { "id": 42, "title": "...", ... } ] } }
Answer with any 2xx status within 8 seconds. Other answers are retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours; after that the delivery is dropped, and a webhook that fails 20 times in a row is switched off. Always check the signature: it is the HMAC-SHA256 of timestamp + "." + raw body using your secret.
// PHP
$raw = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'];
$sig = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$ok = hash_equals('sha256=' . hash_hmac('sha256', $ts . '.' . $raw, $secret), $sig) && abs(time() - $ts) < 300;
// Node.js
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(ts + '.' + rawBody).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
Limits
Each key has an hourly and a daily request limit (the default is 600 per hour and 5,000 per day; yours is shown by /me). Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (a Unix time). When you go over, you get status 429 and a Retry-After header. Tips change once a day, so cache responses for a few minutes.
Errors
Errors use the same shape with an HTTP status: { "error": { "code": "invalid_key", "message": "..." } }
| Status | code | Meaning |
|---|---|---|
| 401 | missing_key, invalid_key | No key, or the key is wrong |
| 403 | key_revoked, key_expired, forbidden | The key was switched off, has expired, or cannot read VIP tips |
| 404 | not_found, no_image | No such tip, or it has no picture |
| 422 | invalid_parameter | A parameter has the wrong format |
| 429 | rate_limited, quota_exceeded | Too many requests; wait and retry |
| 503 | api_disabled | The API is temporarily switched off |
Using the tips
Please credit Infojara and link back to the tip's url. Do not resell the content or present VIP tips to people who have not subscribed. We can revoke a key at any time.