Canonical submission and original-command recovery
Use POST /v1/quotes, then POST /v1/tasks with productId, the approved input, the quoted expectedPricingVersion, and the canonical Idempotency-Key. The host creates a key once for explicitly approved new work, using new_command_key() from the bundled REST engine, and persists it with the approved input before submission. Keys have the form v1.<13-digit Unix milliseconds>.<22–64 base64url characters>. Do not generate keys in model arguments or a workflow retry expression.
Creation requires allow_write=True, the persisted request_key, and explicit command_mode="new". The default command_mode="recover" performs an original-command GET and never obtains another quote or submits again. Repeated invocation in the same new-intent toolset also reads the original after its first submission attempt. Changed input is refused. After a restart or any lost response, use this host-only path; it needs no input, quote or model call:
import os
from truefetch_rest import recover_command, observed_task_id
original = recover_command(
os.environ["TRUEFETCH_API_KEY"], "tasks.create", os.environ["TRUEFETCH_COMMAND_KEY"]
)
if original["receipt"]["outcome"] == "accepted":
saved_task_id = observed_task_id(original)
# Persist the reference before reading the existing task/results.
HTTP 200 is not acceptance. Inspect receipt.outcome: accepted supplies an authoritative task reference even when the current task projection is null; processing and unknown require another explicit original GET, respecting the returned retry interval. rejected and not_accepted_final establish nonacceptance and require deliberate new work if you still want a collection. receipt_expired remains unconfirmed: inspect Tasks or contact support. The helper never seals, replays a POST or creates a replacement key. The server accepts new keys for 24 hours, allows five minutes of future clock skew, and retains terminal receipts for at least seven days; it can still answer a retained original after the new-command window ends. A current Task state does not establish a particular command’s outcome.
Cancellation is a separate command: bind a different persisted canonical cancel_key for the newly created task, or pass cancel_task_ids=(saved_task_id,) and cancel_command_keys={saved_task_id: saved_cancel_key} for an explicitly approved saved target. POST /v1/tasks/{taskId}/cancel sends {} and that cancellation key. Unknown cancellation is recovered with recover_command(api_key, "tasks.cancel", saved_cancel_key), never the creation key. Acceptance of cancellation does not promise the task ended as cancelled. The budget, keys and cancellation mapping remain host-only arguments.
Native tools for one collection intent
Preview: Python 3.12 and crewai==1.15.22. Real-model and live-account acceptance are pending. This REST example uses native BaseTool objects and does not require MCP to be open.
Dependency security: the pinned CrewAI tree includes ChromaDB with unresolved code execution and authorization advisories. Keep this preview in an isolated development environment with memory and knowledge integrations disabled. Review the dependency risks and usage boundaries before installation or production use.
Download these files into the same directory:
- CrewAI adapter
- Bounded single-agent workflow
- Shared REST engine
- Pinned requirements
- Complete workflow and recovery instructions
Your application supplies the API key, credit budget and one persisted request key. Default tools are read-only: usage, estimates, task/results reads and listing. Enabling writes adds budget-checked collection and scoped cancellation. Creating a task can incur charges; the application budget is per collection, not a monthly limit.
The tools decline cached results. Disable caching on the Agent and Crew too, so a previous estimate or queued status cannot stand in for a fresh read. Review telemetry and provider settings before handling customer data. Keep credentials out of prompts and source text out of control decisions.
Recover saved task IDs with the deterministic recovery function. It reads every page, verifies order/count and retains partial status; it does not start another collection. A timeout or lost response does not prove the remote task stopped. Retain the original key and input when acceptance is uncertain.
The included single-Agent Crew disables caching and delegation, limits iterations and tool calls, and preserves observed task IDs on failure. Native SDK tests use a scripted model; real-model tool selection remains unverified. Timeouts cannot forcibly stop in-flight requests. This example is not a marketplace listing or a claim of live-model support. See the Job Search API, pricing and API conventions.
The shared REST reader requires UTF-8 JSON and rejects nonfinite numbers, including numeric overflow. Interrupted or oversized HTTP error bodies keep a redacted HTTP-status diagnostic, and truncated successful transfers fail without returning data. It also rejects duplicate member names within an object, including names written with equivalent Unicode escapes; repeated names in separate records are allowed. Recovery also rejects nonfinite values from tool output instead of marking the export complete. Preserve the saved task ID and original request key after an error; these checks do not create or retry collection.
For each available result page, the reader checks the task again after receiving the page, including the final page. This adds one read-only task GET per page. Changed identity, status, availability or count, or a failed recheck, prevents a complete export. The check is a point-in-time observation; files can expire or become unavailable afterward.
Before collection, the creation tool checks that the estimate matches the requested input and that reserved billing units equal the record limit multiplied by the unit price. Amounts must be positive ASCII integers, and the reservation must fit the host credit budget. Invalid estimates stop before submission; server-side pricing and budget checks still apply.