cd /news/ai-agents/how-an-ai-agent-discovers-a-3pl-over… · home › topics › ai-agents › article
[ARTICLE · art-166571] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

How an AI agent discovers a 3PL over x402

Nettrux has published a machine-readable x402 discovery pointer at its .well-known endpoint, making it the first 3PL to expose freight-booking discovery to AI agents over HTTP. The live document points agents to an agent guide and a 126-path OpenAPI spec on the freight API host, but its resources array is empty and three deploy gates — discovery publishing, real-money settlement, and guest checkout — remain false, so no public pay-and-book endpoint exists yet. Nettrux says it has settled a real x402 USDC payment on Base in testing, which it distinguishes from a live public rail.

by read6 min views1 publishedNov 9, 2026

Agent builders keep asking the same first question: where does my agent look?

Nettrux is the first 3PL on x402, so the answer is deliberately boring and HTTP-native. Before any quote, before any payment header, an agent should fetch three public documents:

https://www.nettrux.ai/.well-known/x402 https://www.nettrux.ai/agents https://nettrux-edge.fly.dev/openapi.json This article is a how-to. Every snippet below was run against the live URLs on Nov 9, 2026 (America/Los_Angeles). The outputs are real. The gates are still off — and we say that in the same breath as the discovery story.

You will get: a machine-readable pointer, an agent guide, a 126-path OpenAPI for the freight API host, and a clear list of deploy gates.

You will not get: a live public pay-and-book endpoint, a populated resources array, public real-money settlement, or guest checkout. Those three switches are baked false:

EDGE_X402_DISCOVERY_PUBLISHED: false X402_REAL_MONEY_SETTLEMENT_LIVE: false GUEST_X402_CHECKOUT_ENABLED: false Nettrux has settled a real x402 USDC payment on Base in testing. That is not the same as a public endpoint. Keep reading if you are wiring discovery into an agent today; stop if you expected a stranger wallet to book a truck without a human and a bearer token.

x402 discovery starts at /.well-known/x402 on the site an agent already trusts. On Nettrux that document is a pointer, not a payable catalog.

import json
import urllib.request

DISCOVERY = "https://www.nettrux.ai/.well-known/x402"

req = urllib.request.Request(
    DISCOVERY,
    headers={
        "User-Agent": "nettrux-discovery-howto/1.0",
        "Accept": "application/json",
    },
)
with urllib.request.urlopen(req, timeout=20) as r:
    doc = json.load(r)

print(doc["name"], doc["kind"], doc["x402Version"])
print("resourceHost:", doc["resourceHost"])
print("openapi:", doc["openapi"])
print("resources:", doc["resources"])
print("gates:", doc["gates"])
print("payment.claimed:", doc["payment"]["claimed"])

Live output from that run:

Nettrux resource-server 1
resourceHost: https://nettrux-edge.fly.dev
openapi: https://nettrux-edge.fly.dev/openapi.json
resources: []
gates: {
  "EDGE_X402_DISCOVERY_PUBLISHED": false,
  "GUEST_X402_CHECKOUT_ENABLED": false,
  "X402_REAL_MONEY_SETTLEMENT_LIVE": false
}
payment.claimed: False

Read that carefully:

resources is payment.claimed is resourceHost and openapi tell the agent where the freight API lives.gates are the same three booleans as llms.txt and the agent guide. The pointer also lists a helper array, x402Resources, that names the documented commit route on the freight API host. That entry is catalog metadata for builders. It is not a claim that the public rail settles money today:

for res in doc.get("x402Resources") or []:
    print(res["method"], res["url"])
    print(res["description"][:160], "...")

Live output:

POST https://nettrux-edge.fly.dev/v1/immediate-bookings/commit
Bearer plus {quote_id}. The OpenAPI summary documents an x402 v1 402 challenge
when X-PAYMENT is absent, and verify, then settle, then book when it is present.
This entry does not name an asset, a chain, or a payee. ...

The pointer names https://nettrux-edge.fly.dev/.well-known/x402 as the freight API discovery document. While EDGE_X402_DISCOVERY_PUBLISHED is false, that URL is not published by the API host. A 404 there is expected; the site pointer is still the catalog.

import urllib.error

EDGE_DISCOVERY = "https://nettrux-edge.fly.dev/.well-known/x402"
req = urllib.request.Request(
    EDGE_DISCOVERY,
    headers={"User-Agent": "nettrux-discovery-howto/1.0", "Accept": "application/json"},
)
try:
    urllib.request.urlopen(req, timeout=20)
except urllib.error.HTTPError as e:
    print("Edge discovery HTTP", e.code)
Edge discovery HTTP 404

If your agent treats every 404 as "this 3PL does not support x402," you will miss Nettrux. Check the site pointer first. Only treat Edge discovery as authoritative once discoveryPublished flips to true and the gate says so.

The discovery pointer points at the OpenAPI. That document is the request/response contract for every authenticated call. It is public and needs no token.

OPENAPI = "https://nettrux-edge.fly.dev/openapi.json"
req = urllib.request.Request(
    OPENAPI,
    headers={"User-Agent": "nettrux-discovery-howto/1.0", "Accept": "application/json"},
)
with urllib.request.urlopen(req, timeout=20) as r:
    oa = json.load(r)

paths = oa["paths"]
print(oa["info"]["title"], "openapi", oa["openapi"], "paths", len(paths))

commit = paths["/v1/immediate-bookings/commit"]["post"]
print("summary:", commit["summary"])
print("security:", commit["security"])
print("responses:", list(commit["responses"]))
body = commit["requestBody"]["content"]["application/json"]["schema"]
print("required body fields:", body["required"])
Nettrux Edge API openapi 3.0.3 paths 126
summary: Commit an immediate booking by PAYING for it over the x402 v1 handshake
(402 challenge without X-PAYMENT; verify → settle → book with it)
security: [{'bearerAuth': []}]
responses: ['200']
required body fields: ['quote_id']

