Get VIP

Tips API

v1

Read 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

RequestWhat it returns
GET /tips/todayTips published today. Optional: access, category, limit
GET /tipsPublished 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}/imageThe tip's picture (PNG or JPEG), when one exists
GET /categoriesCategories with their number of published tips
GET /meYour key's access, limits and usage
GET /webhooksYour registered webhooks
POST /webhooksRegister a webhook: JSON body {"url": "https://..."}. The signing secret is returned once.
POST /webhooks/{id}/deleteRemove 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": "..." } }

StatuscodeMeaning
401missing_key, invalid_keyNo key, or the key is wrong
403key_revoked, key_expired, forbiddenThe key was switched off, has expired, or cannot read VIP tips
404not_found, no_imageNo such tip, or it has no picture
422invalid_parameterA parameter has the wrong format
429rate_limited, quota_exceededToo many requests; wait and retry
503api_disabledThe 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.

Request an API key