v1.0 — Base Sepolia Testnet

Colpero Spatial API

Query 3D scenes via HTTP. Pay per request with USDC via x402 protocol. Built for robots and autonomous agents.

9 endpoints spatial queries + NL
$0.001–$0.01 per request (USDC)
Base Sepolia settlement network
OpenUSD scene format

Overview

What is the Colpero Spatial API?

The Colpero Spatial API lets autonomous agents query 3D environments over HTTP. Scenes are stored in OpenUSD format. Each query runs real spatial computation (distances, pathfinding, area calculations) and returns structured JSON.

All paid endpoints use the x402 protocol from Coinbase for micropayments. Agents pay with USDC on Base Sepolia. No API keys, no accounts, no subscriptions. Just HTTP + payment headers.

Base URL

https://api.colpero.com    // production (coming soon)
http://localhost:3000       // local development

Response Format

All responses are application/json. Errors return standard HTTP codes with a JSON body:

{
  "error": "Object 'unknown_obj' not found in scene"
}

Available Scenes

IDDescriptionDimensions
warehouse_demo Warehouse with racks, forklifts, and loading dock 30m x 20m
office_demo Office with desks, meeting rooms, kitchen 15m x 12m

Authentication

How x402 payments work

x402 is an HTTP-native payment protocol. Instead of API keys, clients pay per request with USDC. The server returns 402 Payment Required with payment instructions. The client signs a USDC transfer and retries.

01
Request No payment header
02
402 Response Payment requirements
03
Sign Payment ERC-20 USDC transfer
04
Retry X-PAYMENT header
05
Data JSON response

Step-by-step

1. Send a request without payment. The server returns 402 Payment Required:

# Request
POST /scenes/warehouse_demo/distance HTTP/1.1
Content-Type: application/json

{ "object_a": "rack_A", "object_b": "loading_dock" }

# Response: 402 Payment Required
{
  "x402Version": 1,
  "accepts": [{
    "scheme": "exact",
    "network": "base-sepolia",
    "maxAmountRequired": "5000",
    "payTo": "0x...",
    "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
    "maxTimeoutSeconds": 300,
    "resource": "http://localhost:3000/scenes/warehouse_demo/distance"
  }]
}

2. Sign the USDC transfer using @coinbase/x402-client:

import { paymentHeaders } from "@coinbase/x402-client";

const headers = await paymentHeaders(
  wallet,                                        // viem WalletClient
  paymentRequirements,                           // from 402 response
  "http://localhost:3000/scenes/warehouse_demo/distance"
);

3. Retry with the payment header. Server verifies via facilitator and returns data:

POST /scenes/warehouse_demo/distance HTTP/1.1
Content-Type: application/json
X-PAYMENT: <base64-encoded-signed-payment>

{ "object_a": "rack_A", "object_b": "loading_dock" }

# Response: 200 OK
# X-PAYMENT-RESPONSE: <settlement-receipt>
{
  "object_a": "rack_A",
  "object_b": "loading_dock",
  "distance_meters": 21.4234,
  ...
}
Dev mode: If the server runs without PAY_TO_ADDRESS set, all endpoints are free. No payment headers needed. Use this for local development.

Network Details

ParameterValue
Networkbase-sepolia
CurrencyUSDC (ERC-20)
USDC Contract0x036CbD53842c5426634e7929541eC2318f3dCF7e
Facilitatorhttps://x402.org/facilitator
Amount unitUSDC micro-units (6 decimals). $0.001 = "1000"

Endpoints

API Reference

All endpoints accept and return JSON. Scene IDs correspond to .usda files in the scenes directory (e.g. warehouse_demo, office_demo).

GET /health FREE

Server health check and capability declaration. Use this to verify connectivity and check if payments are enabled.

curl
curl http://localhost:3000/health
response
{
  "status": "ok",
  "version": "0.1.0",
  "node_id": "default",
  "capabilities": [],
  "allowed_scenes": "all",
  "payment_enabled": false,
  "network": "base-sepolia"
}
FieldTypeDescription
statusstringAlways "ok" if server is running
node_idstringNode identifier in the network
payment_enabledbooleanWhether x402 payments are enforced
networkstring"base-sepolia" or "base"
GET /scenes FREE

List all available scenes with metadata and endpoint links.

