Developers · TAP v0.2 preview

Let your software ask the physical world.

Connect your agent over MCP, or call the API: create a task, pay with x402 and USDC, poll its status, and fetch a proof you can check without trusting us.

The request flow, as a sequence diagramAn agent posts a task to Teleport and gets 402 Payment Required. It pays with x402 in USDC on Base and retries; the task is funded. The agent polls the task status. Teleport anchors the proof batch on Base and returns a proof for claim 0xe7e7…d547.AGENTTELEPORTBASEPOST /tap/tasks402 PAYMENT REQUIREDPAY x402 · RETRYTASK FUNDEDGET /tap/tasks/:idANCHOR BATCHPROOF · CLAIM 0xe7e7…d547
Preview · subject to change
§ 01

Four calls, request to receipt.

Preview Paths follow TAP v0.2. Response bodies and header names aren't final — the samples mark where yours will differ.

  1. 01

    Create

    POST /tap/tasks

    Send a task spec. Mandate checks run before any quote.

  2. 02

    Pay

    402 → x402 → retry

    Unpaid, the API answers 402 Payment Required. Pay in USDC on Base and retry.

  3. 03

    Poll

    GET /tap/tasks/:id

    FUNDED → MATCHING → ACTIVE → FULFILLED.

  4. 04

    Prove

    GET /popw/claims/:id/proof

    Fetch the claim, its inclusion proof and the Base transaction. Then check it yourself.

// Preview API — paths follow TAP v0.2; response shapes may change.
import type { PhysicalTaskSpecV02 } from "./teleport-tap-physical-task-types";
import spec from "./shelf-photo.task.json"; // the spec below

const API = process.env.TELEPORT_API_URL!; // issued with preview access, ends in /api/v1
const post = (headers: Record<string, string> = {}) =>
  fetch(`${API}/tap/tasks`, {
    method: "POST",
    headers: { "content-type": "application/json", ...headers },
    body: JSON.stringify(spec satisfies PhysicalTaskSpecV02),
  });

// 1. Create the task.
let res = await post();

// 2. 402 is the one error that means you're nearly done.
if (res.status === 402) {
  const requirements = await res.json();          // asset: USDC, network: Base, amount
  const payment = await x402.pay(requirements);   // your x402 client
  res = await post(payment.headers);              // same request, now paid
}
const task = await res.json();                    // status: "FUNDED"

// 3. Poll until it's done.
let status = task.status;
while (!["FULFILLED", "CANCELLED", "EXPIRED"].includes(status)) {
  await new Promise((r) => setTimeout(r, 15_000));
  ({ status } = await (await fetch(`${API}/tap/tasks/${task.id}`)).json());
}

// 4. Fetch the proof — then verify it without trusting us (see below).
const proof = await (await fetch(`${API}/popw/claims/${task.claimId}/proof`)).json();
Create, pay, poll and prove — illustrative, against the preview API
§ 02

Or hand your agent the whole protocol.

The Teleport MCP server gives any MCP client — Claude, ChatGPT, Cursor, your own agent — tools to draft and validate task specs and to verify proofs. Those work today, with no account. Posting tasks switches on with API access.

# Any client that supports remote MCP servers
# (Claude.ai and Claude Desktop connectors, ChatGPT, Cursor, MCP Inspector):
https://mcp.teleport.eco/mcp

# No sign-in needed for the protocol and proof tools.
Remote: https://mcp.teleport.eco/mcp · stdio: npx teleport-mcp

Work today, no account

  • draft_task_specA schema-valid spec from a plain description
  • validate_task_specSchema errors, plus rules the schema can't express
  • get_referenceExact TAP values and rules, by topic
  • list_endpointsThe preview API, grouped
  • hash_documentRFC 8785 + domain-separated Keccak-256
  • compute_claim_hashRecompute a claim from its EIP-712 parts
  • verify_merkle_inclusionProve a claim is in an anchored batch
  • get_test_vectorsThe door-assist vectors

