1. Create your account
Go to console.nextmoca.com. The page you land on is the sign-in screen, so if you have never been here before, follow its “New here? Create your workspace” link first. Sign up with Google, GitHub, or email. There is no waitlist and no approval step: you land in a workspace immediately. Which workspace, and whether it carries trial credit, depends on your email address. A personal address founds a new workspace of your own, with trial credit on it. A corporate address, once verified, joins the existing workspace for your domain if there already is one, and that workspace’s balance is shared across its members: only its first five members bring a welcome credit into it, so a later joiner starts with no grant of their own. If you land in a workspace with no credit, add credit from the dashboard’s Wallet page, or email hello@nextmoca.com.2. Create an API key
From the dashboard, open Keys and create one. The full secret is shown exactly once, at creation; copy it before you navigate away. A key looks like:np_live_a1B2c3D4e5F6g7H8i9J0kQ7t2mNx
Keys are org-scoped and grant the ability to spend your organisation’s
allowance. Keep them server-side. Never put one in a browser bundle, a mobile
app, or a URL, and never in
request_id, which reaches our logs
(why).3. Set your credentials
export NEEDLEPATH_API_KEY="np_live_…"
export NEEDLEPATH_HOST="api.nextmoca.com"
import os
API_KEY = os.environ["NEEDLEPATH_API_KEY"]
HOST = os.environ["NEEDLEPATH_HOST"]
const API_KEY = process.env.NEEDLEPATH_API_KEY!;
const HOST = process.env.NEEDLEPATH_HOST!;
The calls below are raw HTTP, on purpose: they show you the contract,
which is what you will be reading when something surprises you.If you would rather start with a client,
pip install needlepath or
npm install @nextmoca/needlepath-sdk (both 0.2.0, Apache-2.0) and skip to
Integrations. Both fail open, and neither adds a runtime
dependency.4. Check you can reach the service
curl -sS "https://$NEEDLEPATH_HOST/v1/health" \
-H "Authorization: Bearer $NEEDLEPATH_API_KEY"
{
"status": "ok",
"service": "needlepath-hosted-adapter",
"endpoint": "/v1/context/select",
"default_operating_point": "np-2026-08-r4",
"operating_points": ["np-2026-07-r1", "np-2026-07-r2", "np-2026-08-r3", "np-2026-08-r4"],
"build_id": "3adaafbba408ad50",
"meter_version": "npm-2026-08-r1",
"meter_versions": ["npm-2026-08-r1"],
"price_version": "npp-2026-08-r1",
"currency": "USD"
}
build_id names the engine build currently serving every operating point.
It is not pinned by an operating point and it changes when we deploy, so record
it alongside policy_version whenever you are keeping results to compare later:
see what a label pins.
The value above is what the endpoint returned when this page was last verified;
expect yours to differ.
A 401 here means no usable Authorization header reached us; a 403 means
one did and it was refused. The difference is worth wiring separately; see
Errors.
5. Make a selection
Send every record you are considering, the task they must serve, and the budget they have to fit inside. There are two request shapes. Start with the short one: it is a single paste and it exercises the whole path. The fullrecords[] example follows, in three
languages.
Start here: the smallest call that works
When you just have text, not pre-split records, send it astext instead of
records. Needlepath splits it on blank lines and assigns each resulting
record a content-hash id, so the same paragraph always comes back as the same
id.
This is the request on the homepage, reproduced
here in full so this page stands alone. It is the same billing-dispute scenario
as the fuller records[] example below.
curl https://api.nextmoca.com/v1/context/select \
-H "Authorization: Bearer $NEEDLEPATH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Customer dana@meridiananalytics.com disputes the July invoice: roughly a third of the usage came from a runaway integration on their side, shut down on July 19. They ask for a refund or credit for the excess.\n\nRefund policy: refunds are issued only for platform-caused overcharges verified against receipts. Service credits differ: for customer-caused overuse, credits up to 25% of the disputed amount may be granted once per account per year, applied to the next invoice.\n\nThe Austin office move completes August 15. Badge access transfers automatically, desk assignments are posted on the intranet, the fourth-floor kitchen closes during the transition, visitor parking moves to the north garage, and commuter benefits need updating by August 10 for anyone using transit passes. Facilities will run tours on Friday.\n\nThe Q3 marketing case-study series features five accounts and is scheduled for September publication; drafts are with legal review and the design team is preparing pull quotes, hero images, and a landing page refresh to accompany the launch announcement.\n\nThe support Slack workspace migrates to a new domain next Tuesday. Existing channels and history carry over automatically; only bookmarked links need updating.\n\nQuarterly OKR review is scheduled for the last week of the quarter, with each team submitting a one-page summary two business days ahead.\n\nThe status page gained a subscribe-by-email option this release, alongside the existing RSS feed and webhook.\n\nConference room booking now supports recurring holds up to eight weeks out, previously capped at two.",
"task": {
"prompt": "What portion of the disputed usage was customer-caused, and does that qualify it for a refund or a service credit?"
},
"budget": {
"max_context_tokens": 400
}
}'
external_data, with sha256:<16 hex characters> as its id: the hash of
that record’s own text, so you can recompute it yourself. Eight paragraphs
went in (the dispute, the refund policy, and six unrelated distractors: an
office move, a marketing draft, a Slack migration, an OKR review, a status-page
change, a conference-room policy) and two came back:
{
"selected": [
{
"record_id": "sha256:05a4f2f4dcf7c20e",
"kind": "external_data",
"score": 21.26224751288877,
"reason": "hard context: weighted evidence coverage: keyword overlap",
"selected_tokens": 65
},
{
"record_id": "sha256:b97f5a473b16b541",
"kind": "external_data",
"score": 16.769003449445826,
"reason": "hard context: weighted evidence coverage: keyword overlap",
"selected_tokens": 52
}
],
"policy_version": "np-2026-08-r4",
"records_available": 8,
"records_selected": 2,
"tokens_before": 390,
"tokens_after": 117,
"tokens_saved": 273,
"reduction_ratio": 0.7,
"fallback_used": false
}
This is also a real illustration of gate versus outcome.
The response above is real under
np-2026-08-r4: fallback_used: false,
outcome: "engaged", two records selected. Its gate.reason nonetheless reads
standdown:source_support_missing, because gate is the envelope gate’s own
shadow assessment and not the decision. Branch on outcome, never on
gate.engaged.task.prompt is still required, exactly as with records[]. So is
budget.max_context_tokens: on this path there is no operating-point default
to fall back to, since there is no explicit budget anywhere else in the
request. budget.operating_point stays optional, though you should send it
anyway; whichever one resolves is echoed back in policy_version, same as
always.
Metering runs over the records Needlepath derived from your text, exactly as
if you had sent them yourself under records[], so the receipt in usage is
recomputable the same way described in
How to recompute your own bill.
text and records are mutually exclusive. Sending both is a 400 with
error: "text_and_records_both_set"; pick one per request.The canonical example, in three languages
This is the canonical example used throughout these docs and in the API playground: a support agent deciding a billing dispute from thirty candidate records, most of them plausible support-desk noise (other accounts’ tickets, unrelated policies, ops notes, marketing drafts). It is longer to paste, and it is the one whose response section 6 walks through field by field.curl https://api.nextmoca.com/v1/context/select \
-H "Authorization: Bearer $NEEDLEPATH_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_id": "req-2026-09-03-0001",
"records": [
{
"id": "r-001",
"kind": "tool_result",
"title": "get_invoice(88231)",
"source": "billing-api",
"text": "{\"invoice_id\": 88231, \"account\": \"acct_4415\", \"total_cents\": 432000, \"currency\": \"usd\", \"status\": \"open\", \"issued\": \"2026-07-28\", \"due\": \"2026-08-27\", \"line_items\": [{\"sku\": \"NP-USAGE\", \"desc\": \"Metered input tokens, July\", \"qty\": 4800000, \"unit_price_cents\": 0.009}, {\"sku\": \"NP-SUPPORT\", \"desc\": \"Priority support\", \"qty\": 1, \"unit_price_cents\": 49900}]}"
},
{
"id": "r-002",
"kind": "tool_result",
"title": "get_account(acct_4415)",
"source": "crm-api",
"text": "{\"account_id\": \"acct_4415\", \"name\": \"Meridian Analytics\", \"plan\": \"scale\", \"payment_method\": \"card_visa_6411\", \"delinquent\": false, \"since\": \"2025-11-03\", \"owner\": \"dana@meridiananalytics.com\"}"
},
{
"id": "r-003",
"kind": "external_data",
"title": "Data retention policy v3",
"source": "handbook",
"text": "Customer-supplied records are retained for 30 days after a support ticket closes, then purged. Internal audit logs of access to those records are retained for one year. This policy governs storage, not billing, and has no bearing on refund or credit eligibility."
},
{
"id": "r-004",
"kind": "external_data",
"title": "Refund policy v4, section 2",
"source": "handbook",
"text": "Refunds for metered usage are issued only for platform-caused overcharges verified against receipts. Refunds for subscription line items are prorated to the day of cancellation. All refunds return to the original payment method within 10 business days. Invoices older than 90 days are not eligible."
},
{
"id": "r-005",
"kind": "external_data",
"title": "Refund policy v4, section 3 (exceptions)",
"source": "handbook",
"text": "Exception: accounts in good standing for over 12 months may receive a one-time courtesy refund of up to $500 per calendar year at a support lead'\''s discretion. This exception does not apply to open invoices; the invoice must be paid before a courtesy refund is considered."
},
{
"id": "r-006",
"kind": "tool_result",
"title": "get_usage(acct_4415, july)",
"source": "metering-api",
"text": "{\"account_id\": \"acct_4415\", \"period\": \"2026-07\", \"input_tokens\": 4800000, \"requests\": 1210, \"stand_downs\": 34, \"charged_tokens\": 4646000}"
},
{
"id": "r-007",
"kind": "tool_result",
"title": "get_open_tickets(acct_9902)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5488\", \"subject\": \"API key rotation question\", \"opened\": \"2026-08-02\", \"status\": \"closed\", \"assignee\": \"support-lead-1\"}]}"
},
{
"id": "r-008",
"kind": "user_input",
"title": null,
"source": null,
"text": "Customer (dana@meridiananalytics.com) writes: We were charged $4,320 for July but we believe roughly a third of that usage came from a runaway integration on our side that we shut down on July 19. Can we get a refund or credit for the excess?"
},
{
"id": "r-009",
"kind": "external_data",
"title": "Credit policy v2",
"source": "handbook",
"text": "Service credits differ from refunds: credits may be granted for customer-caused overuse at up to 25% of the disputed amount, once per account per year, and are applied to the next invoice rather than returned to the payment method. Credits require the account owner'\''s written acknowledgement of the cause."
},
{
"id": "r-012",
"kind": "tool_result",
"title": "get_key_traffic(acct_4415, 2026-07-01..2026-07-19)",
"source": "metering-api",
"text": "{\"keys\": [{\"key_id\": \"np_key_a1\", \"requests\": 980, \"user_agent\": \"meridian-batch/2.1\", \"tokens\": 3100000}, {\"key_id\": \"np_key_b2\", \"requests\": 230, \"user_agent\": \"meridian-app/1.4\", \"tokens\": 1700000}], \"note\": \"np_key_a1 traffic stops 2026-07-19T14:02Z\"}"
},
{
"id": "r-013",
"kind": "external_data",
"title": "Q2 headcount planning notes",
"source": "internal-ops",
"text": "The Q2 headcount review covered open requisitions across support and account management. Two backfills were approved pending final budget sign-off from finance; the rest carry into Q3."
},
{
"id": "r-014",
"kind": "tool_result",
"title": "get_invoice(55102)",
"source": "billing-api",
"text": "{\"invoice_id\": 55102, \"account\": \"acct_2210\", \"total_cents\": 18900, \"currency\": \"usd\", \"status\": \"paid\", \"issued\": \"2026-07-15\", \"due\": \"2026-08-14\"}"
},
{
"id": "r-015",
"kind": "external_data",
"title": "Q3 marketing newsletter draft",
"source": "marketing",
"text": "Meridian Analytics is one of several accounts featured in our upcoming case-study series. The draft highlights their 40% pipeline acceleration after adopting the platform. Publication is scheduled for September."
},
{
"id": "r-016",
"kind": "external_data",
"title": "Office move logistics",
"source": "internal-ops",
"text": "The Austin office move completes August 15. Badge access transfers automatically. Update your commuter benefits by August 10 if you use transit passes."
},
{
"id": "r-017",
"kind": "tool_result",
"title": "get_open_tickets(acct_4415)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5521\", \"subject\": \"July usage dispute\", \"opened\": \"2026-08-05\", \"status\": \"open\", \"assignee\": \"support-lead-2\"}]}"
},
{
"id": "r-018",
"kind": "tool_result",
"title": "get_open_tickets(acct_2210)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5502\", \"subject\": \"Login issue after SSO migration\", \"opened\": \"2026-08-01\", \"status\": \"closed\", \"assignee\": \"support-lead-3\"}]}"
},
{
"id": "r-019",
"kind": "external_data",
"title": "Vacation and PTO policy",
"source": "handbook",
"text": "Full-time staff accrue 15 days of PTO per year, front-loaded each January. Unused days above a 5-day carryover are paid out at year end. This policy applies to internal staff only and has no customer-facing effect."
},
{
"id": "r-020",
"kind": "external_data",
"title": "Runbook: rotating a compromised API key",
"source": "ops-wiki",
"text": "If a key is suspected compromised: revoke it immediately from the dashboard, mint a replacement, and audit the last 30 days of request logs for the revoked key. Notify the account owner within one business hour. This does not apply to routine billing disputes."
},
{
"id": "r-021",
"kind": "llm_response",
"text": "I'\''ve pulled up account acct_4415 and I'\''m reviewing the July invoice and usage history now. One moment while I check the key-level traffic breakdown."
},
{
"id": "r-022",
"kind": "external_data",
"title": "Customer advisory board Q4 invite draft",
"source": "marketing",
"text": "Draft invitation for the Q4 customer advisory board: eight accounts, half-day session, catered lunch, and a closing networking hour. Invitations go out via the account team, not support."
},
{
"id": "r-023",
"kind": "tool_result",
"title": "get_account(acct_9902)",
"source": "crm-api",
"text": "{\"account_id\": \"acct_9902\", \"name\": \"Colby Fixtures\", \"plan\": \"growth\", \"payment_method\": \"card_mc_2290\", \"delinquent\": false, \"since\": \"2026-01-14\", \"owner\": \"ops@colbyfixtures.com\"}"
},
{
"id": "r-026",
"kind": "tool_result",
"title": "get_open_tickets(acct_5511)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5510\", \"subject\": \"Feature request: CSV export for usage analytics\", \"opened\": \"2026-08-03\", \"status\": \"open\", \"assignee\": \"support-lead-1\"}]}"
},
{
"id": "r-027",
"kind": "external_data",
"title": "Q3 all-hands agenda",
"source": "internal-ops",
"text": "Agenda: Q3 numbers recap, the Austin office move timeline, two customer case studies, and a Q&A. Scheduled for the last Thursday of the quarter, recorded for anyone who cannot attend live."
},
{
"id": "r-029",
"kind": "external_data",
"title": "Marketing site refresh, visual only",
"source": "marketing",
"text": "The marketing homepage and case-study pages move to a refreshed visual design next month. Existing URLs and content are unchanged; this is a styling pass only."
},
{
"id": "r-031",
"kind": "tool_result",
"title": "get_open_tickets(acct_6630)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5477\", \"subject\": \"Onboarding walkthrough request\", \"opened\": \"2026-07-30\", \"status\": \"closed\", \"assignee\": \"support-lead-3\"}]}"
},
{
"id": "r-032",
"kind": "external_data",
"title": "On-call rotation for September",
"source": "internal-ops",
"text": "September on-call: week 1 support-lead-1, week 2 support-lead-2, week 3 support-lead-3, week 4 support-lead-1. Swap requests go through the usual calendar invite at least 48 hours ahead."
},
{
"id": "r-033",
"kind": "external_data",
"title": "Partner co-marketing webinar recap",
"source": "marketing",
"text": "Tuesday'\''s co-marketing webinar drew 140 live attendees, with a recording queued for the newsletter. Follow-up survey responses are due back from the partner team by end of week."
},
{
"id": "r-034",
"kind": "external_data",
"title": "Conference room booking policy",
"source": "handbook",
"text": "Rooms can be held up to 90 days ahead through the office system. No-shows for two consecutive bookings lose booking privileges for 30 days. This policy is unrelated to customer accounts or billing."
},
{
"id": "r-035",
"kind": "external_data",
"title": "Blog editorial calendar, Q4",
"source": "marketing",
"text": "Q4 blog calendar: a launch recap in week 1, two customer spotlights in weeks 3 and 6, and a year-in-review post closing out the quarter. Drafts are due to editorial ten business days before publication."
},
{
"id": "r-036",
"kind": "external_data",
"title": "Kitchen and supplies restock schedule",
"source": "internal-ops",
"text": "Snack and coffee restocks happen every Monday and Thursday. Submit special requests through the office system by end of day Friday for the following week."
}
],
"task": {
"prompt": "What does the evidence show about invoice 88231: is the disputed usage customer-caused, and does it qualify for a refund or a service credit?",
"tool_name": "resolve_billing_dispute"
},
"budget": {
"max_context_tokens": 900,
"operating_point": "np-2026-08-r4"
},
"render": true,
"render_format": "plain",
"return_per_record": true
}'
import os
import requests
payload = {
"request_id": "req-2026-09-03-0001",
"records": [
{
"id": "r-001",
"kind": "tool_result",
"title": "get_invoice(88231)",
"source": "billing-api",
"text": "{\"invoice_id\": 88231, \"account\": \"acct_4415\", \"total_cents\": 432000, \"currency\": \"usd\", \"status\": \"open\", \"issued\": \"2026-07-28\", \"due\": \"2026-08-27\", \"line_items\": [{\"sku\": \"NP-USAGE\", \"desc\": \"Metered input tokens, July\", \"qty\": 4800000, \"unit_price_cents\": 0.009}, {\"sku\": \"NP-SUPPORT\", \"desc\": \"Priority support\", \"qty\": 1, \"unit_price_cents\": 49900}]}",
},
{
"id": "r-002",
"kind": "tool_result",
"title": "get_account(acct_4415)",
"source": "crm-api",
"text": "{\"account_id\": \"acct_4415\", \"name\": \"Meridian Analytics\", \"plan\": \"scale\", \"payment_method\": \"card_visa_6411\", \"delinquent\": false, \"since\": \"2025-11-03\", \"owner\": \"dana@meridiananalytics.com\"}",
},
{
"id": "r-003",
"kind": "external_data",
"title": "Data retention policy v3",
"source": "handbook",
"text": "Customer-supplied records are retained for 30 days after a support ticket closes, then purged. Internal audit logs of access to those records are retained for one year. This policy governs storage, not billing, and has no bearing on refund or credit eligibility.",
},
{
"id": "r-004",
"kind": "external_data",
"title": "Refund policy v4, section 2",
"source": "handbook",
"text": "Refunds for metered usage are issued only for platform-caused overcharges verified against receipts. Refunds for subscription line items are prorated to the day of cancellation. All refunds return to the original payment method within 10 business days. Invoices older than 90 days are not eligible.",
},
{
"id": "r-005",
"kind": "external_data",
"title": "Refund policy v4, section 3 (exceptions)",
"source": "handbook",
"text": "Exception: accounts in good standing for over 12 months may receive a one-time courtesy refund of up to $500 per calendar year at a support lead's discretion. This exception does not apply to open invoices; the invoice must be paid before a courtesy refund is considered.",
},
{
"id": "r-006",
"kind": "tool_result",
"title": "get_usage(acct_4415, july)",
"source": "metering-api",
"text": "{\"account_id\": \"acct_4415\", \"period\": \"2026-07\", \"input_tokens\": 4800000, \"requests\": 1210, \"stand_downs\": 34, \"charged_tokens\": 4646000}",
},
{
"id": "r-007",
"kind": "tool_result",
"title": "get_open_tickets(acct_9902)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5488\", \"subject\": \"API key rotation question\", \"opened\": \"2026-08-02\", \"status\": \"closed\", \"assignee\": \"support-lead-1\"}]}",
},
{
"id": "r-008",
"kind": "user_input",
"title": None,
"source": None,
"text": "Customer (dana@meridiananalytics.com) writes: We were charged $4,320 for July but we believe roughly a third of that usage came from a runaway integration on our side that we shut down on July 19. Can we get a refund or credit for the excess?",
},
{
"id": "r-009",
"kind": "external_data",
"title": "Credit policy v2",
"source": "handbook",
"text": "Service credits differ from refunds: credits may be granted for customer-caused overuse at up to 25% of the disputed amount, once per account per year, and are applied to the next invoice rather than returned to the payment method. Credits require the account owner's written acknowledgement of the cause.",
},
{
"id": "r-012",
"kind": "tool_result",
"title": "get_key_traffic(acct_4415, 2026-07-01..2026-07-19)",
"source": "metering-api",
"text": "{\"keys\": [{\"key_id\": \"np_key_a1\", \"requests\": 980, \"user_agent\": \"meridian-batch/2.1\", \"tokens\": 3100000}, {\"key_id\": \"np_key_b2\", \"requests\": 230, \"user_agent\": \"meridian-app/1.4\", \"tokens\": 1700000}], \"note\": \"np_key_a1 traffic stops 2026-07-19T14:02Z\"}",
},
{
"id": "r-013",
"kind": "external_data",
"title": "Q2 headcount planning notes",
"source": "internal-ops",
"text": "The Q2 headcount review covered open requisitions across support and account management. Two backfills were approved pending final budget sign-off from finance; the rest carry into Q3.",
},
{
"id": "r-014",
"kind": "tool_result",
"title": "get_invoice(55102)",
"source": "billing-api",
"text": "{\"invoice_id\": 55102, \"account\": \"acct_2210\", \"total_cents\": 18900, \"currency\": \"usd\", \"status\": \"paid\", \"issued\": \"2026-07-15\", \"due\": \"2026-08-14\"}",
},
{
"id": "r-015",
"kind": "external_data",
"title": "Q3 marketing newsletter draft",
"source": "marketing",
"text": "Meridian Analytics is one of several accounts featured in our upcoming case-study series. The draft highlights their 40% pipeline acceleration after adopting the platform. Publication is scheduled for September.",
},
{
"id": "r-016",
"kind": "external_data",
"title": "Office move logistics",
"source": "internal-ops",
"text": "The Austin office move completes August 15. Badge access transfers automatically. Update your commuter benefits by August 10 if you use transit passes.",
},
{
"id": "r-017",
"kind": "tool_result",
"title": "get_open_tickets(acct_4415)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5521\", \"subject\": \"July usage dispute\", \"opened\": \"2026-08-05\", \"status\": \"open\", \"assignee\": \"support-lead-2\"}]}",
},
{
"id": "r-018",
"kind": "tool_result",
"title": "get_open_tickets(acct_2210)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5502\", \"subject\": \"Login issue after SSO migration\", \"opened\": \"2026-08-01\", \"status\": \"closed\", \"assignee\": \"support-lead-3\"}]}",
},
{
"id": "r-019",
"kind": "external_data",
"title": "Vacation and PTO policy",
"source": "handbook",
"text": "Full-time staff accrue 15 days of PTO per year, front-loaded each January. Unused days above a 5-day carryover are paid out at year end. This policy applies to internal staff only and has no customer-facing effect.",
},
{
"id": "r-020",
"kind": "external_data",
"title": "Runbook: rotating a compromised API key",
"source": "ops-wiki",
"text": "If a key is suspected compromised: revoke it immediately from the dashboard, mint a replacement, and audit the last 30 days of request logs for the revoked key. Notify the account owner within one business hour. This does not apply to routine billing disputes.",
},
{
"id": "r-021",
"kind": "llm_response",
"text": "I've pulled up account acct_4415 and I'm reviewing the July invoice and usage history now. One moment while I check the key-level traffic breakdown.",
},
{
"id": "r-022",
"kind": "external_data",
"title": "Customer advisory board Q4 invite draft",
"source": "marketing",
"text": "Draft invitation for the Q4 customer advisory board: eight accounts, half-day session, catered lunch, and a closing networking hour. Invitations go out via the account team, not support.",
},
{
"id": "r-023",
"kind": "tool_result",
"title": "get_account(acct_9902)",
"source": "crm-api",
"text": "{\"account_id\": \"acct_9902\", \"name\": \"Colby Fixtures\", \"plan\": \"growth\", \"payment_method\": \"card_mc_2290\", \"delinquent\": false, \"since\": \"2026-01-14\", \"owner\": \"ops@colbyfixtures.com\"}",
},
{
"id": "r-026",
"kind": "tool_result",
"title": "get_open_tickets(acct_5511)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5510\", \"subject\": \"Feature request: CSV export for usage analytics\", \"opened\": \"2026-08-03\", \"status\": \"open\", \"assignee\": \"support-lead-1\"}]}",
},
{
"id": "r-027",
"kind": "external_data",
"title": "Q3 all-hands agenda",
"source": "internal-ops",
"text": "Agenda: Q3 numbers recap, the Austin office move timeline, two customer case studies, and a Q&A. Scheduled for the last Thursday of the quarter, recorded for anyone who cannot attend live.",
},
{
"id": "r-029",
"kind": "external_data",
"title": "Marketing site refresh, visual only",
"source": "marketing",
"text": "The marketing homepage and case-study pages move to a refreshed visual design next month. Existing URLs and content are unchanged; this is a styling pass only.",
},
{
"id": "r-031",
"kind": "tool_result",
"title": "get_open_tickets(acct_6630)",
"source": "support-api",
"text": "{\"tickets\": [{\"id\": \"T-5477\", \"subject\": \"Onboarding walkthrough request\", \"opened\": \"2026-07-30\", \"status\": \"closed\", \"assignee\": \"support-lead-3\"}]}",
},
{
"id": "r-032",
"kind": "external_data",
"title": "On-call rotation for September",
"source": "internal-ops",
"text": "September on-call: week 1 support-lead-1, week 2 support-lead-2, week 3 support-lead-3, week 4 support-lead-1. Swap requests go through the usual calendar invite at least 48 hours ahead.",
},
{
"id": "r-033",
"kind": "external_data",
"title": "Partner co-marketing webinar recap",
"source": "marketing",
"text": "Tuesday's co-marketing webinar drew 140 live attendees, with a recording queued for the newsletter. Follow-up survey responses are due back from the partner team by end of week.",
},
{
"id": "r-034",
"kind": "external_data",
"title": "Conference room booking policy",
"source": "handbook",
"text": "Rooms can be held up to 90 days ahead through the office system. No-shows for two consecutive bookings lose booking privileges for 30 days. This policy is unrelated to customer accounts or billing.",
},
{
"id": "r-035",
"kind": "external_data",
"title": "Blog editorial calendar, Q4",
"source": "marketing",
"text": "Q4 blog calendar: a launch recap in week 1, two customer spotlights in weeks 3 and 6, and a year-in-review post closing out the quarter. Drafts are due to editorial ten business days before publication.",
},
{
"id": "r-036",
"kind": "external_data",
"title": "Kitchen and supplies restock schedule",
"source": "internal-ops",
"text": "Snack and coffee restocks happen every Monday and Thursday. Submit special requests through the office system by end of day Friday for the following week.",
},
],
"task": {
"prompt": "What does the evidence show about invoice 88231: is the disputed usage customer-caused, and does it qualify for a refund or a service credit?",
"tool_name": "resolve_billing_dispute",
},
"budget": {
"max_context_tokens": 900,
"operating_point": "np-2026-08-r4",
},
"render": True,
"render_format": "plain",
"return_per_record": True,
}
r = requests.post(
"https://api.nextmoca.com/v1/context/select",
headers={"Authorization": f"Bearer {os.environ['NEEDLEPATH_API_KEY']}"},
json=payload,
timeout=10,
)
r.raise_for_status()
result = r.json()
print(result["records_selected"], "selected,", result["tokens_saved"], "tokens saved")
const payload = {
request_id: "req-2026-09-03-0001",
records: [
{
id: "r-001",
kind: "tool_result",
title: "get_invoice(88231)",
source: "billing-api",
text: "{\"invoice_id\": 88231, \"account\": \"acct_4415\", \"total_cents\": 432000, \"currency\": \"usd\", \"status\": \"open\", \"issued\": \"2026-07-28\", \"due\": \"2026-08-27\", \"line_items\": [{\"sku\": \"NP-USAGE\", \"desc\": \"Metered input tokens, July\", \"qty\": 4800000, \"unit_price_cents\": 0.009}, {\"sku\": \"NP-SUPPORT\", \"desc\": \"Priority support\", \"qty\": 1, \"unit_price_cents\": 49900}]}",
},
{
id: "r-002",
kind: "tool_result",
title: "get_account(acct_4415)",
source: "crm-api",
text: "{\"account_id\": \"acct_4415\", \"name\": \"Meridian Analytics\", \"plan\": \"scale\", \"payment_method\": \"card_visa_6411\", \"delinquent\": false, \"since\": \"2025-11-03\", \"owner\": \"dana@meridiananalytics.com\"}",
},
{
id: "r-003",
kind: "external_data",
title: "Data retention policy v3",
source: "handbook",
text: "Customer-supplied records are retained for 30 days after a support ticket closes, then purged. Internal audit logs of access to those records are retained for one year. This policy governs storage, not billing, and has no bearing on refund or credit eligibility.",
},
{
id: "r-004",
kind: "external_data",
title: "Refund policy v4, section 2",
source: "handbook",
text: "Refunds for metered usage are issued only for platform-caused overcharges verified against receipts. Refunds for subscription line items are prorated to the day of cancellation. All refunds return to the original payment method within 10 business days. Invoices older than 90 days are not eligible.",
},
{
id: "r-005",
kind: "external_data",
title: "Refund policy v4, section 3 (exceptions)",
source: "handbook",
text: "Exception: accounts in good standing for over 12 months may receive a one-time courtesy refund of up to $500 per calendar year at a support lead's discretion. This exception does not apply to open invoices; the invoice must be paid before a courtesy refund is considered.",
},
{
id: "r-006",
kind: "tool_result",
title: "get_usage(acct_4415, july)",
source: "metering-api",
text: "{\"account_id\": \"acct_4415\", \"period\": \"2026-07\", \"input_tokens\": 4800000, \"requests\": 1210, \"stand_downs\": 34, \"charged_tokens\": 4646000}",
},
{
id: "r-007",
kind: "tool_result",
title: "get_open_tickets(acct_9902)",
source: "support-api",
text: "{\"tickets\": [{\"id\": \"T-5488\", \"subject\": \"API key rotation question\", \"opened\": \"2026-08-02\", \"status\": \"closed\", \"assignee\": \"support-lead-1\"}]}",
},
{
id: "r-008",
kind: "user_input",
title: null,
source: null,
text: "Customer (dana@meridiananalytics.com) writes: We were charged $4,320 for July but we believe roughly a third of that usage came from a runaway integration on our side that we shut down on July 19. Can we get a refund or credit for the excess?",
},
{
id: "r-009",
kind: "external_data",
title: "Credit policy v2",
source: "handbook",
text: "Service credits differ from refunds: credits may be granted for customer-caused overuse at up to 25% of the disputed amount, once per account per year, and are applied to the next invoice rather than returned to the payment method. Credits require the account owner's written acknowledgement of the cause.",
},
{
id: "r-012",
kind: "tool_result",
title: "get_key_traffic(acct_4415, 2026-07-01..2026-07-19)",
source: "metering-api",
text: "{\"keys\": [{\"key_id\": \"np_key_a1\", \"requests\": 980, \"user_agent\": \"meridian-batch/2.1\", \"tokens\": 3100000}, {\"key_id\": \"np_key_b2\", \"requests\": 230, \"user_agent\": \"meridian-app/1.4\", \"tokens\": 1700000}], \"note\": \"np_key_a1 traffic stops 2026-07-19T14:02Z\"}",
},
{
id: "r-013",
kind: "external_data",
title: "Q2 headcount planning notes",
source: "internal-ops",
text: "The Q2 headcount review covered open requisitions across support and account management. Two backfills were approved pending final budget sign-off from finance; the rest carry into Q3.",
},
{
id: "r-014",
kind: "tool_result",
title: "get_invoice(55102)",
source: "billing-api",
text: "{\"invoice_id\": 55102, \"account\": \"acct_2210\", \"total_cents\": 18900, \"currency\": \"usd\", \"status\": \"paid\", \"issued\": \"2026-07-15\", \"due\": \"2026-08-14\"}",
},
{
id: "r-015",
kind: "external_data",
title: "Q3 marketing newsletter draft",
source: "marketing",
text: "Meridian Analytics is one of several accounts featured in our upcoming case-study series. The draft highlights their 40% pipeline acceleration after adopting the platform. Publication is scheduled for September.",
},
{
id: "r-016",
kind: "external_data",
title: "Office move logistics",
source: "internal-ops",
text: "The Austin office move completes August 15. Badge access transfers automatically. Update your commuter benefits by August 10 if you use transit passes.",
},
{
id: "r-017",
kind: "tool_result",
title: "get_open_tickets(acct_4415)",
source: "support-api",
text: "{\"tickets\": [{\"id\": \"T-5521\", \"subject\": \"July usage dispute\", \"opened\": \"2026-08-05\", \"status\": \"open\", \"assignee\": \"support-lead-2\"}]}",
},
{
id: "r-018",
kind: "tool_result",
title: "get_open_tickets(acct_2210)",
source: "support-api",
text: "{\"tickets\": [{\"id\": \"T-5502\", \"subject\": \"Login issue after SSO migration\", \"opened\": \"2026-08-01\", \"status\": \"closed\", \"assignee\": \"support-lead-3\"}]}",
},
{
id: "r-019",
kind: "external_data",
title: "Vacation and PTO policy",
source: "handbook",
text: "Full-time staff accrue 15 days of PTO per year, front-loaded each January. Unused days above a 5-day carryover are paid out at year end. This policy applies to internal staff only and has no customer-facing effect.",
},
{
id: "r-020",
kind: "external_data",
title: "Runbook: rotating a compromised API key",
source: "ops-wiki",
text: "If a key is suspected compromised: revoke it immediately from the dashboard, mint a replacement, and audit the last 30 days of request logs for the revoked key. Notify the account owner within one business hour. This does not apply to routine billing disputes.",
},
{
id: "r-021",
kind: "llm_response",
text: "I've pulled up account acct_4415 and I'm reviewing the July invoice and usage history now. One moment while I check the key-level traffic breakdown.",
},
{
id: "r-022",
kind: "external_data",
title: "Customer advisory board Q4 invite draft",
source: "marketing",
text: "Draft invitation for the Q4 customer advisory board: eight accounts, half-day session, catered lunch, and a closing networking hour. Invitations go out via the account team, not support.",
},
{
id: "r-023",
kind: "tool_result",
title: "get_account(acct_9902)",
source: "crm-api",
text: "{\"account_id\": \"acct_9902\", \"name\": \"Colby Fixtures\", \"plan\": \"growth\", \"payment_method\": \"card_mc_2290\", \"delinquent\": false, \"since\": \"2026-01-14\", \"owner\": \"ops@colbyfixtures.com\"}",
},
{
id: "r-026",
kind: "tool_result",
title: "get_open_tickets(acct_5511)",
source: "support-api",
text: "{\"tickets\": [{\"id\": \"T-5510\", \"subject\": \"Feature request: CSV export for usage analytics\", \"opened\": \"2026-08-03\", \"status\": \"open\", \"assignee\": \"support-lead-1\"}]}",
},
{
id: "r-027",
kind: "external_data",
title: "Q3 all-hands agenda",
source: "internal-ops",
text: "Agenda: Q3 numbers recap, the Austin office move timeline, two customer case studies, and a Q&A. Scheduled for the last Thursday of the quarter, recorded for anyone who cannot attend live.",
},
{
id: "r-029",
kind: "external_data",
title: "Marketing site refresh, visual only",
source: "marketing",
text: "The marketing homepage and case-study pages move to a refreshed visual design next month. Existing URLs and content are unchanged; this is a styling pass only.",
},
{
id: "r-031",
kind: "tool_result",
title: "get_open_tickets(acct_6630)",
source: "support-api",
text: "{\"tickets\": [{\"id\": \"T-5477\", \"subject\": \"Onboarding walkthrough request\", \"opened\": \"2026-07-30\", \"status\": \"closed\", \"assignee\": \"support-lead-3\"}]}",
},
{
id: "r-032",
kind: "external_data",
title: "On-call rotation for September",
source: "internal-ops",
text: "September on-call: week 1 support-lead-1, week 2 support-lead-2, week 3 support-lead-3, week 4 support-lead-1. Swap requests go through the usual calendar invite at least 48 hours ahead.",
},
{
id: "r-033",
kind: "external_data",
title: "Partner co-marketing webinar recap",
source: "marketing",
text: "Tuesday's co-marketing webinar drew 140 live attendees, with a recording queued for the newsletter. Follow-up survey responses are due back from the partner team by end of week.",
},
{
id: "r-034",
kind: "external_data",
title: "Conference room booking policy",
source: "handbook",
text: "Rooms can be held up to 90 days ahead through the office system. No-shows for two consecutive bookings lose booking privileges for 30 days. This policy is unrelated to customer accounts or billing.",
},
{
id: "r-035",
kind: "external_data",
title: "Blog editorial calendar, Q4",
source: "marketing",
text: "Q4 blog calendar: a launch recap in week 1, two customer spotlights in weeks 3 and 6, and a year-in-review post closing out the quarter. Drafts are due to editorial ten business days before publication.",
},
{
id: "r-036",
kind: "external_data",
title: "Kitchen and supplies restock schedule",
source: "internal-ops",
text: "Snack and coffee restocks happen every Monday and Thursday. Submit special requests through the office system by end of day Friday for the following week.",
},
],
task: {
prompt: "What does the evidence show about invoice 88231: is the disputed usage customer-caused, and does it qualify for a refund or a service credit?",
tool_name: "resolve_billing_dispute",
},
budget: {
max_context_tokens: 900,
operating_point: "np-2026-08-r4",
},
render: true,
render_format: "plain",
return_per_record: true,
};
const res = await fetch("https://api.nextmoca.com/v1/context/select", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NEEDLEPATH_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const result = await res.json();
console.log(result.records_selected, "selected,", result.tokens_saved, "tokens saved");
This is the exact request behind the API playground example
named
engages. If you would rather click than paste, try it there; your key
prefills straight into the header.6. Read the response
{
"request_id": "req-2026-09-03-0001",
"rendered_context": "Relevant State\n\n1. Credit policy v2 (handbook)\nService credits differ from refunds: credits may be granted for customer-caused overuse at up to 25% of the disputed amount, once per account per year, and are applied to the next invoice rather than returned to the payment method.\nCredits require the account owner's written acknowledgement of the cause.\n\n2. user_input\nCustomer (dana@meridiananalytics.com) writes: We were charged $4,320 for July but we believe roughly a third of that usage came from a runaway integration on our side that we shut down on July 19. Can we get a refund or credit for the excess?\n\n3. Refund policy v4, section 3 (exceptions) (handbook)\nException: accounts in good standing for over 12 months may receive a one-time courtesy refund of up to $500 per calendar year at a support lead's discretion. This exception does not apply to open invoices; the invoice must be paid before a courtesy refund is considered.\n\n4. Refund policy v4, section 2 (handbook)\nRefunds for metered usage are issued only for platform-caused overcharges verified against receipts. Refunds for subscription line items are prorated to the day of cancellation. All refunds return to the original payment method within 10 business days. Invoices older than 90 days are not eligible.\n\n5. llm_response\nI've pulled up account acct_4415 and I'm reviewing the July invoice and usage history now. One moment while I check the key-level traffic breakdown.",
"policy_version": "np-2026-08-r4",
"outcome": "engaged",
"selected": [
{
"record_id": "r-009",
"kind": "external_data",
"title": "Credit policy v2",
"source": "handbook",
"score": 32.658829095499584,
"reason": "hard context: answer-bearing evidence: keyword overlap",
"excerpt": "Service credits differ from refunds: credits may be granted for customer-caused overuse at up to 25% of the disputed amount, once per account per year, and are applied to the next invoice rather than returned to the payment method.\nCredits require the account owner's written acknowledgement of the cause.",
"excerpt_format": "plain",
"selected_tokens": 76
},
{
"record_id": "r-008",
"kind": "user_input",
"title": null,
"source": null,
"score": 54.106697605930485,
"reason": "hard context: weighted evidence coverage: current request; keyword overlap; semantic tag overlap",
"excerpt": "Customer (dana@meridiananalytics.com) writes: We were charged $4,320 for July but we believe roughly a third of that usage came from a runaway integration on our side that we shut down on July 19. Can we get a refund or credit for the excess?",
"excerpt_format": "plain",
"selected_tokens": 60
},
{
"record_id": "r-005",
"kind": "external_data",
"title": "Refund policy v4, section 3 (exceptions)",
"source": "handbook",
"score": 13.458636537340059,
"reason": "hard context: weighted evidence coverage: keyword overlap",
"excerpt": "Exception: accounts in good standing for over 12 months may receive a one-time courtesy refund of up to $500 per calendar year at a support lead's discretion. This exception does not apply to open invoices; the invoice must be paid before a courtesy refund is considered.",
"excerpt_format": "plain",
"selected_tokens": 67
},
{
"record_id": "r-004",
"kind": "external_data",
"title": "Refund policy v4, section 2",
"source": "handbook",
"score": 14.01558939758398,
"reason": "hard context: recent relevant result: keyword overlap",
"excerpt": "Refunds for metered usage are issued only for platform-caused overcharges verified against receipts. Refunds for subscription line items are prorated to the day of cancellation. All refunds return to the original payment method within 10 business days. Invoices older than 90 days are not eligible.",
"excerpt_format": "plain",
"selected_tokens": 74
},
{
"record_id": "r-021",
"kind": "llm_response",
"title": null,
"source": null,
"score": 14.644259731672935,
"reason": "soft context: keyword overlap",
"excerpt": "I've pulled up account acct_4415 and I'm reviewing the July invoice and usage history now. One moment while I check the key-level traffic breakdown.",
"excerpt_format": "plain",
"selected_tokens": 37
}
],
"tokens_before": 1775,
"tokens_after": 314,
"tokens_saved": 1461,
"records_available": 30,
"records_selected": 5,
"fallback_used": false,
"selection_error": null,
"engine_latency_ms": 7.534137000220653,
"budget_tokens": 900,
"attempted_budget_tokens": [
900
],
"reduction_ratio": 0.8230985915492958,
"safety": {
"selection_safe": true,
"fallback_required": false,
"fallback_reason": "",
"coverage_score": 1.0,
"evidence_shape": "exact_anchor_lookup",
"evidence_terms": null,
"repair_reasons": []
},
"gate": {
"engaged": true,
"reason": "engage:delivered_support_complete",
"signals": {
"n_candidates": 21,
"high_drift": false
}
},
"format_metrics": {
"context_format": "plain",
"formatted_context_tokens": 361,
"plain_context_tokens": 361,
"toon_context_tokens": null,
"toon_applied": false,
"whole_context_toon_applied": false,
"structured_toon_excerpts": 0,
"structured_toon_tokens_saved": 0,
"toon_tokens_saved_vs_plain": 0
},
"usage": {
"meter_version": "npm-2026-08-r1",
"outcome": "engaged",
"input_tokens": 1998,
"charge_multiplier": "1.0",
"price_version": "npp-2026-08-r1",
"currency": "USD"
}
}
tokens_saved: 1461 out of tokens_before: 1775.
engine_latency_ms will not match yours. It is a per-call measurement and
varies on every request. Everything else here (the selection, the token counts,
reduction_ratio) is what this request returned on the engine build named in
/v1/health when this page was last verified, and repeated calls on that build
return it identically. A later build can move it without any operating point
having changed; see
what a label pins.That the credit-policy excerpt (r-009, score 32.66) is listed before
the customer’s own message (r-008, score 54.11), despite scoring lower, is
not a mistake in the example: selected[] order is not sorted by score. It
is what this configuration returns on this input, and it is a fair
illustration of why you spot-check selected[] against your own expectations
rather than trusting an aggregate savings number or assuming list order tracks
score.| Field | Read it as |
|---|---|
rendered_context | The block to put in your prompt. render: false is meant to suppress it and is currently ignored. Discard it client-side if you assemble the prompt yourself from selected[]. |
selected[] | Which records made it, with a score and a reason. excerpt is your text verbatim. |
fallback_used | true means the engine stood aside and handed your context back essentially intact. A normal outcome, not an error. See a stand-down is a correct outcome. |
policy_version | The frozen configuration that actually ran. Log it with your results, alongside build_id from /v1/health. |
tokens_before and tokens_after are the engine’s own accounting, useful
for seeing how much a selection moved. They are not the billing quantity
(that is the usage block), and cannot be recomputed from your payload alone.
See How to recompute your own bill.7. Fail open
This is the part to get right before you ship. Selection is an optimisation, so a failure must degrade to no optimisation, never to an empty prompt.def select_context(records, prompt, *, budget=4000):
"""Returns a rendered context block, or None to mean 'send everything'."""
try:
response = requests.post(
f"https://{HOST}/v1/context/select",
headers={"Authorization": f"Bearer {API_KEY}",
"content-type": "application/json"},
json={
"request_id": new_request_id(),
"records": records,
"task": {"prompt": prompt},
"budget": {"max_context_tokens": budget,
"operating_point": "np-2026-08-r4"},
},
timeout=10,
)
response.raise_for_status()
result = response.json()
except Exception:
# Timeout, non-2xx, unparseable body: send what you were going to send.
return None
# An empty selection is also a pass-through case, not a valid prompt.
if result.get("records_selected", 0) == 0 or not result.get("rendered_context"):
return None
return result["rendered_context"]
context = select_context(records, prompt) or render_everything(records)
async function selectContext(
records: unknown[],
prompt: string,
budget = 4000,
): Promise<string | null> {
try {
const response = await fetch(`https://${HOST}/v1/context/select`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"content-type": "application/json",
},
body: JSON.stringify({
request_id: newRequestId(),
records,
task: { prompt },
budget: {
max_context_tokens: budget,
operating_point: "np-2026-08-r4",
},
}),
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) return null;
const result = await response.json();
// An empty selection is a pass-through case, not a valid prompt.
if (!result.records_selected || !result.rendered_context) return null;
return result.rendered_context as string;
} catch {
return null;
}
}
const context = (await selectContext(records, prompt)) ?? renderEverything(records);
Do not retry a
403: none of its causes are transient. Do retry a 429 with
exponential backoff and jitter, and a 5xx only if the request is unchanged.
Errors has the full table.8. Watch it land on the dashboard
Open console.nextmoca.com/needlepath/dashboard to see your calls, tokens saved, and remaining trial credit. Usage typically appears within about an hour of a call: billing reconciles hourly, so do not expect the dashboard to move the instant a response comes back.Next
Records and tasks
What to put in each field, and what each one buys you.
Adaptive budget
Let the engine escalate its own budget instead of guessing one.
Limits
Rate, quota and the one exact ceiling.
Authentication
Key format, rotation, and what a leaked key means.