DOCS / JOBS
Jobs: one intent, every step guarded
A job is a compound intent — “bridge, then deposit, then long, then protect it” — compiled into a step plan the runner executes with you: it builds and guard-checks each transaction only when it’s offered, your wallet signs, and settlement waits are verified server-side between signatures. External agents get the same rails through one endpoint: POST /api/jobs.
Try it for $0 right now
dryRun compiles your ask and builds + guard-checks step 1 against live venues — real quotes, real balances, real refusals — but creates nothing, signs nothing, and costs nothing. It’s the test mode and the docs playground:
curl -s https://www.yeetful.com/api/jobs \
-H "authorization: Bearer $YF_API_KEY" \
-H "content-type: application/json" \
-d '{
"ask": "swap 5 usdc from base to arbitrum, then deposit 4 usdc to hyperliquid, then long $12 of eth on hyperliquid, then protect my eth long with a 5% stop",
"dryRun": true
}'Mint the yf_ key at /dashboard/keys — or skip the key entirely and run the repo’s demo script, which can also authenticate as your wallet via SIWE:
npx tsx scripts/jobs-api-demo.ts # dryRun against prod npx tsx scripts/jobs-api-demo.ts --live # actually creates the job
What comes back
Real output (a funded test wallet, live NEAR Intents quote — trimmed for width). Note what’s in it: the compiled plan, and step 1 as an actual transaction with its guard report and priced value — not a description of one.
{
"dryRun": true,
"title": "Bridge 5 USDC (base) → USDC (arbitrum) → Deposit 4 USDC to
Hyperliquid → Long $12 of ETH on Hyperliquid → Arm stop-loss on ETH (5%)",
"steps": [
{ "seq": 0, "kind": "sign", "builder": "native-cross-chain", "title": "Bridge 5 USDC …" },
{ "seq": 1, "kind": "wait", "builder": "wait", "waitPredicate": { "kind": "oneclick" } },
{ "seq": 2, "kind": "sign", "builder": "native-hl-exec", "title": "Deposit 4 USDC …" },
{ "seq": 3, "kind": "wait", "builder": "wait", "waitPredicate": { "kind": "hl-credit" } },
{ "seq": 4, "kind": "sign", "builder": "native-hl-exec", "title": "Long $12 of ETH …" },
{ "seq": 5, "kind": "auto", "builder": "native-hl-guardian", "title": "Arm stop-loss …" }
],
"firstSignPreview": {
"step": 0,
"artifact": {
"txRequest": { "to": "0x833589…2913", "data": "0xa9059cbb…", "chainId": 8453 },
"summary": "Send 5.0 USDC on Base to NEAR Intents deposit address 0xA046…917E —
solvers then deliver ~4.99 USDC on Arbitrum (ETA ~34s)"
},
"guardReport": { "ok": true, "warnings": [] },
"valueUsd": 5
},
"note": "Nothing was created or signed — re-POST without dryRun to run it."
}If the build can’t clear its guards, you get the reason instead of the artifact — same shape, refused instead of artifact. A real one: “Wallet holds only 2.52 USDC on Arbitrum — bridge funds there first (cross-chain swap).” The layer refuses honestly; it never guesses.
Step kinds
| Kind | Who acts | What happens |
|---|---|---|
sign | Your wallet | Built + guard-checked at offer time (fresh quotes, current balances), then offered for signature. Artifacts expire; stale ones are rebuilt, not reused. |
wait | The runner | Settlement verification — solver fill, Hyperliquid credit — polled server-side. Waits verify; they don’t trust the previous step’s word. |
auto | The runner | Server-side under an existing consent — e.g. arming a Guardian stop once the position exists. |
dryRun vs live
dryRun: true | dryRun: false | |
|---|---|---|
| Compile + plan preview | ✓ | ✓ |
| Step 1 built + guarded live | ✓ | ✓ |
| Rows created | none | the job + its steps |
| Can be signed | no | step by step, from the chat JobCard or your own UI |
| Cost | $0 | whatever you sign — and only that |
Auth, and the rest of the surface
- Two auth paths, full parity: a SIWE session (the browser) or
Authorization: Bearer yf_…(a headless agent). Same compile, same builds, same list atGET /api/jobs. - Watch a job:
GET /api/jobs/:idreturns the job + steps with artifacts. Replies that compile a job also carry a per-job capability token — it’s how the embedded chat’s JobCard follows a job without a session, scoped to exactly that job. - Cancel:
DELETE /api/jobs/:id. Unfilled swaps auto-refund; waits time out closed, never open. - Bad asks refuse honestly: a single-step ask belongs to the native layer(400 tells you so), and a compound ask with an uncompilable segment names the exact step it couldn’t build instead of improvising one.
Where jobs show up
The same compiler answers everywhere: the first-party chat, the embed on your site, and this API. A user typing the ask above gets a JobCard with a sign button per step; your agent POSTing it gets the same steps as JSON. Signed value lands in your dashboard either way — the receipt is the product.