Skip to content

Quickstart

This walks you through recording one supply-chain event against the Tracium sandbox API. It uses the prepared transaction pattern: the server validates and prepares an unsigned transaction, the client signs locally and submits to the chain RPC, then optionally registers the txHash with Tracium so the platform tracks confirmation.

Sandbox access required

You need a Darwin sandbox tenant to follow this end-to-end. Sandbox is free, no credit card.

Request sandbox →
  • Operator credentials and the sandbox base URL (from your provisioning email). Contact the team at tech@darwinevolution.io if you need access.

  • curl installed (or any HTTP client).

  • A client-side wallet / signer (ethers.js, viem, MetaMask, etc.) to sign the prepared transaction and submit it to the RPC.

  • Set BASE_URL to the API base URL provided in your provisioning email:

    Ventana de terminal
    export BASE_URL="<API_BASE_URL>"
  1. Login with the operator credentials from your provisioning email:

    Ventana de terminal
    curl -X POST "$BASE_URL/api/v2/auth/login" \
    -H "Content-Type: application/json" \
    -d '{
    "email": "operator@sandbox.example.com",
    "password": "your-sandbox-password"
    }'

    The response includes accessToken + refreshToken. If your account is scoped to a single tenant, the accessToken is ready to use. If you belong to multiple tenants, the token comes partial: true and you need POST /api/v2/auth/select-tenant to promote it:

    Ventana de terminal
    curl -X POST "$BASE_URL/api/v2/auth/select-tenant" \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "tenantId": "<your-sandbox-tenant-id>" }'
    Ventana de terminal
    export TOKEN="<accessToken>"
  2. Before preparing the transaction, validate the event against the tenant’s process map. This catches schema errors and missing fields without spending gas.

    Ventana de terminal
    curl -X POST "$BASE_URL/api/v1/events/validate" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
    "processType": "RICE_HARVESTING",
    "outputTlc": "TLC-DEMO-001",
    "outputCustodian": "0xYourSandboxOperatorAddress",
    "metadata": {
    "product": "Organic Koshihikari Rice",
    "location": { "lat": 37.5, "lng": 139.9 },
    "quantity": { "value": 500, "unit": "kg" },
    "timestamp": "2026-05-08T08:00:00Z"
    }
    }'

    Successful response:

    { "valid": true, "errors": [], "warnings": [] }

    Note the field names:

    • processType: process map key. Each sandbox has different processes by demo: the food sandbox uses organic-sushi-co, the automotive sandbox uses automotive-parts-mx-tier2, the textiles sandbox uses textiles-cooperative-latam. Your provisioning email lists the valid processType values for your tenant.
    • outputTlc: TLC of the lot to mint (string).
    • outputCustodian: EIP-55 wallet address of the destination custodian.
    • inputTokenIds: optional array of tokenIds (numbers) if this event consumes existing lots (transformation).
    • metadata: free-form object validated against the process map’s schema.
  3. Ventana de terminal
    curl -X POST "$BASE_URL/api/v1/events/prepare" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
    "processType": "RICE_HARVESTING",
    "outputTlc": "TLC-DEMO-001",
    "outputCustodian": "0xYourSandboxOperatorAddress",
    "metadata": {
    "product": "Organic Koshihikari Rice",
    "location": { "lat": 37.5, "lng": 139.9 },
    "quantity": { "value": 500, "unit": "kg" },
    "timestamp": "2026-05-08T08:00:00Z"
    }
    }'

    Response:

    {
    "eventId": "evt_abc123",
    "ipfsCid": "bafybeig...",
    "preparedTx": {
    "to": "0xContractAddress",
    "data": "0x...",
    "gasEstimate": 250000,
    "chainId": 1337
    }
    }

    At this point: server validated the payload, wrote it to IPFS (returned the CID), and prepared the unsigned transaction. Nothing is on-chain yet. The actor’s private key never touched the platform.

  4. This part is client-side. Take preparedTx.to + preparedTx.data

    • gasEstimate + chainId and send the transaction using your signer. Example with ethers.js:
    import { ethers } from 'ethers';
    const wallet = new ethers.Wallet(process.env.OPERATOR_PRIV_KEY, provider);
    const tx = await wallet.sendTransaction({
    to: prepared.preparedTx.to,
    data: prepared.preparedTx.data,
    gasLimit: prepared.preparedTx.gasEstimate,
    });
    const receipt = await tx.wait();
    console.log('on-chain', receipt.hash, receipt.blockNumber);

    The sandbox RPC URL is the one provisioned in your onboarding email.

  5. (Optional) Register the txHash with Tracium

    Section titled “(Optional) Register the txHash with Tracium”

    So Tracium tracks confirmation + emits event.recorded webhooks when the block is mined:

    Ventana de terminal
    curl -X POST "$BASE_URL/api/v1/tx/track" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "txHash": "0xa1b2c3..." }'

    And query status:

    Ventana de terminal
    curl -X POST "$BASE_URL/api/v1/tx/track/status" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "txHash": "0xa1b2c3..." }'
  6. Once confirmed, read the minted NFT:

    Ventana de terminal
    curl "$BASE_URL/api/v1/nfts/tlc/TLC-DEMO-001" \
    -H "Authorization: Bearer $TOKEN"

    The response includes NFT fields (tokenId, tlc, status, custodian, metadataCid, metadata, txHash, blockNumber, eventCount, createdAt, …).

    To see lineage:

    Ventana de terminal
    curl "$BASE_URL/api/v1/nfts/<tokenId>/ancestry" \
    -H "Authorization: Bearer $TOKEN"

You created a Critical Tracking Event for an FSMA 204 designated food (rice). Tracium:

  1. Validated the payload against the tenant’s process map.
  2. Wrote the canonical event JSON to IPFS (off-chain, addressable by CID).
  3. Prepared an unsigned blockchain transaction with the event hash.
  4. You signed and submitted to the chain RPC (the private key never touched the platform).
  5. Optionally you registered the txHash so Tracium tracks confirmation + emits webhooks.
  6. Returned the lot NFT, queryable by TLC.

The same TLC will now travel through the chain. When you record a processing event (milling, packing), Tracium links it as a child of this NFT via inputTokenIds. By the time the rice ships, the full lineage is on-chain with cryptographic proof at every step.