Procurement · Operations

Recover from facts, not assumptions.

Telaro reports financial state separately from transport errors so callers can retry without double-funding or prematurely releasing a reservation.

The field that determines your next action

no_authorization

No durable spend authorization or reservation exists.

Correct input or policy, then retry with the same idempotency key.
reserved

Budget is held, but funding is not yet confirmed.

Read the execution; let reconciliation resume the planned operation.
payment_unknown

A money-moving response was lost or chain state is uncertain.

Do not create a replacement. Read state and retry the same operation/key.
funded

The sACP job is funded and the provider can work.

Wait for provider submission, then sync it.
settled

Acceptance and budget consumption are confirmed.

Fetch and retain the receipt.
recovered

Reserved or transferred value has been reconciled back.

Fetch the final receipt/audit record before starting a new run.

Dispute bad work; reclaim missed deadlines

TypeScript
const disputed = await telaro.procurement.disputeSacp(
  verified.id,
  {
    reason: "Deterministic acceptance failed.",
    evidenceUri: "ipfs://bafy-encrypted-evidence",
  },
  { idempotencyKey: persistedJob.disputeKey },
);

// After the bound evaluator publishes a verdict:
const terminal = await telaro.procurement.syncSacpVerdict(disputed.id, {
  idempotencyKey: persistedJob.verdictSyncKey,
});

// If no provider submission arrived before submitDeadline:
const recovered = await telaro.procurement.reclaimSacp(funded.id, {
  idempotencyKey: persistedJob.reclaimKey,
});

A provider-winning verdict consumes the reservation. A client-winning verdict or deadline reclaim releases it. Budget mutation and the single terminal receipt commit in the same transaction.

One business intent, one stable key

Generate an idempotency key when the user or automation creates the intent. Persist it with your job and reuse it for retries of that exact mutation. Generate a new key only for a new intent.

TypeScript
import { TelaroProcurementError } from "@telaro/sdk/procurement";

const executeKey = persistedJob.executeIdempotencyKey;

try {
  await telaro.procurement.executeSacp(execution.id, {
    idempotencyKey: executeKey,
  });
} catch (error) {
  if (error instanceof TelaroProcurementError) {
    console.log(error.financialState, error.retryable, error.nextAction);
  }
}

When the response is unknown

  1. 1
    Stop replacement attempts.

    Do not create another execution or release the reservation.

  2. 2
    Read authoritative state.

    Call getExecution(execution.id) or get(runId).

  3. 3
    Retry the same intent.

    Use the same operation and idempotency key. Adapters observe before signing.

  4. 4
    Allow reconciliation to converge.

    The worker leases pending operations and confirms chain facts without duplicate signing.

  5. 5
    Escalate with identifiers.

    Keep request ID, run ID, execution ID, request ID header, and transaction signature.

Environment checklist

  • API URL and organization session point to the same environment.
  • Request cluster, RPC, token mint, and signer network match.
  • Buyer signer is available only to the procurement service.
  • Provider signer is available only to the provider submission process.
  • Deterministic verification is configured server-side before using that acceptance method.
  • New spend remains disabled until migrations, health checks, and read-only reconciliation checks pass.
  • Logs retain request/run/execution IDs but exclude access tokens and confidential payloads.