A few agent-relevant paths that exist today:

Path Methods Auth
/health ,/ready GET none
/v1/rates/shop POST bearer
/v1/quotes GET, POST bearer
/v1/immediate-bookings/commit POST bearer
/v1/me GET bearer
/v1/agent/approvals GET bearer

The OpenAPI security scheme is HTTP bearer (JWT or API key). The public site does not issue tokens and does not describe self-serve signup. Guest checkout routes appear in the OpenAPI and stay flagged off — do not call them from these instructions.

Unauthenticated health is a useful smoke check that the freight API host is up:

HEALTH = "https://nettrux-edge.fly.dev/health"
req = urllib.request.Request(
    HEALTH,
    headers={"User-Agent": "nettrux-discovery-howto/1.0", "Accept": "application/json"},
)
with urllib.request.urlopen(req, timeout=20) as r:
    health = json.load(r)
print(health["ok"], health["data"]["status"])
True healthy

Commit without a bearer is rejected. Same day check:

import urllib.error

url = "https://nettrux-edge.fly.dev/v1/immediate-bookings/commit"
payload = json.dumps({"quote_id": "00000000-0000-4000-8000-000000000000"}).encode()
req = urllib.request.Request(
    url,
    data=payload,
    method="POST",
    headers={
        "Content-Type": "application/json",
        "User-Agent": "nettrux-discovery-howto/1.0",
    },
)
try:
    urllib.request.urlopen(req, timeout=20)
except urllib.error.HTTPError as e:
    print("HTTP", e.code, e.read().decode()[:180])
HTTP 401 {"ok":false,"data":null,"error":{"code":"missing_token",
"message":"Authorization: Bearer <token> is required"}, ...}

That is the boundary: discovery is public; booking is authenticated; minting still requires a named human on the Nettrux side of the product.

After the JSON pointer, have the agent (or its author) read the prose contract:

Both returned HTTP 200 when we checked them for this article. The guide's instructions match the pointer: price-lock with POST /v1/quotes (quoteNumber, validUntil, rateInput), then call POST /v1/immediate-bookings/commit with { "quote_id": "..." } and no X-PAYMENT header for the documented 402 challenge. A paid retry carries the X-PAYMENT header an x402 v1 client builds from that challenge.

Because X402_REAL_MONEY_SETTLEMENT_LIVE is false, treat that handshake as documented, not as a claim that a public payment settles or books freight today.

def discover_nettrux():
    """Public discovery only. Does not quote, book, or pay."""
    import json, urllib.request, urllib.error

    pointer = json.load(urllib.request.urlopen(
        urllib.request.Request(
            "https://www.nettrux.ai/.well-known/x402",
            headers={"Accept": "application/json",
                     "User-Agent": "nettrux-discovery-howto/1.0"},
        )
    ))
    gates = pointer["gates"]
    openapi = json.load(urllib.request.urlopen(
        urllib.request.Request(
            pointer["openapi"],
            headers={"Accept": "application/json",
                     "User-Agent": "nettrux-discovery-howto/1.0"},
        )
    ))

    return {
        "name": pointer["name"],
        "resource_host": pointer["resourceHost"],
        "resources_empty": pointer["resources"] == [],
        "gates": gates,
        "openapi_title": openapi["info"]["title"],
        "openapi_paths": len(openapi["paths"]),
        "commit_documented": "/v1/immediate-bookings/commit" in openapi["paths"],
        "ready_for_public_pay_and_book": (
            gates["EDGE_X402_DISCOVERY_PUBLISHED"]
            and gates["X402_REAL_MONEY_SETTLEMENT_LIVE"]
            and bool(pointer["resources"])
        ),
    }

print(discover_nettrux())

Live output shape (abridged):

{
  'name': 'Nettrux',
  'resource_host': 'https://nettrux-edge.fly.dev',
  'resources_empty': True,
  'gates': {
    'EDGE_X402_DISCOVERY_PUBLISHED': False,
    'X402_REAL_MONEY_SETTLEMENT_LIVE': False,
    'GUEST_X402_CHECKOUT_ENABLED': False
  },
  'openapi_title': 'Nettrux Edge API',
  'openapi_paths': 126,
  'commit_documented': True,
  'ready_for_public_pay_and_book': False
}

That last boolean is the whole point of honest discovery. An agent that can parse gates is an agent that will not invent a live rail that is not there.

Discovery gets you the map. Quoting and booking still need:

POST /v1/quotes. Shippers who just need freight moved today use the portal at nettrux.ai: LTL, FTL, and air are live; ocean is in build; tracking links and load documents do not require an agent.

No. The discovery pointer is live. The resources array is empty. Discovery publish, real-money settlement, and guest checkout are all false.

So agents can find the OpenAPI, the freight API host, and the gate flags without guessing. An empty catalog with honest gates beats a marketing page that pretends settlement is open.

Only with a bearer token Nettrux has already issued to your tenant, and only against the authenticated handshake documented in the OpenAPI. Without a token you get 401 missing_token. Public guest checkout is flagged off.

No. Other APIs sell logistics data over x402. The claim is about a 3PL building a native x402 transaction surface for the move itself.

Questions for agent builders: dispatch@nettrux.net.

Alex Carney, Nettrux

── more in #ai-agents 4 stories · sorted by recency
── more on @nettrux 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/how-an-ai-agent-disc…] indexed:0 read:6min 2026-11-09 · —