Developer mode API v1
Build with the AskVenda API
Search the askvenda directory from your own app, site, or script. Read-only, versioned, rate-limited, keyed. Base URL:
https://askvenda.com.ng/api/v1
Test on a staging copy before you switch live traffic.
1. Get an API key
- Ask for access through the Contact page or on Telegram with your app name and contact email.
- We create your developer profile and issue a key starting with
askv_. - Copy it once. Only the hash is stored; a lost key is revoked and reissued, never recovered.
- Send it on every request as the
X-Api-Keyheader. Never put keys in URLs, they leak into logs.
2. Rules of the road
- 60 requests per minute per key by default (raise on request). Watch
X-RateLimit-Remaining; HTTP 429 means slow down. - Masked contacts only. The API returns masked phones, never emails or identity documents. Send users to the vendor profile or Telegram to make contact.
- Approved vendors only. Pending, rejected, and hidden listings never appear.
- Versioned. v1 only grows additively. Breaking changes ship as v2 with 6 months notice.
Examples in your language:
3. Search vendors
GET /vendors?q=&category=&area=&page=&per_page= (per_page max 50, default 12)
curl -H "X-Api-Key: askv_YOUR_KEY" \ "https://askvenda.com.ng/api/v1/vendors?q=tailor&per_page=3"
const KEY = process.env.ASKVENDA_KEY; // never commit keys
const res = await fetch(
'https://askvenda.com.ng/api/v1/vendors?q=tailor&per_page=3',
{ headers: { 'X-Api-Key': KEY, 'Accept': 'application/json' } }
);
if (!res.ok) {
throw new Error('HTTP ' + res.status); // 401 bad key, 429 slow down
}
const { data, meta } = await res.json();
console.log(`page ${meta.page}/${meta.last_page}, ${meta.total} total`);
data.forEach((v) => console.log(v.business_name, '-', v.masked_phone));
$key = getenv('ASKVENDA_KEY'); // never commit keys
$ch = curl_init('https://askvenda.com.ng/api/v1/vendors?q=tailor&per_page=3');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => ['X-Api-Key: ' . $key, 'Accept: application/json'],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException('API HTTP ' . $status); // 401 bad key, 429 slow down
}
$payload = json_decode((string) $body, true);
foreach ($payload['data'] as $v) {
echo $v['business_name'] . ' - ' . $v['masked_phone'] . PHP_EOL;
}
import os
import requests
KEY = os.environ['ASKVENDA_KEY'] # never commit keys
resp = requests.get(
'https://askvenda.com.ng/api/v1/vendors',
params={'q': 'tailor', 'per_page': 3},
headers={'X-Api-Key': KEY, 'Accept': 'application/json'},
timeout=15,
)
resp.raise_for_status() # 401 bad key, 429 slow down
payload = resp.json()
print(f"page {payload['meta']['page']}/{payload['meta']['last_page']}")
for v in payload['data']:
print(v['business_name'], '-', v['masked_phone'])
import { useEffect, useState } from 'react';
const API = 'https://askvenda.com.ng/api/v1';
const KEY = process.env.REACT_APP_ASKVENDA_KEY; // never commit keys
export function VendorList({ query }) {
const [vendors, setVendors] = useState([]);
const [error, setError] = useState('');
useEffect(() => {
fetch(`${API}/vendors?q=${encodeURIComponent(query)}&per_page=6`, {
headers: { 'X-Api-Key': KEY, 'Accept': 'application/json' },
})
.then((res) => {
if (!res.ok) { throw new Error('HTTP ' + res.status); }
return res.json();
})
.then((json) => setVendors(json.data || []))
.catch((err) => setError(String(err.message || err)));
}, [query]);
if (error) { return <p>Could not load vendors: {error}</p>; }
return (
<ul>
{vendors.map((v) => (
<li key={v.id}>
{v.business_name} - {v.area ? v.area.name : ''} ({v.rating_avg})
</li>
))}
</ul>
);
}
4. Vendor detail
GET /vendors/{slug} with signed photo URLs (valid 30 minutes, refresh as needed).
curl -H "X-Api-Key: askv_YOUR_KEY" \ "https://askvenda.com.ng/api/v1/vendors/adebayo-stitches-tanke"
const res = await fetch(
'https://askvenda.com.ng/api/v1/vendors/adebayo-stitches-tanke',
{ headers: { 'X-Api-Key': KEY, 'Accept': 'application/json' } }
);
if (res.status === 404) {
console.log('Unknown slug or not approved yet.');
} else if (!res.ok) {
throw new Error('HTTP ' + res.status);
}
const { data } = await res.json();
console.log(data.business_name, data.category, data.photos.length + ' photos');
$slug = 'adebayo-stitches-tanke';
$ch = curl_init('https://askvenda.com.ng/api/v1/vendors/' . $slug);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => ['X-Api-Key: ' . $key, 'Accept: application/json'],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status === 404) {
echo "Unknown slug or not approved yet.\n";
} else {
$vendor = json_decode((string) $body, true)['data'];
echo $vendor['business_name'] . ' - ' . count($vendor['photos']) . " photos\n";
}
resp = requests.get(
'https://askvenda.com.ng/api/v1/vendors/adebayo-stitches-tanke',
headers={'X-Api-Key': KEY, 'Accept': 'application/json'},
timeout=15,
)
if resp.status_code == 404:
print('Unknown slug or not approved yet.')
else:
resp.raise_for_status()
vendor = resp.json()['data']
print(vendor['business_name'], '-', len(vendor['photos']), 'photos')
export function VendorCard({ slug }) {
const [vendor, setVendor] = useState(null);
useEffect(() => {
fetch(`${API}/vendors/${slug}`, {
headers: { 'X-Api-Key': KEY, 'Accept': 'application/json' },
})
.then((res) => (res.ok ? res.json() : null))
.then((json) => setVendor(json ? json.data : null))
.catch(() => setVendor(null));
}, [slug]);
if (!vendor) { return <p>Loading vendor...</p>; }
return (
<article>
<h3>{vendor.business_name}</h3>
<p>{vendor.masked_phone} - {vendor.rating_avg} ({vendor.rating_count})</p>
<a href={vendor.profile_url}>View on AskVenda</a>
</article>
);
}
Endpoint reference
| Method | Path | Use |
|---|---|---|
| GET | /categories | Active categories with live vendor counts |
| GET | /areas | Active areas with LGA |
| GET | /vendors | Ranked search (q, category, area, page, per_page) |
| GET | /vendors/{slug} | One approved vendor with photos |
Errors
| HTTP | Code | Meaning |
|---|---|---|
| 401 | unauthorized | Missing, unknown, or revoked key |
| 403 | forbidden | Developer deactivated or bad photo signature |
| 404 | not_found | Unknown slug or unapproved vendor |
| 422 | validation / unknown_category / unknown_area | Bad parameter; message names the fix |
| 429 | rate_limited | Over quota; respect Retry-After |
Ready to build?
Tell us your app name and contact email and we issue your key, usually within 24 hours on working days. Keys start at 60 requests per minute; higher quotas for launch partners.
Request a key through the Contact page. Abuse (scraping, reselling data, spamming vendors) revokes keys without warning.
API v1, additive changes only. Last updated Nov 2026.