curl
curl http://localhost:3000/scenes
response
[
  {
    "id": "warehouse_demo",
    "name": "Warehouse Demo",
    "description": "30m x 20m warehouse with racks and loading dock",
    "file": "warehouse_demo.usda",
    "endpoints": {
      "objects": "/scenes/warehouse_demo/objects",
      "distance": "/scenes/warehouse_demo/distance",
      "nearest": "/scenes/warehouse_demo/nearest",
      "area": "/scenes/warehouse_demo/area",
      "path": "/scenes/warehouse_demo/path",
      "query": "/scenes/warehouse_demo/query"
    }
  }
]
GET /nodes FREE

Returns active spatial computing nodes from the on-chain ERC-8004 registry. Filter by capability or minimum reputation score.

query parameters
ParameterTypeRequiredDescription
capabilitystringNoFilter by capability (e.g. "reconstruction")
minReputationintegerNoMinimum reputation score
curl
curl "http://localhost:3000/nodes?capability=reconstruction&minReputation=80"
response
{
  "count": 2,
  "nodes": [
    {
      "agentId": "0x1234...abcd",
      "owner": "0xabcd...1234",
      "capabilities": ["reconstruction", "pathfinding"],
      "pricing": {
        "pricePerQuery": "0.01",
        "pricePerCompute": "0.005",
        "pricePerPath": "0.008"
      },
      "endpoint": "https://node1.colpero.com",
      "reputation": 95,
      "totalSuccess": 1250,
      "totalFailure": 5,
      "active": true
    }
  ]
}
Requires REGISTRY_CONTRACT_ADDRESS to be configured. Results are cached for 60 seconds.
GET /scenes/:id/objects $0.001

List all objects in a scene with their 3D positions, scales, types, and semantic metadata.

curl
curl http://localhost:3000/scenes/warehouse_demo/objects
response
[
  {
    "name": "rack_A",
    "path": "/World/rack_A",
    "type": "rack",
    "position": { "x": 5, "y": 1.5, "z": 5 },
    "scale": { "x": 1.2, "y": 3, "z": 2.4 },
    "metadata": {
      "semantic_type": "rack",
      "label": "Storage Rack A"
    }
  },
  ...
]
POST /scenes/:id/distance $0.005

Compute Euclidean distance (meters) between two named objects in the scene.

request body
{
  "object_a": "rack_A",
  "object_b": "loading_dock"
}
curl
curl -X POST http://localhost:3000/scenes/warehouse_demo/distance \
  -H "Content-Type: application/json" \
  -d '{"object_a": "rack_A", "object_b": "loading_dock"}'
response
{
  "object_a": "rack_A",
  "object_b": "loading_dock",
  "distance_meters": 21.4234,
  "positions": {
    "a": { "x": 5, "y": 1.5, "z": 5 },
    "b": { "x": 25, "y": 0.1, "z": 10 }
  }
}
POST /scenes/:id/nearest $0.005

Find the N nearest objects to a target object, sorted by distance.

request body
{
  "target": "forklift_1",
  "count": 3
}
curl
curl -X POST http://localhost:3000/scenes/warehouse_demo/nearest \
  -H "Content-Type: application/json" \
  -d '{"target": "forklift_1", "count": 3}'
response
[
  {
    "name": "rack_A",
    "type": "rack",
    "distance_meters": 14.3212,
    "position": { "x": 5, "y": 1.5, "z": 5 },
    "metadata": { "semantic_type": "rack" }
  },
  ...
]
POST /scenes/:id/area $0.003

Calculate the floor footprint area (square meters) of a named region or zone.

request body
{
  "region": "loading_dock"
}
curl
curl -X POST http://localhost:3000/scenes/warehouse_demo/area \
  -H "Content-Type: application/json" \
  -d '{"region": "loading_dock"}'
response
{
  "region": "loading_dock",
  "area_sq_meters": 96.0,
  "dimensions": {
    "width_meters": 8,
    "length_meters": 12,
    "height_meters": 0.1
  },
  "center_position": { "x": 25, "y": 0.1, "z": 10 }
}
POST /scenes/:id/path $0.008

Compute the shortest navigable path between two objects using A* pathfinding. Returns waypoints in meters. Grid resolution: 0.5m. Agent padding: 0.4m.

request body
{
  "from": "rack_A",
  "to": "loading_dock"
}
curl
curl -X POST http://localhost:3000/scenes/warehouse_demo/path \
  -H "Content-Type: application/json" \
  -d '{"from": "rack_A", "to": "loading_dock"}'
