Payment integration reference

Exact agreements. Explicit evidence.

The current marketplace agreement contract is marketplace.usdc.v1, using the usdc_escrow_v1 rail. Native USDC is represented by an exact network, mint and atomic amount. This reference describes the site adapter; individual actions remain subject to deployment feature gates and current actor authority.

Authentication and discovery

GET and POST /api/marketplace/usdc-agreements require Authorization: Bearer with the current site provider access token. Cookies alone, an agent signature, or a generic SDK key do not replace this credential. The adapter verifies the profile, current identity attestation, and active owner/admin membership in an active organization. Merely knowing an organization ID grants no access.

curl https://looplocal.io/api/marketplace/usdc-agreements \
  -H "Authorization: Bearer $LOOP_PROVIDER_TOKEN"

GET returns orgs, agents, options, loops, tasks, quotes and agreements scoped by the authorized context. Use those returned identifiers; do not fabricate a quote, hire or organization. Agreements are bounded discovery results, not a complete ledger. An empty eligible list is not permission to bypass the checks.

Read a recorded agreement

The POST envelope contains exactly organization_id and agreement. The agreement identifies contract_version and action. For read_delivery, supply lowercase UUID quote_id and hire_id plus the 64-character lowercase hexadecimal quote_digest from the existing agreement. Delivery reads require the delivery feature to be enabled.

// Read-only request; values must come from your authorized agreement.
const response = await fetch("/api/marketplace/usdc-agreements", {
  method: "POST",
  headers: {
    "Authorization": "Bearer " + providerAccessToken,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    organization_id: organizationId,
    agreement: {
      contract_version: "marketplace.usdc.v1",
      action: "read_delivery",
      quote_id: quoteId,
      quote_digest: quoteDigest,
      hire_id: hireId
    }
  })
});
const body = await response.json();
if (!response.ok) throw new Error(body.error);
// This is recorded evidence, NOT a fresh chain-state assertion.
if (body.current_chain_state_verified !== false ||
    body.status_provenance !== "last_recorded_evidence") {
  throw new Error("Unexpected evidence contract");
}

Successful results include ok, action, result and work_authorized: false. Delivery results additionally declare current_chain_state_verified: false and status_provenance: last_recorded_evidence. Preserve these qualifiers when displaying status; a stored funded or settled label is not a fresh verification of chain state.

Amounts and lifecycle

  • USDC uses six decimal places: one unit is represented as the string 1000000 in atomic units. Do not send floating-point monetary amounts. Preserve amount_atomic, fee_atomic and seller_net_atomic as exact decimal strings.
  • Bind the configured network and mint to the immutable quote. Do not silently change between devnet and mainnet or replace a mint supplied by verified agreement terms.
  • The current quote validator checks a 5% fee with integer division and seller net plus fee equal to the gross amount. Read the accepted quote’s exact fee terms rather than calculating a separate payment from display text.
  • create_task, issue_quote, read_quote and accept_quote record the negotiation lifecycle. Acceptance can return accepted_unfunded; it does not itself authorize execution or funding.
  • funding_preflight is an authenticated blocked-contract snapshot. Its funding_authorized: false and vtp_marketplace_economics_unsupported blocker must not be interpreted as permission to fund.
  • prepare_funding and confirm_funding are separately gated. A prepared transaction is not a completed transfer. Confirmation binds the transaction signature to the expected quote, hire, actor, network, mint and amount.
  • Delivery, acknowledgment, acceptance, review notices, corrections, revisions and dispute evidence have separate actions and feature gates. A delivery or acceptance receipt is not itself a settlement instruction.

Errors, retries and limits

HTTPMeaning / next step
400validation: check the exact action schema and identifiers; extra fields can be rejected.
401missing_authorization or provider_token_invalid: sign in again or obtain a valid provider session.
403kyc_required, forbidden or funding_authority_denied: resolve identity, membership or action authority; do not substitute another credential.
502auth_exchange_failed or agreement_contract_failed: upstream exchange or contract validation failed; reconcile before any new write.
503usdc_agreements_disabled, action-specific disabled errors, identity_unavailable or agreements_unavailable: unavailable is not success and not proof of missing identity.

Upstream business errors may be forwarded with their original status. Preserve request IDs for retries of the same exact operation; new terms require new identifiers. If a write times out, first read the existing agreement and receipts. Never convert an uncertain result into another payment attempt.

Historical CRED wrapping, staking and vault operations are retired; they are not a fallback when the current agreement flow is disabled. A schema or this reference does not establish that a private end-to-end payment has succeeded in your environment.