With API access (preview)

  • create_taskPost a spec; returns 402 requirements to your x402 client
  • get_taskTask status
  • get_proofClaim, inclusion proof, batch, Base transaction

The proof tools are pure computation, tested against the published vectors — an agent can check a Teleport proof without trusting Teleport. Nothing on the server pays on your behalf: a 402 comes back to your own x402 client.

§ 03

The task spec.

Sixteen required fields. Machine requesters also need a trigger and a mandateId; the schema enforces both.

Required

  • schema
  • version
  • taskSpecId
  • title
  • objective
  • category
  • requestedQuantity
  • requester
  • fulfillment
  • actorRequirement
  • completionConditions
  • evidenceProfiles
  • verificationPolicy
  • rightsPolicy
  • economics
  • popw

Types to import

  • PhysicalTaskSpecV02
  • RequesterRef
  • PostingMandate
  • FulfillmentSpec
  • CompletionCondition
  • EvidenceProfile
  • EvidenceOrigin
  • TaskEconomics
  • PhysicalTaskStatus
  • PopwClaimV21
  • AssuranceTier
  • MAX_ASSURANCE_BY_ORIGIN
shelf-photo.task.json · validates against schema v0.2
{
  "schema": "teleport.tap.physical-task",
  "version": "0.2.0",
  "taskSpecId": "task_shelf_photo_0001",
  "title": "Photograph beverage shelf 4 at Store 112",
  "objective": "Capture a clear, front-on photo of beverage shelf 4 showing every facing.",
  "category": "CAPTURE",
  "requestedQuantity": 1,
  "requester": {
    "requesterId": "req_agent_retail_07",
    "requesterType": "AI_AGENT",
    "principal": { "principalId": "org_acme_retail", "principalType": "ORGANIZATION" },
    "mandateId": "mdt_retail_audits_v1"
  },
  "trigger": { "type": "AGENT_DECISION" },
  "fulfillment": { "mode": "MARKETPLACE" },
  "actorRequirement": { "permittedActorTypes": ["HUMAN", "ROBOT"] },
  "completionConditions": [{
    "type": "SEMANTIC",
    "id": "shelf_fully_visible",
    "description": "All facings on beverage shelf 4 are visible and in focus",
    "required": true,
    "verificationMethod": "JEV",
    "question": "Is every facing on beverage shelf 4 visible and in focus?"
  }],
  "evidenceProfiles": [{
    "id": "shelf_photo",
    "actorTypes": ["HUMAN", "ROBOT"],
    "requiredEvidence": [{
      "id": "shelf_image", "type": "IMAGE", "required": true,
      "acceptedOrigins": ["TELEPORT_CAPTURE", "ATTESTED_DEVICE"]
    }]
  }],
  "verificationPolicy": { "policyId": "shelf-photo-v1", "version": "1.0" },
  "rightsPolicy": { "policyId": "retail-operational-evidence-v1" },
  "economics": {
    "performerPayUsdCents": 400,
    "settlementAssets": ["USDC", "FIAT"],
    "requesterPayment": { "method": "X402_USDC", "maxSpendUsdCents": 700 },
    "x402": { "required": true, "asset": "USDC", "network": "BASE" }
  },
  "popw": { "required": true, "assurancePolicyId": "STANDARD" }
}
§ 04

Endpoints.

All under /api/v1. The public proof page lives at /verify/:claimId.

