IPMeta API
Documentation
Real-time IP geolocation, ASN/ISP lookup, and proxy/VPN/threat intelligence — all behind a single REST API.
Authentication
Every request must include your API key as a Bearer token. Keys are prefixed ipm_live_ and scoped to your plan.
Authorization: Bearer ipm_live_<your_api_key>
curl "https://api.ip-meta.xyz/v1/ip-lookup?ip=8.8.8.8" \ -H "Authorization: Bearer ipm_live_your_key_here"
const res = await fetch(
'https://api.ip-meta.xyz/v1/ip-lookup?ip=8.8.8.8',
{ headers: { Authorization: 'Bearer ipm_live_your_key_here' } }
);
const data = await res.json();Plans & Rate Limits
Limits reset on a 30-day rolling period from subscription date, not calendar month.
| Plan | Lookups/mo | Proxy/VPN/Threat data | Bulk endpoint | Team seats |
|---|---|---|---|---|
| Free | 1,000 | ✕ | ✕ | 1 |
| Pro | 150,000 | ✓ | ✓ | 5 |
| Scale | Unlimited | ✓ | ✓ | 20 |
X-RateLimit-Limit: 150000 # monthly cap X-RateLimit-Remaining: 149987 # requests remaining X-RateLimit-Reset: 1717977600 # unix epoch reset time
Error Codes
| Status | Meaning | Common cause |
|---|---|---|
| 401 | Unauthorized | Missing, malformed, or revoked API key |
| 403 | Forbidden | Plan doesn't include this feature |
| 429 | Too Many Requests | Monthly quota exceeded — check X-RateLimit-Reset |
| 400 | Bad Request | Missing required parameters |
| 500 | Internal Error | Server-side issue — retry with exponential backoff |
| 503 | Service Unavailable | Database unreachable — retry shortly |
IP Lookup API
Resolve an IP address to geolocation, ASN/ISP, and proxy/VPN/threat signals in a single request.
Resolves an IP address to latitude, longitude, city, region, country, timezone, ASN/ISP, and proxy/VPN/threat signals. Pass ?ip=auto (default) to detect from the request IP, or supply any explicit IPv4/IPv6 address.
| Param | Type | Req | Description |
|---|---|---|---|
| ip | string | optional | IP to resolve. Pass auto (default) to detect from request, or an explicit IPv4/IPv6 address |
{
"ip": "8.8.8.8",
"ip_version": "v4",
"geo": {
"lat": 37.4056,
"lon": -122.0775,
"city": "Mountain View",
"region": "California",
"country": "US",
"timezone": "America/Los_Angeles",
"postal": "94043"
},
"network": {
"asn": "AS15169",
"isp": "Google LLC",
"is_mobile": false
},
"security": {
"is_proxy": false,
"is_vpn": false,
"is_tor": false,
"is_datacenter": true,
"threat_score": 2
}
}Resolves up to 100 IPs in a single call. Accepts a comma-separated list via query string (GET) or a JSON array in the body (POST). Each result has the same shape as /v1/ip-lookup.
| Param | Type | Req | Description |
|---|---|---|---|
| ips | string | required | Comma-separated IPv4/IPv6 addresses, max 100 |
curl "https://api.ip-meta.xyz/v1/bulk?ips=8.8.8.8,1.1.1.1" \ -H "Authorization: Bearer ipm_live_your_key_here"
{
"results": [
{ "ip": "8.8.8.8", "geo": { "city": "Mountain View", "country": "US" }, "network": { "asn": "AS15169", "isp": "Google LLC" } },
{ "ip": "1.1.1.1", "geo": { "city": "Sydney", "country": "AU" }, "network": { "asn": "AS13335", "isp": "Cloudflare, Inc." } }
]
}Same as GET /v1/bulk but accepts a JSON body — useful when the IP list is long or generated programmatically.
| Field | Type | Req | Description |
|---|---|---|---|
| ips | string[] | required | Array of IPv4/IPv6 addresses, max 100 |
curl -X POST https://api.ip-meta.xyz/v1/bulk \
-H "Authorization: Bearer ipm_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"ips": ["8.8.8.8", "1.1.1.1"]}'Usage & Quota
Returns lookup counts, plan limits, and billing period start/end. No query parameters.
Billing Functions
These are Firebase HTTPS callable functions invoked via the Firebase SDK — not plain REST. They require an authenticated Firebase user session.
httpsCallable(functions, 'functionName')(payload). They enforce Firebase Auth internally — no API key needed, but the user must be signed in.Cancels the caller's Paystack subscription at period end (non-immediate). Verifies subscription ownership with Paystack before disabling. Takes no payload.
| Field | Type | Description |
|---|---|---|
| success | boolean | Always true on success |
| message | string | Human-readable confirmation |
| periodEnd | string | null | ISO date when access expires |
import { getFunctions, httpsCallable } from 'firebase/functions';
const functions = getFunctions();
const cancel = httpsCallable(functions, 'cancelSubscription');
const result = await cancel();
// result.data = { success: true, message: "...", periodEnd: "2025-06-15" }| Code | Cause |
|---|---|
| unauthenticated | User not signed in |
| failed-precondition | No active subscription (already free) |
| permission-denied | Subscription doesn't match authenticated user's email |
| internal | Paystack API error — retry |
Sends a sales/enterprise enquiry to hello@ip-meta.xyz via Resend and stores the lead in sales_leads. Unauthenticated calls are permitted (pricing page use case).
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | required | Contact person name |
| string | required | Contact email | |
| company | string | optional | Company name |
| message | string | optional | Free-form message |
| type | string | optional | sales (pricing page) or custom (billing panel upgrade). Default: sales |
| currentPlan | string | optional | Caller's current plan. Default: free |
Returns the Paystack public key and plan pricing for the frontend to initialize the Paystack widget. The secret key is never returned.
{
"public_key": "pk_live_...",
"plans": {
"pro": { "usd": 19, "name": "Pro" },
"scale": { "usd": 79, "name": "Scale" }
}
}