Purserhouse for AI agents

An agent sends a customer's own trade documents to Purserhouse over MCP or REST and gets back findings on cost, risk or speed and one next step: everything that stops clearance or shipping, then at most three others. Request access, grant consent, submit, then poll.

Purserhouse is for US small and mid-size importers of goods made in China, and the customs brokers who serve them. Send a CBP Form 7501 for the IEEPA refund window and printed duty, or a demurrage and detention invoice for a check, the real last free day and a dispute basis. A person or company gives it their own documents; it returns every red line (anything that stops clearance or shipping), then at most three other findings on cost, risk or speed, and one next step. Agents can do this on the customer’s behalf.

The API contract below is a summary. /openapi.yaml is authoritative. The full guide written for language models is at /llms-full.txt , and a short index is at /llms.txt .

Machine-readable entry points

WhatWhere
MCP server (Streamable HTTP, JSON-RPC 2.0)https://purserhouse.com/mcp
REST API basehttps://purserhouse.com/api/v1
Public market snapshot (no key)GET https://purserhouse.com/api/market
Free public tools (no key)https://purserhouse.com/api/public/{refund-check,last-free-day,tariff-stack,screen,hs,dd-letter,isf-check}
OpenAPI description/openapi.yaml
MCP server card/.well-known/mcp.json
Short index for LLMs/llms.txt
Full guide for LLMs/llms-full.txt
Every page as Markdownadd index.md to any page URL, for example /en/importer/index.md

The flow

  1. Look at coverage (no key). Call GET /api/v1/coverage or the MCP tool lanebrief_coverage to see lanes, ports, territories, container types, sides, document kinds and limits.
  2. Get a key by requesting access (no key). POST /api/v1/access-requests or lanebrief_request_access with email, name, company, side, lanes and a note. The reply is 202. A person at Purserhouse reviews the request; the key (lb_live_...) is issued after access is granted.
  3. Grant consent (key). The customer agrees once that their documents may be processed. POST /api/v1/consent or lanebrief_grant_consent. Before that, submissions fail with 403 consent_required.
  4. Submit documents (key). POST /api/v1/cases or lanebrief_submit_documents. You get 202 with a case_id, status: "processing", a poll_url and retry_after. Add wait_seconds (0 to 25) to hold the call until the case is answered: if it is ready in time you get 200 with the result inline. Add idempotency_key (or rely on the files’ hashes) so that a retry returns the same case with duplicate: true instead of opening a second one.
  5. Poll the result (key). GET /api/v1/cases/{id} or lanebrief_get_result, no more often than every retry_after seconds, until status is answered or failed. Not needed when the submit already returned the result.
  6. Optional: details. GET /api/v1/cases/{id}/details or lanebrief_get_details returns the detailed breakdown behind the findings.

GET /api/v1/account (or lanebrief_account) shows the plan, whether billing is enabled, the free cases per month, how many are used and how many remain.

MCP client configuration

Most MCP clients that support remote HTTP servers accept a block like this. Replace the key with your own.

{
  "mcpServers": {
    "lanebrief": {
      "type": "http",
      "url": "https://purserhouse.com/mcp",
      "headers": {
        "Authorization": "Bearer lb_live_..."
      }
    }
  }
}

Tools: lanebrief_market_snapshot (no key), lanebrief_coverage, lanebrief_request_access (no key needed), lanebrief_grant_consent, lanebrief_submit_documents (files as base64), lanebrief_get_result, lanebrief_get_details, lanebrief_account; the free public tools (no key) lanebrief_refund_check, lanebrief_last_free_day, lanebrief_tariff_stack, lanebrief_screen, lanebrief_hs_rulings, lanebrief_dd_letter, lanebrief_isf_check.

REST examples

Coverage, no key:

curl https://purserhouse.com/api/v1/coverage

Request access, no key:

curl -X POST https://purserhouse.com/api/v1/access-requests \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]","name":"A. Buyer","company":"Example Trading","side":"importer","lanes":["CN-PG"],"note":"Agent integration"}'

Grant consent, once per key:

curl -X POST https://purserhouse.com/api/v1/consent \
  -H "Authorization: Bearer lb_live_..."

Submit documents as multipart:

curl -X POST https://purserhouse.com/api/v1/cases \
  -H "Authorization: Bearer lb_live_..." \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "lang=en" \
  -F "dest_country=AE"

Or as JSON:

curl -X POST https://purserhouse.com/api/v1/cases \
  -H "Authorization: Bearer lb_live_..." \
  -H "Content-Type: application/json" \
  -d '{"text":"Quote attached, 1x40HC Shanghai to Jebel Ali","lang":"en","dest_country":"AE","files":[{"name":"invoice.pdf","mime":"application/pdf","data_base64":"JVBERi0x..."}]}'

Poll:

curl https://purserhouse.com/api/v1/cases/CASE_ID \
  -H "Authorization: Bearer lb_live_..."

Public market data (no key)

GET /api/market is a free, public JSON snapshot. It is described in /openapi.yaml (getMarket) and is also the MCP tool lanebrief_market_snapshot (no key, no arguments, same JSON). Responses are cached for 60 seconds, CORS is open, and requests are rate limited per IP (HTTP 429 with Retry-After).

curl https://purserhouse.com/api/market

