First-time setup
Follow these steps in order. When you finish, you will have a working project API key and a successful weather + traffic query against the hosted API.
wc_… API key stored in your secrets manager (for your app)POST /v1/context/queries response with a requestIdOne-time account, project, and key setup — do this once per environment.
Atlas One separates people from software:
https://world-context.vercel.app) — your backend calls it with a wc_… key. It does not use your console password or email sessionIf you try to call the API with a Clerk session cookie, it will fail. Apps must use the project key.
staging or my-tms-prodKeys and usage are project-scoped. A key from project A cannot read snapshots created under project B. Use separate projects for staging vs production when you can.
local-dev or railway-prod)wc_. Copy it immediatelyLost the secret? Revoke that key in the console and mint a new one. There is no rotate endpoint in V1 — revoke + create is the path.
Never commit wc_… keys to git, paste them into public Slack, or ship them in a browser frontend. Keep keys on the server.
In the environment where your backend runs, set:
ATLAS_ONE_API_BASE_URL=https://world-context.vercel.app ATLAS_ONE_API_KEY=wc_your_secret_here
Optional — only if HeftIQ (or your host) gave you a Vercel Deployment Protection bypass secret. Without it, some hosted deployments return an HTML “Authentication Required” page instead of JSON:
VERCEL_AUTOMATION_BYPASS_SECRET=your_bypass_secret
Confirm the API is reachable before you debug query bodies.
export ATLAS_ONE_API_BASE_URL='https://world-context.vercel.app' # If you have a bypass secret, keep this header on every request: # -H "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" curl -sS "$ATLAS_ONE_API_BASE_URL/health"
Expect: JSON that indicates the service is up (not an HTML login page). If you see HTML auth, add the bypass header from step 4 and retry.
Resolve weather/traffic/routing/hazard context for a location and time window.
This is the Memphis → Atlanta demo (same corridor as Playground). Replace the key with yours.
export ATLAS_ONE_API_BASE_URL='https://world-context.vercel.app'
export ATLAS_ONE_API_KEY='wc_…'
curl -sS -X POST "$ATLAS_ONE_API_BASE_URL/v1/context/queries" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
# -H "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
-d '{
"kinds": ["weather", "traffic", "routing", "hazard"],
"location": {
"kind": "routePlace",
"origin": "Memphis, TN",
"destination": "Atlanta, GA"
},
"timeWindow": {
"windowStart": "2026-07-21T12:00:00.000Z",
"windowEnd": "2026-07-22T12:00:00.000Z"
},
"options": {
"hazard": { "corridorBufferKm": 100 }
}
}'You should get HTTP 200. The top-level envelope always looks like this — one result object per kind you asked for:
{
"requestId": "req_…",
"results": [
{ "kind": "weather", "cacheHit": false, "snapshot": { /* see weather below */ } },
{ "kind": "traffic", "cacheHit": false, "snapshot": { /* see traffic below */ } }
]
}Live fields live under snapshot.signals. Optional fields may be omitted when the provider did not return them.
{
"kind": "weather",
"cacheHit": false,
"snapshot": {
"snapshotId": "wctx_…",
"kind": "weather",
"providerRef": "open-meteo@1.0.0",
"providerVersion": "1.0.0",
"sourceRetrievedAt": "2026-07-21T12:00:00.000Z",
"expiresAt": "2026-07-21T12:30:00.000Z",
"locationInput": {
"kind": "routePlace",
"origin": "Memphis, TN",
"destination": "Atlanta, GA"
},
"timeWindowInput": {
"windowStart": "2026-07-21T12:00:00.000Z",
"windowEnd": "2026-07-22T12:00:00.000Z"
},
"signals": {
"kind": "weather",
"currentCondition": "Partly cloudy",
"temperatureC": 24.5,
"precipitationProbability": 0.2,
"rainIndicator": false,
"snowIndicator": false,
"stormIndicator": false,
"windSpeedKph": 12,
"windGustsKph": 22,
"visibilityM": 10000,
"snowfallCm": 0,
"severeWeatherAlert": false,
"precipitationRisk": 0.15,
"windRisk": 0.1,
"visibilityRisk": 0.05,
"forecastRiskScore": 0.18,
"routeWeatherExposureScore": 0.22,
"icingRisk": 0,
"floodRisk": 0.05
},
"severity": { "weatherSeverityScore": 0.15 },
"confidence": 0.82,
"freshnessStatus": "fresh",
"status": "ok",
"providerFailureState": "none",
"attribution": {
"providerName": "Open-Meteo",
"attributionText": "Weather data by Open-Meteo (https://open-meteo.com)",
"sourceUrl": "https://open-meteo.com",
"licenseRef": "https://open-meteo.com/en/license"
},
"limitations": [],
"hashes": {
"input": "…",
"output": "…",
"location": "…",
"timeWindow": "…"
}
}
}{
"kind": "traffic",
"cacheHit": false,
"snapshot": {
"snapshotId": "wctx_…",
"kind": "traffic",
"providerRef": "tomtom-flow@1.0.0",
"providerVersion": "1.0.0",
"sourceRetrievedAt": "2026-07-21T12:00:00.000Z",
"expiresAt": "2026-07-21T12:10:00.000Z",
"locationInput": {
"kind": "routePlace",
"origin": "Memphis, TN",
"destination": "Atlanta, GA"
},
"timeWindowInput": {
"windowStart": "2026-07-21T12:00:00.000Z",
"windowEnd": "2026-07-22T12:00:00.000Z"
},
"signals": {
"kind": "traffic",
"congestionLevel": 0.35,
"estimatedDelayMinutes": 12,
"delayPercent": 0.18,
"routeDurationMinutes": 380,
"freeFlowDurationMinutes": 320,
"routeDistanceMeters": 620000,
"dataCoveragePercent": 0.98,
"routeConfidence": 0.91,
"roadClosureIndicator": false,
"incidentIndicator": true,
"incidentCount": 2,
"routeOriginLabel": "Memphis, TN",
"routeDestinationLabel": "Atlanta, GA",
"comparingSummary": "Comparing Memphis, TN → Atlanta, GA",
"bottleneckSummary": {
"segmentCount": 3,
"slowestRelativeSpeed": 0.42,
"closedOrImpassable": false
}
},
"severity": { "trafficSeverityScore": 0.28 },
"confidence": 0.88,
"freshnessStatus": "fresh",
"status": "ok",
"providerFailureState": "none",
"attribution": {
"providerName": "TomTom",
"attributionText": "Traffic data © TomTom",
"sourceUrl": "https://developer.tomtom.com"
},
"limitations": [],
"hashes": {
"input": "…",
"output": "…",
"location": "…",
"timeWindow": "…"
}
}
}Read results[].snapshot.signals for the human-useful numbers (temp, delay, etc.). Check snapshot.status per kind — HTTP 200 can still mean one kind failed.
Save requestId if something looks wrong — support can use it to trace the call.
kinds — required. One or both of "weather", "traffic"location — required. Where to evaluate context (see shapes below)timeWindow — required. windowStart / windowEnd as ISO-8601 UTC strings. End must be after startroutePlace — place names: { "kind":"routePlace", "origin":"Memphis, TN", "destination":"Atlanta, GA" }place — single named place: { "kind":"place", "query":"Chicago, IL" }point — coordinates: { "kind":"point", "latitude":40.7, "longitude":-74.0 }route — lat/lng endpoints (when you already have coordinates)HTTP 200 can still mean one kind failed. Always check each result’s snapshot.status (for example weather ready while traffic is failed).
Prefer the typed client in app code. Package: @world-context/sdk.
import { AtlasOneClient } from "@world-context/sdk";
const client = new AtlasOneClient({
baseUrl: process.env.ATLAS_ONE_API_BASE_URL!, // https://world-context.vercel.app
apiKey: process.env.ATLAS_ONE_API_KEY!, // wc_…
// Only if your deployment requires Vercel Deployment Protection:
// vercelProtectionBypass: process.env.VERCEL_AUTOMATION_BYPASS_SECRET,
});
const result = await client.queryContext({
kinds: ["weather", "traffic", "routing", "hazard"],
location: {
kind: "routePlace",
origin: "Memphis, TN",
destination: "Atlanta, GA",
},
timeWindow: {
windowStart: new Date().toISOString(),
windowEnd: new Date(Date.now() + 86_400_000).toISOString(),
},
options: {
hazard: { corridorBufferKm: 100 },
},
});
for (const row of result.results) {
console.log(row.kind, row.snapshot.status, row.cacheHit);
}If you want to see a successful query before wiring your app:
Playground uses your console session (no key in the browser) but still meters usage against the project — check Usage afterward.
From a query response, copy snapshot.snapshotId, then:
curl -sS "$ATLAS_ONE_API_BASE_URL/v1/context/snapshots/<snapshotId>" \ -H "Authorization: Bearer $ATLAS_ONE_API_KEY" # -H "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET"
POST /v1/weather/history/query returns past weather observations plus a deterministic period summary for one location — evidence for questions like “was this lane near heavy rain last week,” never a causal claim about a delay or disruption. It is a separate endpoint from /v1/context/queries: historical data is a time series, not a single point-in-time snapshot, so it is not fetchable via GET /v1/context/snapshots or comparable via /v1/context/compare.
curl -sS -X POST "https://world-context.vercel.app/v1/weather/history/query" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"location": { "kind": "point", "latitude": 41.8781, "longitude": -87.6298 },
"startTime": "2026-07-01",
"endTime": "2026-07-03",
"granularity": "hourly",
"variables": ["temperature", "precipitation", "wind_speed", "weather_code"],
"timezone": "America/Chicago"
}'location is a single point (lat/lng) or a named place (geocoded before the query runs) — there is no route/corridor variant here, unlike /v1/context/queries.
startTime/endTime are always both required. Set them to the same date for one day's data; set them to different dates for a range — up to 31 days at hourly granularity, or 5 years at daily. Both bounds are inclusive:"2026-07-01" .. "2026-07-03" above returns all three days (July 1, 2, and 3), 72 hourly observations. Future dates are rejected outright — the archive typically lags now by about 5 days.
{
"queryId": "wctx_hist_…",
"location": {
"latitude": 41.8781,
"longitude": -87.6298,
"timezone": "America/Chicago"
},
"requestedPeriod": { "startTime": "2026-07-01T05:00:00.000Z", "endTime": "2026-07-04T05:00:00.000Z" },
"granularity": "hourly",
"observations": [
{
"observedAt": "2026-07-01T00:00:00-05:00",
"temperatureCelsius": 25.6,
"precipitationMm": 0,
"windSpeedKph": 10.3,
"weatherCode": 0,
"classification": "clear"
}
],
"summary": {
"minimumTemperatureCelsius": 20.3,
"maximumTemperatureCelsius": 31.5,
"averageTemperatureCelsius": 25.3,
"totalPrecipitationMm": 27.4,
"adverseConditionIntervals": 19,
"dominantClassification": "cloudy",
"missingObservationCount": 0
},
"provider": { "name": "open-meteo-historical", "dataset": "era5", "retrievedAt": "2026-07-29T21:00:14.564Z" },
"freshness": { "dataStatus": "historical", "latestObservationAt": "2026-07-03T23:00:00-05:00" },
"limitations": []
}classification (clear / cloudy / rain / heavy_rain / snow / thunderstorm / fog / high_wind / extreme_heat / extreme_cold / unknown) is always present on every observation, independent of which variables you requested — it is a core output of this endpoint, not an echo of a requested field. weatherCode (the provider's raw code) is only present when "weather_code" is itself in variables. Requesting an unsupported variable is a validation error, not a silently dropped field.
Historical data is immutable, so identical requests are cached long-term — a repeat query returns the same observations/summary under a fresh queryId, with no second call to the upstream provider.
Not every requested variable is guaranteed from every provider. visibility has no archive-API equivalent at all, and relative_humidity/surface_pressure/cloud_cover have no daily rollup — these come back as null plus an entry in limitations, never a fabricated value.
Ask whether one snapshot (or request set) is a material change from another.
Use POST /v1/context/compare when you need to know whether one snapshot is a material change from another. Both sides must be the same kind (for example weather vs weather). You can pass stored snapshotIds from your project, or inline snapshot objects for dry runs.
Tip: Always use https:// for ATLAS_ONE_API_BASE_URL. Plain http:// can 308-redirect and break JSON clients.
# After two queries, copy each snapshot.snapshotId (same kind).
curl -sS -X POST "$ATLAS_ONE_API_BASE_URL/v1/context/compare" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
# -H "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
-d '{
"baselineSnapshotId": "wctx_…",
"candidateSnapshotId": "wctx_…"
}'Read these fields first:
materiallyChanged — whether the engine treats the candidate as a decision-relevant changechangeClassifications — why (for example severity_increased)severity (0–1) and severityBand — how large the change iscompatibility — soft vs hard scope mismatches (hard mismatches fail the request)Output hash equality is a fast “identical payload” shortcut for audit — it is not the same as materiality. A provider label change can appear in the report without flipping materiallyChanged.
A single POST /v1/context/queries can return several kinds under one requestId. Use POST /v1/context/compare-requests to compare two of those request sets (for example “before vs after” for the same corridor).
curl -sS -X POST "$ATLAS_ONE_API_BASE_URL/v1/context/compare-requests" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
# -H "x-vercel-protection-bypass: $VERCEL_AUTOMATION_BYPASS_SECRET" \
-d '{
"baselineRequestId": "req_…",
"candidateRequestId": "req_…"
}'Query-shape changes such as kind_added / kind_removed are reported, but they alone do not mean the environment got worse — check per-kind materiallyChanged in the response for true signal changes.
Cache hits still attach snapshots to the new requestId, so compare-by-request works even when the second query reused cached weather/traffic.
Monitor usage, and turn Atlas One from a query API into a monitoring one — webhooks, watches, and MCP.
Open Usage in the console. You will see metered units for the current period, remaining quota, and reset date. When you hit the limit, the API returns a quota error — wait for the period to reset or ask for a higher limit.
Register a URL that should receive signed deliveries when a watch (see the next section) detects a material change. You can also manage endpoints from the Projects console — open a project and go to Webhooks.
curl -sS -X POST "https://world-context.vercel.app/v1/webhook-endpoints" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-app.example.com/hooks/atlas-one"}'The response includes a secret starting with whsec_ — shown once, encrypted at rest, and never returned again. Registering an endpoint alone does not activate anything; subscribe a watch to it (next section) to start receiving deliveries.
POST https://your-app.example.com/hooks/atlas-one
Content-Type: application/json
Atlas-One-Event-Id: evt_...
Atlas-One-Timestamp: 1785500000
Atlas-One-Signature: <hex hmac>
{
"id": "evt_...",
"type": "context.material_change",
"createdAt": "2026-07-29T01:00:00.000Z",
"watchId": "watch_...",
"runId": "run_...",
"previousSnapshotId": "snap_...",
"currentSnapshotId": "snap_...",
"data": { "comparisonId": "cmp_...", "primaryClassification": "weather_severity_delta", "matchedConditions": ["weather_severity_increased"] }
}The payload is a notification, not the full signal — fetch GET /v1/context/snapshots/{currentSnapshotId} for the actual weather/traffic/routing/hazard fields.
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody: string, timestamp: string, signature: string, secret: string): boolean {
const expected = createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex");
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}Sign the raw request body — re-serializing the parsed JSON before verifying will produce a different byte sequence and fail. Note the signature covers the timestamp and body only, not the event id — if your handler needs to reject a specific event id, check it separately from the payload rather than assuming the signature alone binds to it.
A context watch saves a weather/ traffic/routing/hazard query plus a notification policy and re-executes it on a schedule — this is what turns Atlas One from a query API into a monitoring one. (For tariffs / trade regulation, use policy trade watches instead.) Manage context watches from the Projects console, or with the API directly:
curl -sS -X POST "https://world-context.vercel.app/v1/watches" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "I-45 Houston to Dallas weather",
"query": {
"kinds": ["weather"],
"location": {
"kind": "route",
"origin": { "latitude": 29.7604, "longitude": -95.3698 },
"destination": { "latitude": 32.7767, "longitude": -96.7970 }
},
"relativeTimeWindow": { "offsetMinutes": 0, "durationMinutes": 360 }
},
"policy": {
"version": "1",
"refreshEveryMinutes": 60,
"conditions": [{ "type": "weather_severity_increased", "minimumSeverity": "moderate" }]
},
"webhookEndpointId": "whep_..."
}'relativeTimeWindow is resolved fresh from “now” on every scheduled run — a watch cannot carry an absolute time window. refreshEveryMinutes must be one of 30, 60, 120, 180, 360, 720, or 1440. Passing webhookEndpointId at creation atomically activates the watch (draft → active) and starts billing its scheduled runs; omit it to save a draft first and activate later:
curl -sS -X POST "https://world-context.vercel.app/v1/watches/$WATCH_ID/webhook-subscriptions" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"webhookEndpointId": "whep_..."}'Condition types: weather_severity_increased (optional minimumSeverity: none/low/ moderate/high/critical), route_delay_increased (optional minimumIncreaseMinutes), traffic_jam_added, new_route_hazard_exposure, hazard_no_longer_intersects_route, provider_unavailable, and provider_recovered. A run only delivers a webhook when the comparison is materially changed and at least one condition matches.
Unsubscribing a watch's last active endpoint drops it back to draft and stops scheduled execution immediately — an unsubscribed watch never keeps costing provider spend in the background.
Atlas One also exposes a Model Context Protocol server at POST https://world-context.vercel.app/v1/mcp — the same project-scoped wc_… API key and usage metering as the REST API, but callable directly by an MCP-aware AI client (Claude Code, Claude Desktop, ChatGPT, Codex, etc.) instead of hand-written HTTP calls.
claude mcp add --transport http atlas-one "https://world-context.vercel.app/v1/mcp" \ --header "Authorization: Bearer wc_your_secret_here" \ --header "x-vercel-protection-bypass: your_bypass_secret"
Or add it to a project-shared .mcp.json so your whole team picks it up:
{
"mcpServers": {
"atlas-one": {
"type": "http",
"url": "https://world-context.vercel.app/v1/mcp",
"headers": {
"Authorization": "Bearer ${ATLAS_ONE_API_KEY}",
"x-vercel-protection-bypass": "${VERCEL_AUTOMATION_BYPASS_SECRET}"
}
}
}
}Use environment-variable placeholders rather than committing raw secrets. Run /mcp inside a Claude Code session (start a new one if the server was just added — servers load at session start) to confirm it shows as connected.
atlas_get_capabilities, atlas_query_context, atlas_get_snapshot, atlas_compare_snapshots, atlas_compare_context_requests, atlas_query_historical_weatheratlas_list_watches, atlas_get_watch, atlas_create_watch, atlas_update_watch, atlas_subscribe_watch, atlas_unsubscribe_watch, atlas_delete_watchatlas_create_webhook_endpoint, atlas_list_webhook_endpoints, atlas_delete_webhook_endpoint (signing secret returned once on create)Full partner docs: authentication, usage-event rules, catalogs, known limitations, and host certification — see the repo docs/partners/mcp.md.
Ask for atlas_get_capabilities first — it lists every tool, required scope, and provider fact without consuming any metered quota.
Write tools (atlas_create_watch, atlas_subscribe_watch) require an idempotencyKey — a retried call with the same key and the same arguments replays the original result instead of creating a duplicate. atlas_delete_watch additionally requires confirm: true.
We're still relying on Vercel Deployment Protection for some deployments — while that's the case, the MCP endpoint needs the same x-vercel-protection-bypass header shown above (see step 4). Drop it once protection is off, or once you're pointed at an unprotected deployment.
Query regulatory and trade developments, resolve friendly product names to HS codes, register trade lanes, and get notified when your lanes or domains are exposed — via REST today (console pages for this surface are not shipped yet).
Physical context (weather/traffic) answers “what is happening on the ground?” Policy events answer “what is changing in tariffs, customs, sanctions, or legislation that could affect trade?” Same wc_… project key; different routes and scopes (policy_events:read).
List events with a filter. Empty body means “show me what this project may see.” Optional domain matches product interest (HS, concepts, industries, or everyday names). Optional include pulls overlays:
curl -sS -X POST "https://world-context.vercel.app/v1/policy-events/query" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": {
"version": "1",
"names": ["steel manufacturing"]
},
"limit": 10,
"include": ["probability", "research", "exposures", "hypotheses"]
}'Each item is a mediated view — the canonical cluster member you are allowed to see, plus clusterSiblingIds that are also visible to your project. Invisible ids return 404 (no leak of hidden siblings). When a domain filter matches, look for relevance (matched / confidence / matchedBy).
curl -sS "https://world-context.vercel.app/v1/policy-events/$POLICY_EVENT_ID?include=probability,research" \ -H "Authorization: Bearer $ATLAS_ONE_API_KEY"
import { AtlasOneClient } from "@world-context/sdk";
const client = new AtlasOneClient({
baseUrl: process.env.ATLAS_ONE_API_BASE_URL!,
apiKey: process.env.ATLAS_ONE_API_KEY!,
});
const { items } = await client.queryPolicyEvents({
domain: { version: "1", names: ["steel manufacturing"] },
include: ["probability", "research", "exposures", "hypotheses"],
limit: 10,
});OpenAPI tag Policy at https://world-context.vercel.app/docs (Swagger UI) lists every policy route interactively.
You do not need to memorize Harmonized System chapters. Resolve a friendly name or industry against a small hermetic catalog (no LLM on this path). Unknown names return matched: false — Atlas One never invents HS codes.
# Autocomplete catalog (steel / aluminum / apparel, …)
curl -sS "https://world-context.vercel.app/v1/policy-domain/concepts" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY"
# Name → concept + HS chapters + expanded domain filter
curl -sS -X POST "https://world-context.vercel.app/v1/policy-domain/resolve" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "steel manufacturing" }'Use the expanded domain on event query or a domain-target trade watch. Watches store what you wrote; expansion happens at match/query time so catalog growth applies retroactively.
Separate from context watches (/v1/watches). A policy trade watch notifies a webhook when something material happens for a chosen target. Requires a webhook endpoint first (see §14) and scopes policy_trade_watches:read|write.
Pick exactly one target type:
policyEventId (material-change → policy.material_change)policy.discovered; later changes → policy.material_change)policy.exposure)curl -sS -X POST "https://world-context.vercel.app/v1/policy-trade-watches" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Steel domain watch",
"webhookEndpointId": "whep_...",
"target": {
"type": "domain",
"domain": {
"version": "1",
"names": ["steel manufacturing"]
}
}
}'curl -sS -X POST "https://world-context.vercel.app/v1/policy-trade-watches" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "CN→US steel lane",
"webhookEndpointId": "whep_...",
"target": {
"type": "lane",
"projectTradeLaneId": "ptl_..."
}
}'List / get / soft-delete: GET|DELETE /v1/policy-trade-watches and GET /v1/policy-trade-watches/:watchId. Delete sets status to deleted (repeat DELETE → 404).
Managing policy trade watches from the Projects console UI is still deferred — use REST, the TypeScript SDK, or the Policy Events Postman collection.
Atlas One does not invent your supply chain from policy text. You register known lanes; the platform then matches them against policy scope and stores project-private exposures (and optional impact hypotheses). Scopes: project_trade_lanes:read|write and policy_events:read for exposure reads.
curl -sS -X POST "https://world-context.vercel.app/v1/project-trade-lanes" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"originCountry": "CN",
"destinationCountry": "US",
"mode": "ocean",
"hsCodes": ["7208"],
"label": "CN→US HRC ocean"
}'Preview a match without persisting (handy for demos):
curl -sS -X POST "https://world-context.vercel.app/v1/policy-event-exposures/evaluate" \
-H "Authorization: Bearer $ATLAS_ONE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"policyEventId": "pol_...",
"tradeLanes": [{
"originCountry": "CN",
"destinationCountry": "US",
"mode": "ocean",
"hsCodes": ["7208"]
}]
}'List durable exposures / hypotheses for your project:
curl -sS "https://world-context.vercel.app/v1/policy-event-exposures?policyEventId=$POLICY_EVENT_ID" \ -H "Authorization: Bearer $ATLAS_ONE_API_KEY" curl -sS "https://world-context.vercel.app/v1/policy-impact-hypotheses?policyEventId=$POLICY_EVENT_ID" \ -H "Authorization: Bearer $ATLAS_ONE_API_KEY"
Computing an exposure does not auto-notify. Create a lane-target policy trade watch to receive policy.exposure webhooks after the daily evaluate jobs run.
Troubleshooting, terminology, and quick links — come back here anytime.