response
{
  "from": "rack_A",
  "to": "loading_dock",
  "path_distance_meters": 28.5432,
  "waypoints": [
    { "x": 5, "y": 0.1, "z": 5 },
    { "x": 15, "y": 0.1, "z": 8 },
    { "x": 25, "y": 0.1, "z": 10 }
  ]
}
POST /scenes/:id/query $0.01

Ask a natural language question about the scene. Powered by Claude with tool use. The AI agent calls spatial tools internally to build an accurate answer.

request body
{
  "question": "Which rack is closest to forklift_1 and how far is it?"
}
curl
curl -X POST http://localhost:3000/scenes/warehouse_demo/query \
  -H "Content-Type: application/json" \
  -d '{"question": "Which rack is closest to forklift_1 and how far is it?"}'
response
{
  "question": "Which rack is closest to forklift_1 and how far is it?",
  "answer": "Rack A is the closest rack to forklift_1, at approximately 14.32 meters."
}
The NL query endpoint has a max of 5 tool-use iterations. Complex multi-step questions (e.g. "find the shortest path between the two most distant racks") will use multiple internal spatial queries to compose the answer.

Pricing Summary

EndpointMethodPrice (USDC)Micro-units
/healthGETFree0
/scenesGETFree0
/nodesGETFree0
/scenes/:id/objectsGET$0.0011000
/scenes/:id/distancePOST$0.0055000
/scenes/:id/nearestPOST$0.0055000
/scenes/:id/areaPOST$0.0033000
/scenes/:id/pathPOST$0.0088000
/scenes/:id/queryPOST$0.01010000

Quickstart

Integrate in 5 minutes

1. Install dependencies

npm install @coinbase/x402-client viem

2. Create a wallet

You need a wallet with testnet USDC on Base Sepolia. Get test USDC from the Coinbase faucet.

3. Query the API

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";
import { paymentHeaders } from "@coinbase/x402-client";

const API = "http://localhost:3000";

// Setup wallet
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const wallet = createWalletClient({
  account,
  chain: baseSepolia,
  transport: http(),
});

// Helper: make a paid request
async function paidRequest(path: string, body?: object) {
  const url = `${API}${path}`;
  const method = body ? "POST" : "GET";

  // Step 1: initial request → 402
  const initial = await fetch(url, {
    method,
    headers: { "Content-Type": "application/json" },
    body: body ? JSON.stringify(body) : undefined,
  });

  if (initial.status !== 402) return initial.json();

  // Step 2: extract payment requirements
  const requirements = await initial.json();

  // Step 3: sign payment
  const payment = await paymentHeaders(
    wallet,
    requirements.accepts[0],
    url
  );

  // Step 4: retry with payment
  const paid = await fetch(url, {
    method,
    headers: {
      "Content-Type": "application/json",
      ...payment,
    },
    body: body ? JSON.stringify(body) : undefined,
  });

  return paid.json();
}

// ── Usage examples ──

// List scenes (free)
const scenes = await fetch(`${API}/scenes`).then(r => r.json());
console.log(scenes);

// Get objects ($0.001)
const objects = await paidRequest("/scenes/warehouse_demo/objects");
console.log(`Found ${objects.length} objects`);

// Compute distance ($0.005)
const dist = await paidRequest("/scenes/warehouse_demo/distance", {
  object_a: "rack_A",
  object_b: "loading_dock",
});
console.log(`Distance: ${dist.distance_meters}m`);

// Find path ($0.008)
const path = await paidRequest("/scenes/warehouse_demo/path", {
  from: "rack_A",
  to: "loading_dock",
});
console.log(`Path: ${path.path_distance_meters}m, ${path.waypoints.length} waypoints`);

// Natural language query ($0.01)
const answer = await paidRequest("/scenes/warehouse_demo/query", {
  question: "What is the total area of the loading dock?",
});
console.log(answer.answer);

Running locally (dev mode)

# Clone and install
git clone https://github.com/colpero/colpero-spatial-api.git
cd colpero-spatial-api
npm install
pip install -r requirements.txt

# Configure (leave PAY_TO_ADDRESS empty for free mode)
cp .env.example .env

# Start server
npm run dev

# API is live at http://localhost:3000
# All endpoints are free in dev mode

Docker

docker-compose up

# API at http://localhost:3000
# Health check: http://localhost:3000/health
Testnet only. The API currently runs on Base Sepolia with testnet USDC. Get free testnet tokens from the Coinbase faucet. Mainnet deployment on Base is coming soon.