MedBridge Sales Ops API Skill
Overview
This skill covers interacting with the MedBridge Sales Ops API to produce two types of decision packages:
- Quote Decision Package — pricing, freight comparison, transport recommendation, and policy warnings.
- Engagement Reconciliation — opportunity-to-milestone reconciliation, revenue recognition, invoice/payment status, and CRM follow-up routing.
The API is read-only. Return only valid JSON matching the provided answer_template.json.
API Base URL
Use the base URL provided by the environment:
GDPEVO_ENV_BASE_URL or API_BASE_URL (e.g., http://34.46.77.124:8002)
- Do not use
localhost or 127.0.0.1 unless the remote URL itself points there.
Discovery Endpoint
GET /api returns the list of collections and supported endpoints. Collections:
customers, events, freight-quotes, invoices, opportunities, payments, policies, products, quotes, revenue-journals, rfqs, vouchers
GET /api/search?q=<text> for free-text search
Access Patterns
- List all:
GET /api/<collection> → { collection, count, records: [...] }
- By ID:
GET /api/<collection>/<id> → single record or { error, message }
Task Type 1: Quote Decision Package
Required API Calls
GET /api/quotes/<quote_id> — confirmed quantity, product code, customer_id, quote_date, status
GET /api/customers/<customer_id> — customer name, region, payment terms overrides
GET /api/products/<product_code> — price tiers, lead time, shelf life
GET /api/freight-quotes — filter to those with quote_id matching the target quote
GET /api/policies — global payment terms, freight reconfirmation rules
Calculation Rules
Pricing
- Select the catalog tier from
product.price_tiers where confirmed_quantity falls within [min_qty, max_qty] (inclusive; max_qty: null means unbounded upper).
exw_total_usd = confirmed_quantity * selected_tier.unit_price_usd
- Round to two decimal places.
- Payment terms come from
policies (look for payment_terms field, typically under a policy record).
Freight Options
For each freight-quotes record tied to the quote:
grand_total_usd = exw_total_usd + freight_cost_usd (two decimals)
validity_status:
"valid" if status == "active" AND valid_until ≥ current business date
"expired" if valid_until < current business date
"stale" if status == "stale" or status indicates stale/mismatch
source_is_stale = true when status != "active" (e.g., "stale", "mismatch")
customs_border_risk = route_risk value (low / medium / high)
transit_days = transit_days_text (e.g., "4-6 days")
Transport Recommendation
- Prefer active freight quotes.
- Among active quotes, prefer lowest
route_risk then shortest transit.
- If the road option is stale/invalid or has high border risk, flag it.
freight_reconfirmation_required = true when:
- Any selected/active freight has
valid_until close to or before the current date, OR
- Policy explicitly requires reconfirmation, OR
- A stale road quote exists and was previously considered.
Warnings
road_quote_invalid_or_stale — true if the road freight quote for this shipment is stale/expired or has high risk.
freight_warning — human-readable summary of any risk/validity issue.
policy_terms — copy relevant payment terms and reconfirmation flags from policies.
Task Type 2: Engagement Reconciliation
Required API Calls
GET /api/opportunities/<opportunity_id> — won amount, phases, outstanding amount, contact, stage
GET /api/customers/<customer_id> — customer name
GET /api/invoices — filter by customer_id or opportunity_id
GET /api/payments — filter by customer_id or opportunity_id
GET /api/revenue-journals — filter by opportunity_id
GET /api/events and GET /api/vouchers — as needed for event/voucher follow-up
Reconciliation Logic
Milestone Mapping
- Opportunity
phases array maps to milestones. Each phase has phase_id, amount_usd, invoice_id, completion_date.
- Order phases by their natural order (e.g., P1 → MS1, P2 → MS2, P3 → MS3).
Invoice & Payment State per Milestone
For each phase:
- Find invoice by
phase.invoice_id in the invoices collection.
- Find payment(s) matching
invoice_id or customer_id.
- Determine:
invoice_state: PAID | OPEN | VOID | UNKNOWN
payment_state: PAID | PARTIAL | UNPAID | UNKNOWN
paid_amount: sum of payments for this invoice (two decimals)
due_date: from invoice record (due_date field), or null
Revenue Recognition Status
For each phase:
RECOGNIZED — if there is a revenue-journal record with matching phase_id and status "posted".
MISSING_REVENUE_JOURNAL — if the milestone is paid (or mostly paid) but no matching revenue-journal exists.
NOT_REQUIRED_UNPAID — if the milestone is unpaid; no recognition needed yet.
UNKNOWN — if data is ambiguous.
Opportunity-Level Checks
phase_total_amount = sum of all phase amount_usd
opportunity_matches_phase_total = abs(won_amount - phase_total_amount) < 0.01
total_paid_amount = sum of all milestone paid_amount
outstanding_balance = won_amount - total_paid_amount (or from opportunity outstanding_amount_usd if provided)
Follow-Up Routing (invoice_actions)
primary_accounting_action:
RECORD_REVENUE_MS2 — if a paid milestone (typically MS2) is missing a revenue journal.
VERIFY_REVENUE_ONLY — if revenue journals exist for all paid milestones but need verification.
NO_ACCOUNTING_ACTION — otherwise.
collection_action:
SEND_COLLECTION_NOTICE — if a milestone is unpaid AND past due date.
MONITOR_UNPAID_NOT_DUE — if unpaid but not yet due.
NO_COLLECTION_ACTION — if all paid.
Event & Voucher Actions (event_actions)
- Look up event by
event_id and voucher by voucher_code.
event_status mapping: scheduled → SCHEDULED, confirmed → ACTIVE, live → ACTIVE, completed → COMPLETED, cancelled → CANCELLED, tentative → UNKNOWN.
voucher_status mapping: active → ACTIVE, draft → DRAFT, expired → EXPIRED, disabled → DISABLED.
invite_action:
SEND_BRIEFING_INVITE — if event is active/scheduled and voucher is active.
VERIFY_INVITE_SENT — if event status suggests invite may already be sent.
NO_INVITE_ACTION — if event is completed/cancelled or voucher is expired.
Common Pitfalls
- Do not use localhost — Always use the remote base URL from
environment_access.md.
- Currency precision — All USD amounts must have exactly two decimal places in JSON output.
- Freight quote filtering — Only include freight quotes whose
quote_id matches the target quote. Distractor quotes exist in the collection.
- Stale vs active — A freight quote can have
status: "active" but valid_until in the past; treat as expired.
- Phase-to-milestone mapping — The API uses
phases with IDs like HEL-P1; map these to MS1, MS2, MS3 in output ordered ascending.
- Payment aggregation — Multiple payment records may exist per invoice; sum them.
- Do not include markdown or narrative outside the JSON response.
- Enum values — Match the exact enum strings in the answer template (case-sensitive).
Data Model Quick Reference
Quote
{
"id": "Q-...",
"customer_id": "CUST-...",
"quote_date": "YYYY-MM-DD",
"confirmed_quantity": 360,
"primary_product_code": "WC-KIT-A",
"status": "revision_requested",
"incoterm": "EXW plus freight options",
"line_items": [{ "product_code": "...", "confirmed_quantity": 360, "prior_unit_price_usd": 124.0 }]
}
Product
{
"code": "WC-KIT-A",
"price_tiers": [{ "min_qty": 1, "max_qty": 149, "unit_price_usd": 129.5, "lead_time_days": 35 }],
"shelf_life_months": 36
}
Freight Quote
{
"id": "FR-...",
"quote_id": "Q-...",
"mode": "air|sea|road",
"cost_usd": 16200.0,
"status": "active|stale|mismatch",
"valid_until": "YYYY-MM-DD",
"route_risk": "low|medium|high",
"transit_days_text": "4-6 days",
"cold_chain_support": true|false
}
Opportunity
{
"id": "OPP-...",
"customer_id": "CUST-...",
"stage": "closed_won|...",
"won_amount_usd": 120000.0,
"outstanding_amount_usd": 70000.0,
"contact": "Name",
"phases": [
{ "phase_id": "HEL-P1", "amount_usd": 50000.0, "invoice_id": "INV-...", "completion_date": "YYYY-MM-DD" }
]
}
Invoice
{
"id": "INV-...",
"customer_id": "CUST-...",
"opportunity_id": "OPP-...",
"phase_id": "HEL-P1",
"amount_usd": 50000.0,
"status": "issued|paid|void",
"due_date": "YYYY-MM-DD"
}
Payment
{
"id": "PAY-...",
"invoice_id": "INV-...",
"customer_id": "CUST-...",
"amount_usd": 50000.0,
"payment_date": "YYYY-MM-DD"
}
Revenue Journal
{
"id": "RJ-...",
"opportunity_id": "OPP-...",
"phase_id": "HEL-P1",
"invoice_id": "INV-...",
"amount_usd": 50000.0,
"status": "posted",
"debit_account": "Deferred Revenue",
"credit_account": "Implementation Services Revenue"
}
Event
{
"id": "EVT-...",
"opportunity_id": "OPP-...",
"customer_id": "CUST-...",
"status": "scheduled|confirmed|live|completed|cancelled|tentative",
"event_date": "YYYY-MM-DD",
"primary_contact": "Name",
"voucher_code": "CODE"
}
Voucher
{
"code": "CODE",
"event_id": "EVT-...",
"opportunity_id": "OPP-...",
"customer_id": "CUST-...",
"status": "active",
"discount_percent": 50,
"max_redemptions": 20,
"redemptions_used": 0,
"valid_until": "YYYY-MM-DD"
}
1---2name: self-attempt-02-313description: MedBridge Sales Ops API Skill4---5# MedBridge Sales Ops API Skill67## Overview89This skill covers interacting with the MedBridge Sales Ops API to produce two types of decision packages:101. **Quote Decision Package** — pricing, freight comparison, transport recommendation, and policy warnings.112. **Engagement Reconciliation** — opportunity-to-milestone reconciliation, revenue recognition, invoice/payment status, and CRM follow-up routing.1213The API is read-only. Return only valid JSON matching the provided `answer_template.json`.1415---1617## API Base URL1819Use the base URL provided by the environment:20- `GDPEVO_ENV_BASE_URL` or `API_BASE_URL` (e.g., `http://34.46.77.124:8002`)21- **Do not** use `localhost` or `127.0.0.1` unless the remote URL itself points there.2223### Discovery Endpoint24`GET /api` returns the list of collections and supported endpoints. Collections:25- `customers`, `events`, `freight-quotes`, `invoices`, `opportunities`, `payments`, `policies`, `products`, `quotes`, `revenue-journals`, `rfqs`, `vouchers`26- `GET /api/search?q=<text>` for free-text search2728### Access Patterns29- List all: `GET /api/<collection>` → `{ collection, count, records: [...] }`30- By ID: `GET /api/<collection>/<id>` → single record or `{ error, message }`3132---3334## Task Type 1: Quote Decision Package3536### Required API Calls371. `GET /api/quotes/<quote_id>` — confirmed quantity, product code, customer_id, quote_date, status382. `GET /api/customers/<customer_id>` — customer name, region, payment terms overrides393. `GET /api/products/<product_code>` — price tiers, lead time, shelf life404. `GET /api/freight-quotes` — filter to those with `quote_id` matching the target quote415. `GET /api/policies` — global payment terms, freight reconfirmation rules4243### Calculation Rules4445#### Pricing46- Select the **catalog tier** from `product.price_tiers` where `confirmed_quantity` falls within `[min_qty, max_qty]` (inclusive; `max_qty: null` means unbounded upper).47- `exw_total_usd = confirmed_quantity * selected_tier.unit_price_usd`48- Round to **two decimal places**.49- Payment terms come from `policies` (look for `payment_terms` field, typically under a policy record).5051#### Freight Options52For each `freight-quotes` record tied to the quote:53- `grand_total_usd = exw_total_usd + freight_cost_usd` (two decimals)54- `validity_status`:55 - `"valid"` if `status == "active"` AND `valid_until` ≥ current business date56 - `"expired"` if `valid_until` < current business date57 - `"stale"` if `status == "stale"` or status indicates stale/mismatch58- `source_is_stale = true` when `status != "active"` (e.g., `"stale"`, `"mismatch"`)59- `customs_border_risk` = `route_risk` value (low / medium / high)60- `transit_days` = `transit_days_text` (e.g., `"4-6 days"`)6162#### Transport Recommendation63- Prefer **active** freight quotes.64- Among active quotes, prefer **lowest `route_risk`** then shortest transit.65- If the road option is stale/invalid or has high border risk, flag it.66- `freight_reconfirmation_required = true` when:67 - Any selected/active freight has `valid_until` close to or before the current date, OR68 - Policy explicitly requires reconfirmation, OR69 - A stale road quote exists and was previously considered.7071#### Warnings72- `road_quote_invalid_or_stale` — true if the road freight quote for this shipment is stale/expired or has high risk.73- `freight_warning` — human-readable summary of any risk/validity issue.74- `policy_terms` — copy relevant payment terms and reconfirmation flags from policies.7576---7778## Task Type 2: Engagement Reconciliation7980### Required API Calls811. `GET /api/opportunities/<opportunity_id>` — won amount, phases, outstanding amount, contact, stage822. `GET /api/customers/<customer_id>` — customer name833. `GET /api/invoices` — filter by `customer_id` or `opportunity_id`844. `GET /api/payments` — filter by `customer_id` or `opportunity_id`855. `GET /api/revenue-journals` — filter by `opportunity_id`866. `GET /api/events` and `GET /api/vouchers` — as needed for event/voucher follow-up8788### Reconciliation Logic8990#### Milestone Mapping91- Opportunity `phases` array maps to milestones. Each phase has `phase_id`, `amount_usd`, `invoice_id`, `completion_date`.92- Order phases by their natural order (e.g., P1 → MS1, P2 → MS2, P3 → MS3).9394#### Invoice & Payment State per Milestone95For each phase:961. Find invoice by `phase.invoice_id` in the invoices collection.972. Find payment(s) matching `invoice_id` or `customer_id`.983. Determine:99 - `invoice_state`: `PAID` | `OPEN` | `VOID` | `UNKNOWN`100 - `payment_state`: `PAID` | `PARTIAL` | `UNPAID` | `UNKNOWN`101 - `paid_amount`: sum of payments for this invoice (two decimals)102 - `due_date`: from invoice record (`due_date` field), or `null`103104#### Revenue Recognition Status105For each phase:106- `RECOGNIZED` — if there is a revenue-journal record with matching `phase_id` and status `"posted"`.107- `MISSING_REVENUE_JOURNAL` — if the milestone is **paid** (or mostly paid) but no matching revenue-journal exists.108- `NOT_REQUIRED_UNPAID` — if the milestone is unpaid; no recognition needed yet.109- `UNKNOWN` — if data is ambiguous.110111#### Opportunity-Level Checks112- `phase_total_amount` = sum of all phase `amount_usd`113- `opportunity_matches_phase_total` = `abs(won_amount - phase_total_amount) < 0.01`114- `total_paid_amount` = sum of all milestone `paid_amount`115- `outstanding_balance` = `won_amount - total_paid_amount` (or from opportunity `outstanding_amount_usd` if provided)116117#### Follow-Up Routing (invoice_actions)118- `primary_accounting_action`:119 - `RECORD_REVENUE_MS2` — if a paid milestone (typically MS2) is missing a revenue journal.120 - `VERIFY_REVENUE_ONLY` — if revenue journals exist for all paid milestones but need verification.121 - `NO_ACCOUNTING_ACTION` — otherwise.122- `collection_action`:123 - `SEND_COLLECTION_NOTICE` — if a milestone is unpaid AND past due date.124 - `MONITOR_UNPAID_NOT_DUE` — if unpaid but not yet due.125 - `NO_COLLECTION_ACTION` — if all paid.126127#### Event & Voucher Actions (event_actions)128- Look up event by `event_id` and voucher by `voucher_code`.129- `event_status` mapping: `scheduled` → `SCHEDULED`, `confirmed` → `ACTIVE`, `live` → `ACTIVE`, `completed` → `COMPLETED`, `cancelled` → `CANCELLED`, `tentative` → `UNKNOWN`.130- `voucher_status` mapping: `active` → `ACTIVE`, `draft` → `DRAFT`, `expired` → `EXPIRED`, `disabled` → `DISABLED`.131- `invite_action`:132 - `SEND_BRIEFING_INVITE` — if event is active/scheduled and voucher is active.133 - `VERIFY_INVITE_SENT` — if event status suggests invite may already be sent.134 - `NO_INVITE_ACTION` — if event is completed/cancelled or voucher is expired.135136---137138## Common Pitfalls1391401. **Do not use localhost** — Always use the remote base URL from `environment_access.md`.1412. **Currency precision** — All USD amounts must have exactly two decimal places in JSON output.1423. **Freight quote filtering** — Only include freight quotes whose `quote_id` matches the target quote. Distractor quotes exist in the collection.1434. **Stale vs active** — A freight quote can have `status: "active"` but `valid_until` in the past; treat as expired.1445. **Phase-to-milestone mapping** — The API uses `phases` with IDs like `HEL-P1`; map these to `MS1`, `MS2`, `MS3` in output ordered ascending.1456. **Payment aggregation** — Multiple payment records may exist per invoice; sum them.1467. **Do not include markdown or narrative** outside the JSON response.1478. **Enum values** — Match the exact enum strings in the answer template (case-sensitive).148149---150151## Data Model Quick Reference152153### Quote154```json155{156 "id": "Q-...",157 "customer_id": "CUST-...",158 "quote_date": "YYYY-MM-DD",159 "confirmed_quantity": 360,160 "primary_product_code": "WC-KIT-A",161 "status": "revision_requested",162 "incoterm": "EXW plus freight options",163 "line_items": [{ "product_code": "...", "confirmed_quantity": 360, "prior_unit_price_usd": 124.0 }]164}165```166167### Product168```json169{170 "code": "WC-KIT-A",171 "price_tiers": [{ "min_qty": 1, "max_qty": 149, "unit_price_usd": 129.5, "lead_time_days": 35 }],172 "shelf_life_months": 36173}174```175176### Freight Quote177```json178{179 "id": "FR-...",180 "quote_id": "Q-...",181 "mode": "air|sea|road",182 "cost_usd": 16200.0,183 "status": "active|stale|mismatch",184 "valid_until": "YYYY-MM-DD",185 "route_risk": "low|medium|high",186 "transit_days_text": "4-6 days",187 "cold_chain_support": true|false188}189```190191### Opportunity192```json193{194 "id": "OPP-...",195 "customer_id": "CUST-...",196 "stage": "closed_won|...",197 "won_amount_usd": 120000.0,198 "outstanding_amount_usd": 70000.0,199 "contact": "Name",200 "phases": [201 { "phase_id": "HEL-P1", "amount_usd": 50000.0, "invoice_id": "INV-...", "completion_date": "YYYY-MM-DD" }202 ]203}204```205206### Invoice207```json208{209 "id": "INV-...",210 "customer_id": "CUST-...",211 "opportunity_id": "OPP-...",212 "phase_id": "HEL-P1",213 "amount_usd": 50000.0,214 "status": "issued|paid|void",215 "due_date": "YYYY-MM-DD"216}217```218219### Payment220```json221{222 "id": "PAY-...",223 "invoice_id": "INV-...",224 "customer_id": "CUST-...",225 "amount_usd": 50000.0,226 "payment_date": "YYYY-MM-DD"227}228```229230### Revenue Journal231```json232{233 "id": "RJ-...",234 "opportunity_id": "OPP-...",235 "phase_id": "HEL-P1",236 "invoice_id": "INV-...",237 "amount_usd": 50000.0,238 "status": "posted",239 "debit_account": "Deferred Revenue",240 "credit_account": "Implementation Services Revenue"241}242```243244### Event245```json246{247 "id": "EVT-...",248 "opportunity_id": "OPP-...",249 "customer_id": "CUST-...",250 "status": "scheduled|confirmed|live|completed|cancelled|tentative",251 "event_date": "YYYY-MM-DD",252 "primary_contact": "Name",253 "voucher_code": "CODE"254}255```256257### Voucher258```json259{260 "code": "CODE",261 "event_id": "EVT-...",262 "opportunity_id": "OPP-...",263 "customer_id": "CUST-...",264 "status": "active",265 "discount_percent": 50,266 "max_redemptions": 20,267 "redemptions_used": 0,268 "valid_until": "YYYY-MM-DD"269}270```