Docs menu

Verify API

Audit a claim against live web evidence or citations you supply: claim in, four-label verdict out — with span-level quotes, machine-readable reason codes and source authority. Typically takes 5–15 seconds.

POST /v1/verify

Generally available. A deployment with the endpoint switched off answers 404. Legacy alias: POST https://searchpipe.tech/verify.

Authorize

Authenticate with your sp- API key in the Authorization: Bearer sp-YOUR_KEY header; X-API-Key: sp-YOUR_KEY is also accepted. Verification uses the same key and credit balance as /v1/search.

Request

Send Content-Type: application/json. Only claim is required. Input moderation applies: rejected content returns 400 without a charge.

Body parameters

Body
ParameterTypeDescription
claimstring · requiredThe claim (statement or citation) to verify — max 2000 characters.
modestring · default autoEvidence route: paper (DOI/arXiv), web, or auto — a DOI or arXiv signal picks the paper route.
evidence_urlsstring[] · optionalUp to 5 caller-supplied citations to verify; URLs are SSRF-checked.
max_evidenceinteger · default 5Maximum number of evidence items to return (1-10).

Request example

curl -X POST https://searchpipe.tech/verify \
  -H "Authorization: Bearer sp-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"claim": "Attention Is All You Need introduced the transformer architecture"}'
import httpx

resp = httpx.post(
    "https://searchpipe.tech/verify",
    headers={"Authorization": "Bearer sp-YOUR_KEY"},
    json={"claim": "Attention Is All You Need introduced the transformer architecture"},
    timeout=60,
)
data = resp.json()
print(data["verdict"], data["reason_code"], data["confidence"])
for ev in data["evidences"]:
    print(ev["per_evidence_verdict"], ev["url"])
const resp = await fetch("https://searchpipe.tech/verify", {
  method: "POST",
  headers: {
    "Authorization": "Bearer sp-YOUR_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ claim: "Attention Is All You Need introduced the transformer architecture" }),
});
const data = await resp.json();
console.log(data.verdict, data.reason_code, data.confidence);
for (const ev of data.evidences) console.log(ev.per_evidence_verdict, ev.url);
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"time"
)

func main() {
	payload := []byte(`{"claim":"Attention Is All You Need introduced the transformer architecture"}`)
	req, _ := http.NewRequest("POST", "https://searchpipe.tech/verify", bytes.NewReader(payload))
	req.Header.Set("Authorization", "Bearer sp-YOUR_KEY")
	req.Header.Set("Content-Type", "application/json")
	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	out, _ := io.ReadAll(resp.Body)
	fmt.Println(string(out))
}
import java.net.URI;
import java.net.http.*;
import java.time.Duration;

public class SearchPipeVerify {
    public static void main(String[] args) throws Exception {
        String json = "{\"claim\":\"Attention Is All You Need introduced the transformer architecture\"}";
        HttpClient client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(10))
            .build();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://searchpipe.tech/verify"))
            .timeout(Duration.ofSeconds(60))
            .header("Authorization", "Bearer sp-YOUR_KEY")
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();
        HttpResponse<String> resp =
            client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(resp.body());
    }
}
using System.Net.Http.Json;

using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "sp-YOUR_KEY");

var payload = new
{
    claim = "Attention Is All You Need introduced the transformer architecture",
};

HttpResponseMessage resp = await client.PostAsJsonAsync("https://searchpipe.tech/verify", payload);
resp.EnsureSuccessStatusCode();
Console.WriteLine(await resp.Content.ReadAsStringAsync());

Response

Every verdict carries a machine-readable reason_code from a fixed whitelist, and every evidence item carries a verbatim quote span — never a free-form generated explanation. This illustrative response shows the shape; values are examples, not a live verification.

{
  "verdict": "supported",
  "confidence": 0.93,
  "reason_code": "quote_span_found",
  "evidences": [
    {
      "url": "https://arxiv.org/abs/1706.03762",
      "title": "Attention Is All You Need",
      "source_tier": "preprint",
      "quote": "We propose a new simple network architecture, the Transformer, based solely on attention mechanisms",
      "span_start": 0,
      "span_end": 103,
      "per_evidence_verdict": "supported",
      "confidence": 0.95,
      "url_health": {
        "status_code": 200,
        "redirected": false,
        "wayback_snapshot": null,
        "fetched_at": "2026-10-30T09:00:00Z"
      }
    }
  ],
  "timing": {"v_prepare": 0.4, "v_evidence": 3.1, "v_judge": 6.2, "v_health": 0.8}
}

Verdict labels

Four-label verdict scale returned in the verdict field
verdictMeaning
supportedFetched evidence whose text explicitly supports the claim.
partialThe evidence supports part of the claim, or the support is weak.
unsupportedReachable evidence does not support the claim — catches misattributed or hallucinated citations.
inconclusiveNo verdict possible: fetch failures, paywalls or insufficient checkable evidence. A valid deliverable, billed like any other verdict.

reason_code whitelist

Machine-readable reasons returned in the reason_code field
reason_codeMeaning
doi_matchThe claim resolved to a DOI that points to a real paper.
title_matchThe claim matched a known paper title (fuzzy).
quote_span_foundA verbatim span supporting the claim was located in a fetched source.
no_supporting_evidenceSources were reachable but none of them supports the claim.
fetch_failedCandidate sources could not be fetched.
paywallCandidate sources sit behind a paywall.
low_authorityOnly low-authority sources were available, so confidence stays low.
conflicting_evidenceThe evidence points in more than one direction.

Response fields

200 response body
FieldTypeDescription
verdictstringOne of supported, partial, unsupported, inconclusive (table above).
confidencenumber0-1 confidence in the verdict.
reason_codestringMachine-readable reason from the whitelist above — template phrases, never free-form text.
evidencesarrayEvidence items, each with url, title, source_tier (official/press/academic/preprint/community/unknown), quote, span_start, span_end, per_evidence_verdict, confidence and url_health (status_code, redirected, wayback_snapshot, fetched_at).
timingobjectPer-stage wall time in seconds (v_prepare, v_evidence, v_judge, v_health).

Verify a batch of claims

POST/v1/verify/batch

Check up to 20 claims in one synchronous request and handle each result independently. Partial failures do not fail the whole batch.

Batch body
ParameterDescription
claimsRequired array of 1–20 statements; each is limited to 2,000 characters.
modeauto (default), paper, or web; applied to the entire batch.
max_evidence1–10 evidence items per claim; default 5. This endpoint does not accept evidence_urls.
Batch response fields
FieldMeaning
results[]Matches the order of claims. Each item has the single-claim response shape, or null when that item fails.
failed[]Each failure includes index (zero-based position in claims) and error. Partial failures do not fail the whole batch.
curl -X POST "https://searchpipe.tech/v1/verify/batch" \
  -H "Authorization: Bearer sp-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "claims": [
    "FastAPI is a Python web framework.",
    "Python was created by Guido van Rossum."
  ],
  "mode": "web",
  "max_evidence": 5
}'

The batch is charged before execution. Failed items are refunded; completed inconclusive verdicts are charged. The batch is a synchronous REST endpoint, not a background job — there is no separate MCP batch tool.

Billing and error handling

  • 1 credit per claim. An inconclusive verdict is a completed verification and is charged; overall pipeline failures return 503 and are refunded automatically.
  • Input moderation rejections return 400 without a charge.
  • Verdicts are not cached — a verdict depends on the live state of the cited pages.
  • A deployment with the endpoint switched off answers 404.