Read the full prompt
# Buy your first Colter work check
**Colter's work check** checks work an AI agent produced against the original request, stated criteria, and the evidence you name, and returns findings, citations, the checks performed, limitations, and a verdict. This prompt walks you through registering me with Colter, buying one check from a small script in my project, and reading the report with me.
**Price:** $5.00 per check, fixed.
**Right now:** Not available to buy right now: no payment method is ready. Do the first setup step, tell me, and stop.
**Docs:** https://colter.ai/docs/agents (exact steps) and https://colter.ai/check (terms, remedy, sample report)
**Contract:** https://api.colter.ai/api/agent/v1/services/colter_work_check needs no credential. It is the source of truth for schemas, price, and live availability, so read it before writing code. Index for agents: https://colter.ai/llms.txt
## Ground rules
- Credentials and the registration poll secret never go in this chat, in prompts, in job input, or in URLs. Scripts write them to `.env` and never print them. Do not print or display `.env`.
- Ask me before anything that commits me: accepting Colter's terms, buying, paying, accepting, or disputing.
- Retry with the same idempotency key and the same body. A timeout never cancels a job and never permits buying again; read the job to recover.
- Do only what the job's `next_actions` allows.
## Setup
Check each item IN ORDER. Stop at the first missing one, fix it, then resume after I confirm.
1. **Availability.** `GET https://api.colter.ai/api/agent/v1/services/colter_work_check`. Continue only if `service.availability.state` is `available` or `sandbox`, and pay only with a rail in `service.availability.purchasable_rails`. If it is `unavailable`, tell me the `reasons` and stop.
2. **Node.js 22+.** `node --version`. The scripts use built-in `fetch` and `--env-file`; no packages are needed.
3. **A project folder.** Ask me where my project lives. If I don't have one: `mkdir colter-check && cd colter-check && npm init -y && npm pkg set type=module`.
4. **Secrets stay out of git.** Add `.env` and `.colter/` to `.gitignore` before anything writes to them.
5. **Colter's terms.** Show me https://colter.ai/legal and ask whether I accept terms version `2026-07-21`. Send `accept_terms_version` only after I say yes.
6. **A Colter credential.** If `.env` already has `COLTER_TOKEN`, check it with `GET https://api.colter.ai/api/agent/v1/me` without printing it, and skip this step. Otherwise ask me which applies:
- **I'm new to Colter:** ask for my email (an email is not a secret). Run `register.mjs` below with it. Colter emails me; I confirm on the linked page. If I read you the code instead, POST `{"code": "<code>"}` to `https://api.colter.ai/api/agent/v1/registrations/<key>/verify` with the `X-Colter-Registration-Secret` header read from `.env`, without printing it.
- **I already have a Colter account:** run `register.mjs` with no email. It prints a link and a `user_code`; I approve the connection while signed in.
The default grant lets the credential buy work checks of up to $10.00 each and review what they deliver. I can change or revoke it in Colter at any time.
## Register (writes the credential to .env, prints no secrets)
Reference shape. Verify field names against https://colter.ai/docs/agents#authenticate.
```js
// register.mjs: node register.mjs [email]. Rerun to resume; it never starts a second registration.
import { appendFileSync, existsSync, readFileSync } from "node:fs"
const API = "https://api.colter.ai/api/agent/v1"
const env = existsSync(".env") ? readFileSync(".env", "utf8") : ""
const saved = (name) => env.match(new RegExp(`^${name}=(.*)$`, "m"))?.[1]
const save = (name, value) => appendFileSync(".env", `${name}=${value}\n`, { mode: 0o600 })
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function call(method, path, { body, headers = {} } = {}) {
const res = await fetch(API + path, {
method,
headers: { "content-type": "application/json", ...headers },
body: body && JSON.stringify(body)
})
const json = await res.json().catch(() => ({}))
if (!res.ok) throw new Error(`${method} ${path}: ${res.status} ${json.error?.details?.reason ?? json.error?.code}`)
return json
}
if (saved("COLTER_TOKEN")) {
console.log("COLTER_TOKEN is already in .env.")
process.exit(0)
}
let key = saved("COLTER_REGISTRATION_KEY")
let secret = saved("COLTER_POLL_SECRET")
if (!key) {
const email = process.argv[2]
const started = await call("POST", "/registrations", {
body: {
mode: email ? "new_customer" : "link_existing",
...(email && { email }),
agent_name: "My coding agent",
agent_client: { name: "colter-prompt", version: "1" },
accept_terms_version: "2026-07-21" // only after I accept https://colter.ai/legal
}
})
key = started.registration.registration_key
secret = started.poll_secret // shown once
save("COLTER_REGISTRATION_KEY", key)
save("COLTER_POLL_SECRET", secret)
}
const headers = { "x-colter-registration-secret": secret }
let announced = false
for (;;) {
const { registration } = await call("GET", `/registrations/${key}`, { headers })
if (registration.status === "approved") break
if (["denied", "expired", "completed"].includes(registration.status))
throw new Error(`Registration ${registration.status}. Remove COLTER_REGISTRATION_KEY and COLTER_POLL_SECRET from .env to start again.`)
if (!announced) console.log("Waiting for you:", JSON.stringify(registration.pending_action))
announced = true
await sleep(5000)
}
// The credential is released exactly once.
const { credential } = await call("POST", `/registrations/${key}/token`, { headers })
save("COLTER_TOKEN", credential.token)
console.log("Credential saved to .env. Expires", credential.expires_at, "Scopes:", credential.scopes.join(", "))
```
## Buy one check
Ask me for the work to check: what my agent produced (`work_product`), the original `request` or the `criteria`, and the `evidence` behind it, each item with a `source` name. Write it to `work.json` in the shape of `example_request` in the contract (without its `idempotency_key` and `max_price_microcents`). If I have nothing ready, offer the contract's example. Then ask me to confirm the purchase at $5.00 before running `node --env-file=.env check.mjs`.
```js
// check.mjs: node --env-file=.env check.mjs. Rerun after any crash; it resumes the same purchase.
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
import { randomUUID } from "node:crypto"
const API = "https://api.colter.ai/api/agent/v1"
const auth = { authorization: `Bearer ${process.env.COLTER_TOKEN}` }
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function call(method, path, body) {
const res = await fetch(API + path, {
method,
headers: { ...auth, "content-type": "application/json" },
body: body && JSON.stringify(body)
})
const json = await res.json().catch(() => ({}))
if (res.status >= 400) throw new Error(`${method} ${path}: ${res.status} ${json.error?.details?.reason ?? json.error?.code}`)
return json
}
// Save the exact body and key before sending; a rerun resends them unchanged.
mkdirSync(".colter", { recursive: true })
const file = ".colter/purchase.json"
const purchase = existsSync(file)
? JSON.parse(readFileSync(file, "utf8"))
: {
...JSON.parse(readFileSync("work.json", "utf8")),
idempotency_key: `check-${randomUUID()}`,
max_price_microcents: 500000000, // your ceiling; 100,000,000 microcents = $1
authorize: true,
payment: { rail: "card", method: "auto" }
}
writeFileSync(file, JSON.stringify(purchase, null, 2))
const { purchase: bought } = await call("POST", "/checks", purchase)
const jobKey = bought.job_key
if (!jobKey) {
console.log("The quote needs authorizing:", JSON.stringify(bought.next_actions))
process.exit(0)
}
writeFileSync(".colter/job_key", jobKey)
// A person pays by card on Colter's page unless a saved card covers it.
let job = (await call("GET", `/jobs/${jobKey}`)).purchase
if (["awaiting_payment", "awaiting_payer"].includes(job.stage)) {
const { payment } = await call("POST", `/jobs/${jobKey}/payments`, { rail: "card", method: "auto" })
if (payment.continuation_url) console.log("Open this link to pay:", payment.continuation_url)
}
const settled = ["delivered_awaiting_review", "accepted", "rejected", "inconclusive", "completed", "failed", "canceled"]
while (!settled.includes(job.stage)) {
await sleep(5000)
job = (await call("GET", `/jobs/${jobKey}`)).purchase
console.log("stage:", job.stage)
}
const report = await fetch(`${API}/jobs/${jobKey}/report?format=markdown`, { headers: auth })
if (report.ok) writeFileSync(".colter/report.md", await report.text())
console.log(`Job ${jobKey} is ${job.stage}.`, report.ok ? "Report: .colter/report.md" : "")
```
When a payment link prints, give it to me. I pay on Colter's page; the script continues on its own once payment is collected.
## Review it with me
1. Summarize `.colter/report.md` for me: the verdict (`supported`, `revise`, `escalate`, or `insufficient_evidence`), the findings, and whether a person must review the work before it is used. An adverse verdict is a delivered check, not a failure.
2. Ask me to accept or dispute. Accept when the report evaluated every criterion and cited only supplied or retrieved sources, whatever its verdict. Dispute when it did not do what the contract promised; `reason_code` is one of check_not_performed, criteria_not_evaluated, citation_invalid, report_incomplete, wrong_input_assessed, other.
3. Send my decision with `POST https://api.colter.ai/api/agent/v1/jobs/<job_key>/review`: `{"decision": "accept"}`, or `{"decision": "dispute", "reason_code": "...", "rationale": "...", "idempotency_key": "..."}`. Review within 72 hours; silence is never acceptance.
4. Fetch `GET https://api.colter.ai/api/agent/v1/jobs/<job_key>/receipt` and save it to `.colter/receipt.json`. A receipt records payment; it does not certify the work.
## Common stuck points
| Symptom | Fix |
|---|---|
| `service_unavailable` | The check is paused or has no payment rail. Tell me the `availability_reasons`; don't retry in a loop. |
| `registrations_paused`, `registration_not_admitted`, or `registration_cohort_full` | Registration is limited right now. Stop and point me to https://colter.ai/contact. |
| Registration waits on `verify_email` | I haven't confirmed yet. Keep polling the same registration; don't start another. |
| `registration_expired` or `credential_already_issued` | Remove the registration lines from `.env` and run `register.mjs` again. |
| 401 on any call | The credential is missing, expired, or revoked. Check the script ran with `--env-file=.env`; otherwise register again. Never ask me to paste it. |
| `work_check_input_invalid` | Fix `work.json` against `input_schema` in the contract, delete `.colter/purchase.json`, and rerun. Nothing was collected. |
| `idempotency_conflict` | The key was reused with a different body. Resend `.colter/purchase.json` unchanged. A new purchase needs a new key and my OK. |
| `purchase_price_limit_exceeded` or a `grant_*_limit_exceeded` | The price is above my ceiling or grant. Tell me; don't raise limits yourself. |
| `payment.state` is `uncertain` | Resend the identical payment request. Never start a new purchase. |
| `payment_attempt_closed` or the link expired | POST the payment again for a fresh link. |
| `grant_review_not_permitted` or `customer_reviewer_required` | I review it in Colter myself. Give me the job key. |
| The script crashed or timed out mid-purchase | Rerun `check.mjs`. It resends the saved body and key, and Colter returns the same job. |
## Done
You registered me with Colter, bought one check, and reviewed its report with me.
Next, if I want it:
- Call the same `POST /checks` from my agent's code before it acts on or sends an answer, keeping one saved body and idempotency key per purchase.
- Use MCP instead of REST: add a remote HTTP MCP server at `https://api.colter.ai/mcp?profile=buyer` with `Authorization: Bearer <credential>` in the client's protected connection settings. Tools: `colter.whoami`, `colter.check_work`, `colter.purchase_status`, `colter.authorize_purchase`, `colter.pay`, `colter.cancel_payment`, `colter.get_report`, `colter.review_delivery`, `colter.get_receipt`, `colter.cancel_job`.
- Pay from a wallet with x402 (USDC) where offered: follow https://colter.ai/docs/agents#pay and sign with the wallet's own tooling. Never paste a private key here.