API Documentation
Public REST API for DNS, WHOIS, SSL, email authentication and blacklist checks. JSON responses, simple bearer-token auth, 60 requests/minute per token.
Overview
The NerdTools API exposes the same checks available via the web UI as JSON endpoints. All responses are JSON; all requests use standard HTTP methods.
https://subs.gr/api/v1
All endpoints are versioned under /v1/. Breaking changes will move to /v2/ — your current integrations stay stable.
Authentication
All data endpoints require an API token. You can pass it three equivalent ways — choose whichever fits your client.
1. Bearer token (recommended)
Authorization: Bearer YOUR_API_TOKEN
2. X-Api-Key header
X-Api-Key: YOUR_API_TOKEN
3. Query parameter (last resort)
https://subs.gr/api/v1/dns?domain=example.com&api_key=YOUR_API_TOKEN
Avoid query-param auth in production — tokens may leak into web server logs and browser history. Use only for testing.
How to get a token
- Sign up for a free account (https://subs.gr/register)
- Go to Profile → API Tokens
- Click "Create Token", give it a descriptive name, copy the generated token (shown once).
Maximum 10 active tokens per account. Tokens never expire automatically — revoke them via the dashboard or DELETE endpoint.
Rate limit
60 requests per minute, per token.
When you exceed this, the API returns HTTP 429 with a Retry-After header indicating when you can try again.
HTTP/1.1 429 Too Many Requests
Retry-After: 47
Content-Type: application/json
{ "message": "Too Many Attempts." }
Many results are cached server-side (DNS 120s, SSL/WHOIS 1h, blacklist/emailauth 5min) — repeating the same query within those windows does not increase load on upstream services.
Error responses
All errors return JSON with a single "error" field describing the problem. Common status codes:
| Status | Meaning |
|---|---|
401 | Missing or invalid API token. |
422 | Invalid or missing required parameter. |
429 | Rate limit exceeded (60/min). |
503 | Upstream service unavailable (e.g. whois daemon down). |
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{ "error": "domain parameter required (e.g. ?domain=example.com)" }
GET/v1/dns
Resolve DNS records (A, AAAA, MX, NS, TXT, CNAME, CAA, SOA, SRV, PTR, ANY) for a domain.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
domain | string | yes | FQDN to look up, e.g. example.com. IDN domains accepted (auto-converted to Punycode). |
type | string | no | Record type. Default: A. One of: A, AAAA, MX, NS, TXT, CNAME, CAA, SOA, SRV, PTR, ANY |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/dns?domain=google.com&type=MX"
Example response (200 OK)
{
"domain": "google.com",
"type": "MX",
"records": [
{ "host": "google.com", "class": "IN", "ttl": 300, "type": "MX", "pri": 10, "target": "smtp.google.com" }
],
"count": 1,
"cached": true,
"ttl": 120
}
GET/v1/ssl
Check the SSL/TLS certificate of a domain — expiry, days remaining, issuer, SANs.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
domain | string | yes | FQDN to check (port 443 assumed). |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/ssl?domain=github.com"
Example response (200 OK)
{
"domain": "github.com",
"status": "ok",
"days_left": 287,
"expires": "2027-03-04",
"issued": "2026-03-04",
"subject_cn": "github.com",
"issuer_o": "Sectigo Limited",
"issuer_cn": "Sectigo ECC Domain Validation Secure Server CA",
"san": ["github.com", "www.github.com", "*.github.com"]
}
Possible status values:
ok (>30 days left),
expiring_soon (≤30),
expired,
error.
GET/v1/emailauth
Check email authentication records: SPF, DKIM, DMARC.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
domain | string | yes | FQDN to check (e.g. gmail.com). |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/emailauth?domain=gmail.com"
Example response (200 OK)
{
"domain": "gmail.com",
"score": "3/3",
"status": "pass",
"spf": { "status": "found", "record": "v=spf1 redirect=_spf.google.com", "policy": "neutral" },
"dmarc": { "status": "found", "record": "v=DMARC1; p=none; sp=quarantine; rua=mailto:...", "policy": "none" },
"dkim": { "status": "found", "selector": "20230601", "host": "20230601._domainkey.gmail.com" }
}
Top-level status:
pass (all 3 found),
partial (1–2 found),
fail (none found).
GET/v1/blacklist
Check if an IP or domain appears on known email blacklists (DNSBLs) — Spamhaus, Barracuda, SpamCop, SORBS and more.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
query | string | yes | IPv4 address or domain. Domains are resolved to IPv4 first; IPv6 is not supported. |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/blacklist?query=1.1.1.1"
Example response (200 OK)
{
"query": "1.1.1.1",
"ip": "1.1.1.1",
"status": "clean",
"listed": 0,
"total": 20,
"details": [
{ "name": "Spamhaus ZEN", "zone": "zen.spamhaus.org", "listed": false, "blocked": false, "code": null },
{ "name": "SpamCop", "zone": "bl.spamcop.net", "listed": false, "blocked": false, "code": null }
]
}
status is "clean" if listed === 0, otherwise "listed".
GET/v1/whois
Domain registration data — registrar, creation/expiry dates, nameservers.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
domain | string | yes | FQDN to look up. |
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/whois?domain=github.com"
Example response (200 OK)
{
"domain": "github.com",
"parsed": {
"registrar": "MarkMonitor Inc.",
"created": "2007-10-09T18:20:50Z",
"expires": "2027-10-09T18:20:50Z",
"nameservers": ["dns1.p08.nsone.net", "dns2.p08.nsone.net", "dns3.p08.nsone.net", "dns4.p08.nsone.net"]
}
}
.gr / .ελ domains return status:"unavailable" because the registry restricts public WHOIS due to GDPR.
GET/v1/tokens
List your API tokens. The token plaintext is never shown after creation — only metadata is returned.
Example request
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/tokens"
Example response (200 OK)
{
"tokens": [
{
"id": 42,
"name": "production-server-01",
"last_used_at": "2026-05-22T14:31:08+03:00",
"expires_at": null,
"created_at": "2026-04-10T09:12:55+03:00"
}
]
}
POST/v1/tokens
Create a new API token. The plain token is returned ONCE — save it immediately.
Body (JSON)
| Name | Type | Required | Description |
|---|---|---|---|
name | string | no | Human-readable label (1–100 chars). Default: "My token". |
Example request
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"my-new-token"}' \
"https://subs.gr/api/v1/tokens"
Example response (201 Created)
{
"id": 43,
"name": "my-new-token",
"token": "ntk_live_a8B9c0D1e2F3g4H5i6J7k8L9m0N1o2P3q4R5s6T7",
"note": "Save this token — it will not be shown again."
}
Limit: 10 tokens per account.
DELETE/v1/tokens/{id}
Revoke a token by ID. The token is invalidated immediately.
Example request
curl -X DELETE \
-H "Authorization: Bearer YOUR_TOKEN" \
"https://subs.gr/api/v1/tokens/42"
Example response (200 OK)
{ "message": "Token revoked." }
Returns 404 if the token does not exist or does not belong to you.