Need a reusable client? Download the PHP, Python and Node.js lightweight SDKs. The quick examples and their existing links remain available.
Integration examples
Following the multilingual examples in Console, these samples create a GFW Full batch, then read paginated results by batch_id. They are for reading and copying only; this page does not execute API requests.
View batch creation and paginated result examples
#!/usr/bin/env bash
set -euo pipefail
# Requires curl + jq. Set these server-side environment variables first.
: "${WEAVEBIT_API_KEY:?Set your API key}"
: "${WEAVEBIT_REQUEST_ID:?Set and persist one ID for this logical create}"
base='https://api.weavebit.com/v2'
request() {
local path="$1" body="$2" response
response=$(curl --silent --show-error --fail-with-body --max-time 30 \
-X POST "$base/$path" \
-H "Authorization: Bearer $WEAVEBIT_API_KEY" \
-H 'Content-Type: application/json' \
-H "Idempotency-Key: $WEAVEBIT_REQUEST_ID" \
--data "$body") || return 1
if ! jq -e '.code == 0' >/dev/null <<<"$response"; then
printf 'API operation failed; inspect code and message.\n' >&2
return 1
fi
printf '%s' "$response"
}
body='{"check_type":"gfw_full_domain_check","target":[{"domain":"example.com"}],"nodes":["NODE_ID_FROM_GET_NODES"]}'
# Replace the node placeholder using get_nodes; review estimate before create.
# Create can incur charges. Reuse the same body and request ID for a retry.
created=$(request task/create "$body")
batch_id=$(jq -er '.batch_id' <<<"$created")
printf 'Persist batch_id: %s\n' "$batch_id"
first=$(request task/result "$(jq -cn --arg id "$batch_id" \
'{batch_id:$id,page:1,page_size:200}')")
pages=$(jq -er '.pagination.pages' <<<"$first")
(( pages >= 1 && pages <= 5 )) || exit 1
jq '{batch_status,datas,pagination}' <<<"$first"
for ((page=2; page<=pages; page++)); do
request task/result "$(jq -cn --arg id "$batch_id" --argjson p "$page" \
'{batch_id:$id,page:$p,page_size:200}')" | jq '{batch_status,datas,pagination}'
done
# One read pass, not polling. Pending/running: resume later with this batch_id.
# Retain required results before expires_at; never turn null into success.<?php
// PHP 8+ with cURL. Set and persist these server-side environment variables.
$key = getenv('WEAVEBIT_API_KEY');
$requestId = getenv('WEAVEBIT_REQUEST_ID');
if (!$key || !$requestId) {
throw new RuntimeException('Set API key and a persistent request ID.');
}
function api(string $path, array $body): array {
global $key, $requestId;
$curl = curl_init('https://api.weavebit.com/v2/' . $path);
curl_setopt_array($curl, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30, CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key,
'Content-Type: application/json', 'Idempotency-Key: ' . $requestId],
CURLOPT_POSTFIELDS => json_encode($body, JSON_THROW_ON_ERROR),
]);
$raw = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
if ($raw === false || $status < 200 || $status >= 300) {
throw new RuntimeException('HTTP request failed; preserve creation idempotency.');
}
$data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
if (($data['code'] ?? null) !== 0) {
throw new RuntimeException('API code: ' . ($data['code'] ?? 'missing'));
}
return $data;
}
$body = ['check_type' => 'gfw_full_domain_check',
'target' => [['domain' => 'example.com']],
'nodes' => ['NODE_ID_FROM_GET_NODES']];
// Fetch current nodes and review estimate first. Create can incur charges.
$created = api('task/create', $body);
$batchId = $created['batch_id']; // Persist this before querying results.
$first = api('task/result', ['batch_id' => $batchId, 'page' => 1, 'page_size' => 200]);
$pages = (int)$first['pagination']['pages'];
if ($pages < 1 || $pages > 5) throw new RuntimeException('Invalid page count.');
$rows = $first['datas'];
for ($page = 2; $page <= $pages; $page++) {
$result = api('task/result', ['batch_id' => $batchId, 'page' => $page, 'page_size' => 200]);
$rows = array_merge($rows, $result['datas']);
}
echo json_encode(['batch_id' => $batchId, 'batch_status' => $first['batch_status'],
'datas' => $rows], JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
// One read pass. If pending/running, resume later with the stored batch_id.
// Retain results before expires_at, preserving 0, 1, and null separately.# Python 3. Standard library only; credentials stay on your server.
import json
import os
from urllib.request import Request, urlopen
key = os.environ["WEAVEBIT_API_KEY"]
request_id = os.environ["WEAVEBIT_REQUEST_ID"] # Persist for this logical create.
def api(path, body):
request = Request("https://api.weavebit.com/v2/" + path,
data=json.dumps(body).encode("utf-8"), method="POST",
headers={"Authorization": "Bearer " + key,
"Content-Type": "application/json",
"Idempotency-Key": request_id})
# HTTP errors raise; do not blindly retry creation with a new ID.
with urlopen(request, timeout=30) as response:
data = json.load(response)
if data.get("code") != 0:
raise RuntimeError("API code: " + str(data.get("code")))
return data
body = {"check_type": "gfw_full_domain_check",
"target": [{"domain": "example.com"}],
"nodes": ["NODE_ID_FROM_GET_NODES"]}
# Replace the node placeholder and review estimate first; create can incur charges.
created = api("task/create", body)
batch_id = created["batch_id"] # Persist this before querying results.
first = api("task/result", {"batch_id": batch_id, "page": 1, "page_size": 200})
pages = int(first["pagination"]["pages"])
if not 1 <= pages <= 5:
raise RuntimeError("Invalid page count")
rows = list(first["datas"])
for page in range(2, pages + 1):
result = api("task/result", {"batch_id": batch_id, "page": page, "page_size": 200})
rows.extend(result["datas"])
print(json.dumps({"batch_id": batch_id, "batch_status": first["batch_status"],
"datas": rows}, indent=2))
# One read pass. If pending/running, resume later with the stored batch_id.
# Retain results before expires_at; preserve None (null), 0, and 1 separately.// Node.js 18+. Credentials and a persistent request ID belong on your server.
const key = process.env.WEAVEBIT_API_KEY;
const requestId = process.env.WEAVEBIT_REQUEST_ID;
if (!key || !requestId) throw new Error('Set API key and a persistent request ID.');
async function api(path, body) {
const response = await fetch(`https://api.weavebit.com/v2/${path}`, {
method: 'POST', signal: AbortSignal.timeout(30000),
headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json',
'Idempotency-Key': requestId },
body: JSON.stringify(body),
});
if (!response.ok) throw new Error(`HTTP ${response.status}; preserve creation idempotency.`);
const data = await response.json();
if (data.code !== 0) throw new Error(`API code: ${data.code}`);
return data;
}
async function main() {
const body = { check_type: 'gfw_full_domain_check',
target: [{ domain: 'example.com' }], nodes: ['NODE_ID_FROM_GET_NODES'] };
// Fetch current nodes and review estimate first; create can incur charges.
const created = await api('task/create', body);
const batchId = created.batch_id; // Persist this before querying results.
const first = await api('task/result', { batch_id: batchId, page: 1, page_size: 200 });
const pages = first.pagination.pages;
if (!Number.isInteger(pages) || pages < 1 || pages > 5) throw new Error('Invalid page count');
const rows = [...first.datas];
for (let page = 2; page <= pages; page++) {
const result = await api('task/result', { batch_id: batchId, page, page_size: 200 });
rows.push(...result.datas);
}
console.log(JSON.stringify({ batch_id: batchId, batch_status: first.batch_status,
datas: rows }, null, 2));
// One read pass. If pending/running, resume later with the stored batch_id.
// Retain results before expires_at; preserve 0, 1, and null separately.
}
main().catch(error => { console.error(error.message); process.exitCode = 1; });API v2 provides asynchronous batch network checks with seven methods: estimate the cost, create a batch, then query progress and retain results. Console recurring monitoring currently supports DNS Pollution and GFW Full tasks. Use monitoring when the platform should schedule checks and deliver notifications.
Results describe observations and assessments for a target, method, network, and time. They are not a complete browser test or attribution of responsibility. See result interpretation for boundaries and the batch workflow for implementation guidance.
Authentication and responses
The Base URL is https://api.weavebit.com/v2. The v2 endpoints below use POST, UTF-8 JSON, and the same account API key:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Manage the key in Console. Store it on the server, not in browser scripts, request URLs, source control, or logs. Responses include integer code and string message; code=0 means the API operation succeeded. HTTP success, API success, and a normal detection outcome are separate checks.
Seven methods and target parameters
Use a lowercase check_type below. target is an array of objects whose fields depend on the method. Supply nodes except for DNS Pollution.
| check_type | Required target fields | Optional fields and defaults | Output and boundary |
|---|---|---|---|
dns_resolve |
domain |
resolver: "" |
Resolution status and A records; resolution success is not a Pollution assessment |
icmp_ping_check |
ip |
count: 4 |
ICMP status, latency, and loss; no reply does not prove an application outage |
tcp_connect_check |
ip |
port: 443 |
Connection status for an IPv4 address and port, not an application response |
http_host_reset_check |
domain |
port: 80, path: "/" |
HTTP Host request status; a valid response does not guarantee 200 or a correct page |
tls_sni_handshake_check |
domain |
port: 443 |
Handshake status with the target SNI, not a complete certificate audit |
dns_pollution_check |
domain |
None | Pollution result_code, DNS status, and a; omit nodes |
gfw_full_domain_check |
domain |
http_port: 80, tls_port: 443 |
DNS Pollution, HTTP Host, TLS SNI, and overall_result, not all seven methods |
domain must be a plain hostname, at most 253 characters, without a scheme, path, query, port, spaces, or @. Unicode internationalized names normalize to lowercase ASCII Punycode; use check_id to associate results with your targets. ip accepts IPv4 only. Ports are integers from 1–65535; count is 1–20. path starts with / and is at most 2048 characters. resolver is an IPv4 address; leaving it empty uses the network's system DNS.
Estimate and creation requests accept 1–1000 targets. Targets that normalize to the same name can still be charged as separate tasks; deduplicate on the client. Do not mix domain and IP fields or substitute GFW Full's http_port and tls_port for a base method's port.
Endpoints
Append these paths to the v2 Base URL. Queries do not create checks; create starts a batch that can incur charges.
| Path | Request | Purpose |
|---|---|---|
/task/get_nodes |
{} |
Read currently available nodes |
/task/estimate |
check_type, target, and nodes where required |
Estimate a target and node combination |
/task/create |
The same detection parameters | Create an asynchronous batch with optional idempotency header |
/task/result |
batch_id, optional page, page_size |
Read one page of targets in a batch |
/task/get_batches |
Optional page: 1, page_size: 20, status, check_type |
Read batch metadata from the last 24 hours, without target lists |
/task/get_balance |
{} |
Read balance, reservations, and available balance |
get_batches.page_size accepts 1–100. Filter status by pending, running, or completed, and check_type by method. result requires the batch_id returned by creation, not just a check_id. Use check_id to identify and associate targets in the returned list.
Fetch and select nodes
curl -X POST 'https://api.weavebit.com/v2/task/get_nodes' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{}'
Response datas[] contains node_id, node_zh_name, and node_en_name; parent nodes also contain children[]. Use node_id for programmatic association, not display names. nodes accepts an array of up to 100 node codes or the string "all". Parents expand into currently available child nodes. Availability changes; choose networks relevant to customers and estimate again before creation.
Omit nodes for DNS Pollution. Its public contract requires a domain and returns an assessment; clients do not need the internal detection implementation.
Estimate and create
Send the intended JSON body to /task/estimate, review the estimate and available balance, then send it to /task/create. This GFW Full example requires a current node code from get_nodes and a target you are authorized to check:
curl -X POST 'https://api.weavebit.com/v2/task/create' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: YOUR_UNIQUE_REQUEST_ID' \
-d '{
"check_type": "gfw_full_domain_check",
"target": [{"domain": "example.com"}],
"nodes": ["NODE_ID_FROM_GET_NODES"]
}'
For a standalone DNS Pollution batch, use this body:
{
"check_type": "dns_pollution_check",
"target": [{"domain": "example.com"}]
}
Estimate response data includes unit_price, currency, planned_node_count, planned_target_count, planned_quantity, estimate_cost, and available_balance. Amounts are decimal strings; do not use binary floating-point for accounting. Review current pricing and rely on the actual estimate and creation responses.
Creation returns batch_id, datas[].check_id, normalized datas[].target, execution_deadline_at, expires_at, and estimated billing. Acceptance does not mean completion. Creation checks available funds and reserves pending costs; valid returned results are settled. Timeouts, node errors, and results discarded for insufficient balance are not charged. Repeated queries do not cause duplicate charges.
Idempotency and retries
Idempotency-Key is optional but recommended for each creation. It accepts 1–128 letters, digits, and . _ : -. The same account, key, and request return the original batch; different parameters with that key return 40901. If creation times out with uncertain acceptance, retry the original body with the original key, not a new key.
40902 means creation with that key is still processing; retry later with the same key. For 42900, respect Retry-After. Idempotency records expire with batch data after 24 hours; later reuse is treated as a new request. Persist your own business-request and batch association.
Query and paginate results
curl -X POST 'https://api.weavebit.com/v2/task/result' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"batch_id":"BATCH_ID_FROM_CREATE","page":1,"page_size":200}'
page defaults to 1. Default and maximum page_size are 200 targets. Follow pagination.page, page_size, total, and pages to read every page. Pagination only changes datas; batch_status and final billing cover the whole batch. Match a particular target by check_id in the returned list.
batch_status and datas[].status use pending, running, and completed for progress. Completed batches can still contain timeouts or indeterminate results. For methods other than DNS Pollution, target results are in datas[].results[], containing node code, names, and result. DNS Pollution returns its assessment in datas[].result, without a selected-node list.
For base methods read status and observation fields. For DNS Pollution read result_code, status, and a. Each GFW Full node's result contains the three named dimension objects and overall_result. Preserve 0, 1, and null separately; never convert null into normal or blocked. See result documentation.
Execution and retention deadlines
A batch has a maximum six-hour execution window. Assignments not returned by execution_deadline_at reach a final timeout state and are not charged. Targets and results expire for cleanup 24 hours after creation, not completion. Both timestamps use UTC ISO 8601.
Collect results during execution and retain required evidence before expires_at. Console monitoring history and temporary API batches have different lifecycles; do not infer API retention from monitoring history.
Error handling
| code | Meaning | Client action |
|---|---|---|
40000 |
Invalid request | Check JSON and required fields |
40001 |
Invalid method | Check check_type |
40002 |
Invalid target | Check domain, IP, ports, and parameters |
40003 |
Invalid nodes | Refresh nodes and check nodes |
40004 |
Limit exceeded | Split targets or reduce selections |
40100 |
Unauthorized | Check the account key; avoid endless retries |
40201 |
Insufficient available balance | Review balance and pending reservations |
40401 |
Task not found | Check account, identifier, and expiry |
40901 |
Idempotency conflict | Preserve the original request; use a new key for a new operation |
40902 |
Idempotent creation in progress | Retry later with the original key |
41300 |
Payload too large | Reduce request content |
42900 |
Rate limited | Respect Retry-After and use bounded backoff |
50000 |
Internal error | Bounded retries; preserve creation idempotency |
50301 |
Pending account settlement | Retry later |
Protocol statuses such as NODE_TIMEOUT, NODE_ERROR, INVALID_RESULT, and UNKNOWN are separate from API error codes. HTTP/TLS timeouts, EOF, and handshake errors must not be rewritten as proven blocking.
API v1 synchronous single domain checks
API v1 at https://api.weavebit.com/v1/task/pollute provides synchronous single-domain DNS Pollution checks only. It uses the same account key but form fields key and host, not the v2 JSON request format.
curl -X POST 'https://api.weavebit.com/v1/task/pollute' \
-H 'Accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'key=YOUR_API_KEY' \
--data-urlencode 'host=example.com'
Check error_code and error_msg first. In a successful response, result=0 means no DNS Pollution was reported, 1 means Pollution was reported, and -1 means no valid outcome is currently available. Synchronous means waiting in the same request, not a fixed response-time guarantee. This is not a batch interface; prefer v2 for batches, concurrency, or other methods. Manage keys, balance, and API Explorer in Console.