Ask before you sign.
One POST tells an agent whether the transaction it is about to sign breaks its published spec.
The watchdog judges transactions after they land. Pre-flight moves the same rules in front of the signature. Haltr reads the agent's spec and halt state from the registry, checks the token's mint and a Jupiter sell-back, and simulates the transaction on mainnet when you send it. Every check served is logged on this page.
Endpoint
JSON in, JSON out. CORS is open, so an agent can call it from anywhere. Limits: 30 checks a minute per agent and 240 per IP, a transaction of up to 2,400 base64 characters, and 4s for each external read. A read that times out marks its check as warn. It never passes silently.
https://haltr.xyz/api/preflightRequest
| Field | Type | Required | Meaning |
|---|---|---|---|
| agent | string | Required | Registry id, such as haltr-demo-agent, or the agent's wallet address. |
| client | string | Optional | Label shown in the public log below. Trimmed to 60 characters. |
| intent. | string | Required | Venue the trade routes through: Raydium, ClawPump, Jupiter, Orca, Meteora or PumpSwap. Any other name is evaluated as Other. When the sent programs call a different known venue, that venue is evaluated instead. |
| intent. | "buy" | "sell" | Required | Direction of the trade. |
| intent. | string | Required | Mint of the token bought or sold. Use So11111111111111111111111111111111111111112 for SOL. SOL, USDC and USDT are named by their mint. Any other mint that calls itself one of those is named by its short address, so it cannot pass an asset allowlist. |
| intent. | number | Required | SOL notional of the trade. At least one lamport, 0.000000001. |
| intent. | number | Required | Slippage tolerance the agent will sign with, 0 to 10000. |
| intent. | string[] | Optional | Top-level programs the transaction calls. Ignored when a transaction is sent. Without either, Haltr infers the venue's usual programs and only warns about them. |
| intent. | string | Optional | Base64 transaction, legacy or v0, up to 2,400 characters. Send it unsigned. Signatures are not needed because Haltr simulates with signature checks off. The agent wallet must be one of its signers. Haltr reads its programs and simulates it on mainnet. |
| intent. | number | Optional | Expected PnL in SOL, negative for a loss. Feeds the drawdown rule. Defaults to 0. |
Response
| Field | Type | Meaning |
|---|---|---|
| ok | boolean | True only when the agent is armed, no spec rule breaks, the honeypot check does not fail and the simulation does not fail. Sign only on true. |
| agentId | string | Registry id the request resolved to. |
| agentStatus | "active" | "halted" | "flattened" | Registry status at the time of the check. |
| specVersion | number | The published spec version that was applied. |
| certified | boolean | True when that spec version is certified with a $ANSEM burn. |
| violations | Violation[] | Broken rules, most severe first. Each has rule, severity, title, detail, observed and limit. |
| checks | object | Seven named checks, each { status, detail }. Status is pass, warn, fail or skipped. |
| evaluatedMs | number | Wall time Haltr spent on the check, in milliseconds. |
| checkId | number | null | Row id in the public log. |
| docs | string | Link to this page. |
| resolved | object | How the intent was read: dex, asset, programIds, programSource and roundTripPct. |
Checks
ok is false when the agent is not armed, any spec rule breaks, or the honeypot or simulation check fails. Warnings are for the agent's own judgment and never flip ok on their own.
| Check | What Haltr looks at | When it fails or warns |
|---|---|---|
| halted | Registry status of the agent. | Fails when the agent is halted or flattened. A halted agent must not trade. |
| spec | The same deterministic rules the watchdog applies to landed transactions: size, drawdown, venue, asset list, slippage, programs, rate and honeypot. | Fails on any violation. |
| honeypot | For buys, a Jupiter quote from SOL to the token, then back to SOL for exactly what the buy returns. For every mint, its Token-2022 extensions. | Fails with no sell route, a round trip under 50%, a non-transferable mint, a permanent delegate, a transfer fee over 10%, or an address that is not a token mint. Warns on a transfer hook, a fee over 1%, or a read that did not answer. |
| tokenAuthorities | Mint and freeze authority on the mint. | Warns only. USDC has both and never fails here. |
| programs | Top-level programs against the spec allowlist. Read from the transaction, else intent.programIds, else inferred from the venue. | Fails on a sent or declared program outside the allowlist. Inferred programs are a guess, so they only warn and never fail. |
| simulation | simulateTransaction on mainnet with signature checks off and a fresh blockhash. Inner programs are listed from the logs. The agent wallet must be one of the transaction's signers. | Fails when the transaction errors, when the RPC rejects it as malformed, or when the agent wallet does not sign it. Warns when the RPC cannot be reached. Skipped without a transaction. |
| rateLimit | Actions the watchdog observed from the wallet in the last 60 seconds, plus this one. | Fails above the spec's trades per minute. |
Status codes
| 200 | A PreflightResponse. Read ok. |
| 400 | Bad input. The error names the field. |
| 404 | No registered agent matches agent. |
| 413 | Body over 16,384 bytes, or a transaction over 2,400 base64 characters. |
| 429 | Over 30 checks a minute for one agent, or 240 from one IP. Wait for Retry-After. |
| 500, 503 | Haltr could not evaluate. Treat it as not ok. |
Examples
curl -s -X POST https://haltr.xyz/api/preflight \
-H 'content-type: application/json' \
-d '{"agent":"haltr-demo-agent","client":"my-bot/1.0","intent":{"dex":"Raydium","side":"buy","assetMint":"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v","sizeSol":0.004,"slippageBps":50}}'import type { VersionedTransaction } from "@solana/web3.js";
/** Ask Haltr before signing. Send tx unsigned; sign only on true. */
export async function preflight(tx: VersionedTransaction): Promise<boolean> {
const res = await fetch("https://haltr.xyz/api/preflight", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
agent: "haltr-demo-agent",
client: "my-bot/1.0",
intent: {
dex: "Raydium", side: "buy", sizeSol: 0.004, slippageBps: 50,
assetMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
transaction: Buffer.from(tx.serialize()).toString("base64"),
},
}),
});
if (!res.ok) return false; // fail closed
const verdict = await res.json();
return verdict.ok === true;
}Try it
This form calls the live API for Haltr's demo agent. Its spec v7 allows Raydium only, at most 0.005 SOL a trade. Change the DEX or the size to see the check stop it.
No request sent yet. Edit the intent and send it. The answer from the live API appears here.
Recent checks
The ten newest checks served, read from the pre-flight log.
| Time | Agent | Verdict | Reasons | Latency | Client |
|---|---|---|---|---|---|
| 2026-09-29 18:12:55 UTC | Haltr Reference Agent | Clear | None | 1081ms | haltr-reference-agent/1 |
| 2026-09-29 17:57:49 UTC | Haltr Reference Agent | Clear | None | 1090ms | haltr-reference-agent/1 |
| 2026-09-29 17:42:43 UTC | Haltr Reference Agent | Clear | None | 1102ms | haltr-reference-agent/1 |
| 2026-09-29 17:27:36 UTC | Haltr Reference Agent | Clear | None | 1093ms | haltr-reference-agent/1 |
| 2026-09-29 17:12:30 UTC | Haltr Reference Agent | Clear | None | 1076ms | haltr-reference-agent/1 |
| 2026-09-29 17:09:23 UTC | Haltr Demo Agent | Clear | None | 1086ms | haltr-docs |
| 2026-09-29 16:57:24 UTC | Haltr Reference Agent | Clear | None | 1090ms | haltr-reference-agent/1 |
| 2026-09-29 16:42:20 UTC | Haltr Reference Agent | Clear | None | 1104ms | haltr-reference-agent/1 |
| 2026-09-29 03:02:27 UTC | Haltr Demo Agent | Stop | MAX_TRADE_SIZE, MAX_SLIPPAGE | 4183ms | skill-test |
| 2026-09-29 03:02:14 UTC | Haltr Demo Agent | Clear | None | 4195ms | skill-test |