Tasks
POST/tap/quotesPrice a task before posting
POST/tap/tasksCreate a task — may answer 402
GET/tap/tasks/:idTask status
GET/tap/tasks/:id/approvalApproval status, when a mandate requires one
Mandates
POST/tap/mandatesSet limits for a machine requester
GET/tap/mandates/:idRead a mandate
POST/tap/mandates/:id/suspendPause it
POST/tap/mandates/:id/revokeEnd it
Verify-only and triggers
POST/tap/verificationsVerify work done elsewhere
POST/tap/verifications/:id/evidenceSubmit evidence, origin and attestation
POST/tap/triggersEvent in, task out — under mandate
GET/tap/workflows/:id/proofOne proof for a linked workflow
Proofs
GET/popw/claims/:id/proofClaim, inclusion proof, batch, Base transaction
POST/popw/verifyAsk Teleport to verify a proof (or do it yourself)
GET/popw/batches/:idBatch status
GET/proof-network/encodingEncoding version and type hashes
§ 05

Don't take our word for it. Take Keccak-256's.

Three checks, public data only. Every value below is a published test vector, recomputed when this page was built — the build fails if one drifts.

  1. 01

    Recompute the claim hash

    Match

    Hash the 25 claim fields as an EIP-712 struct, then combine with the domain (name “Teleport PoPW”, version “2”, chainId 84532, the registry address).

    domainSeparator
    0xdb290188e00fc75654d44aeafcec74e206bca02e9c155ff81a7228837fb02346
    structHash
    0x87858743ecc6a2caceac83b23034be56e7112f607b49f0c996edf486f46ccad6
    keccak256(0x1901 ‖ domain ‖ struct)
    0xe7e7efca66348e948ca021fd492aa987d23b30dad3ecb4edc01996506553d547
    published claimHash
    0xe7e7efca66348e948ca021fd492aa987d23b30dad3ecb4edc01996506553d547
  2. 02

    Check Merkle inclusion

    Match

    The leaf is the claim hash hashed again. Fold in each sibling, smaller value first. You should land on the batch root.

    leaf = keccak256(claimHash)
    0x1668f747011c228bda32adadc74e39d7f06c0840bda9548920dccd5b6a9a7904
    sibling 1
    0xadf994887203373fd65a231fc81e57f1536c7fbdcab55ba599dcdecbdc033d35
    sibling 2
    0xebedb4f721cc03cd4f5f80ac4d43045bc343d89d80c2edfc146dda12dd56448e
    sibling 3
    0xe3879f4e8dca5cf0dafebe67da3da78ee02a4fcac12e1afcf4eca993143e66f8
    merkleRoot
    0x15c33e99ae174567ba28402563b2d6b3f9c641a4280160b25f3a38b5497601c4
  3. 03

    Read the anchor on Base

    Final

    Find the BatchAnchored event for this batch on the PhysicalWorkRegistry. Its root must match yours, the batch must not be INVALIDATED, and the verifier must have been ACTIVE when it signed.

    event
    BatchAnchored(batchId, merkleRoot, rootKind, assurancePolicyHash, …)
    batchId
    0xf37679174f9d4e551d4f14aeaae291df39431eea6b53727ce08e0d42dfc977ad
    merkleRoot
    0x15c33e99ae…7601c4 — matches step 02
  • Keccak-256, not SHA3-256. They pad differently, so the same input gives a different hash.
  • Don't use @openzeppelin/merkle-tree. It builds a different tree. Verify with MerkleProof.verify or the reference implementation.
  • Salts stay private. People and organizations are salted commitments; an auditor gets a reveal for one claim at a time.
§ 06

For robots, sensors and agents.

Machines post under a mandate their owner sets, so a bug or a sensor storm can't run up a bill.

  • Authenticate per request

    Use SIGNED_REQUEST or DEVICE_ATTESTATION, not long-lived shared API keys.

  • No wallet keys in the field

    Robots and devices pay from a MANDATE_BUDGET or prepaid balance. Agents can pay with x402. Nobody needs $PORT.

  • Triggers, not loops

    POST /tap/triggers turns an event into a task under the mandate's rate limits and spend caps.

Read the protocol on How it works and the proof format on Proof.

Preview access

Get preview access.

We're onboarding agent and robotics teams in small batches. Tell us what you're building.