It contains as_of, fx (exchange rates with date, change and source), lanes (a freight trend index per lane with value, unit, date and source), watch (which data sources were updated and when, never their numbers), attributions and note. A value appears only when its licence allows it. It never contains forwarder medians or customer data, and the trend index is a market trend, not a quote. Show the attributions when you reuse it. Sources and cadence: Data and sources .

Free public tools (no key)

Seven JSON endpoints, described in /openapi.yaml (publicRefundCheck, publicLastFreeDay, publicTariffStack, publicScreen, publicHSRulings, publicDDLetter, publicISFCheck) and available as MCP tools without a key. They store nothing and call no model (except hs with q, which asks one for codes only); they run the same rules and licence gate as a customer case. Limit: 30 requests per 10 minutes per IP (screen: 10), then HTTP 429 with Retry-After. Errors are {"error": "..."}. Every response has sources and test_mode.

EndpointMCP toolAnswers
POST /api/public/refund-checklanebrief_refund_checkWhich chapter 99 lines of a CBP 7501 fall in the IEEPA refund window (in_refund_window, not_in_window, not_checked) and the printed duty total. Liquidation status is not on a 7501; interest is not included.
GET /api/public/last-free-daylanebrief_last_free_dayThe last free day from the carrier’s published US tariff, or why it is not calculated.
GET /api/public/tariff-stacklanebrief_tariff_stackThe additional-duty layers in force for an HTS number and origin on a date. No total duty.
POST /api/public/screenlanebrief_screenPossible matches of a company name on the sanctions lists. Not a clearance.
GET /api/public/hslanebrief_hs_rulingscode: heading text from the US schedule and the newest 10 CBP CROSS rulings under a 6-digit heading. q (MCP query, a product description): up to 3 suggested codes (proposed by a model, each checked against the tariff tables, all text from the schedule) and up to 5 text matches, each with the newest 3 rulings; llm is unavailable when no model answered. Suggestions, not a classification; limit 10 per 10 minutes.
POST /api/public/dd-letterlanebrief_dd_letterA demurrage or detention invoice check and letter drafts.
POST /api/public/isf-checklanebrief_isf_checkWhich of the ten importer ISF elements (19 CFR 149.3(a)) are given or missing, and whether each HTSUS number has six digits and is in the HTS. Presence and format, not truth. Also takes the filled Excel template as multipart field file (1 MB).
curl -X POST https://purserhouse.com/api/public/refund-check -H 'Content-Type: application/json' \
  -d '{"entry_date":"2025-12-01","origin":"CN","lines":[{"hts":"9903.01.24","duty":"1250.00"}]}'
curl 'https://purserhouse.com/api/public/last-free-day?carrier=MAEU&port=USLAX&arrival=2026-11-20&container=40'

Relay the JSON as returned. A null field, not_checked or computed: false means not calculated; do not fill it in.

What an answer looks like

The numbers below are an invented illustration of the shape, not a real result.

{
  "case_id": 123,
  "status": "answered",
  "lang": "en",
  "findings": [
    {"code": "net_weight_mismatch", "axis": "risk", "severity": "blocker", "title": "Documents do not match", "detail": "Net weight differs between invoice and packing list.", "red_line": true, "evidence": {"invoice": "3400", "packing": "3120"}},
    {"code": "quote_above_median", "axis": "cost", "severity": "medium", "title": "Quote above the market median", "detail": "...", "saving_usd": 250}
  ],
  "next_step": "Ask the factory for a corrected packing list.",
  "answer_text": "..."
}

If a number cannot be calculated from licensed data, the answer says “not calculated”. It is never filled in with a guess.

Errors

Errors have the shape {"error":{"code","message","hint"}}.

StatusCodeWhat to do
400invalid_requestFix the request using hint.
401unauthorizedCheck the key and the Authorization header.
402payment_requiredOnly once billing starts. Tell the customer; do not retry.
403consent_requiredGrant consent once, then resubmit.
404not_foundThe case id is wrong or the case was deleted after 7 days.
413too_largeSend fewer or smaller files.
429rate_limitedWait for the Retry-After header, then retry.

Rules agents must follow

How Purserhouse differs from marketplaces, benchmarks and duty calculators: Purserhouse compared . The human version of the same service starts on the home page .

Frequently asked questions

Does Purserhouse have an MCP server?

Yes. It is a Streamable HTTP MCP server at https://purserhouse.com/mcp, using JSON-RPC 2.0 and the same bearer key as the REST API. The server card is at /.well-known/mcp.json.

Is there public data I can read without a key?

Yes. GET https://purserhouse.com/api/market returns exchange rates, a freight trend index per lane and the list of data sources with their last update time, as JSON. It has no customer data and no forwarder medians.

Do I need an API key?

Yes for customer answers. No key is needed for the coverage endpoint, the access request and the public /api/market snapshot. Keys look like lb_live_... and are issued after access is granted.

Does it cost anything?

Not at the moment: the service is free. Later there will be a monthly free allowance and paid use beyond it. The account endpoint reports the current billing state, so an agent never has to guess.

Can an agent pay for Purserhouse?

Not yet. Agent payments are planned but not available. Until billing starts, nothing is charged.

Which document should I send?

The customer's own commercial invoice, packing list, freight quote, bill of lading or certificates, as PDF, image or spreadsheet, for ocean container shipments only.

What if the answer is still processing?

Wait the number of seconds in retry_after and poll the same case again, or send wait_seconds (up to 25) with the submission to have the call held until the result is ready. Submitting the same documents again within 24 hours returns the same case, so a retry after a timeout is safe.

Updated: