Skip to content

Developer docs

Build on the ledger. Draft, never execute.

BudAlly exposes the same objects the product runs on — packages, receipts, lines, proposals, rule results — through an MCP server for AI agents and a REST API for everything else. Both are read-plus-draft: anything that changes the world becomes a proposal in the tenant's approval queue.

Base URLsapi.budally.com/v1 · mcp.budally.com
AuthOAuth 2.1 (PKCE) per user; scoped API keys per tenant-location for servers
StatusMCP: beta for Close and Chain Ops · REST: Placeholder: [DATE] · Docs are pre-release

MCP server

Add https://mcp.budally.com as a remote MCP server in Claude, ChatGPT, or your own client. The OAuth flow signs the user in with their BudAlly role; tools are filtered by that role and by the tenant's data-use rules. Every draft tool returns a proposal id you can watch in the queue.

// read tools

inventory.read(location, as_of?)
→ packages with tag, qty, cost, lab results, source taint
sales.read(location, from, to)
→ receipts joined to Metrc receipt ids, match rate
ledger.read(tag)
→ every event for one package
prices.read(location)
→ shelf + OTD, market median (source, n, k) where licensed
rules.check(pack, action, context)
→ ALLOWED | BLOCKED | UNKNOWN + rule id + citation

// draft tools — each returns a proposal_id

  • po.draft(location, lines[])
  • price_change.draft(sku, new_price, rationale)
  • campaign.draft(segment, copy, holdout)
  • bill.draft(invoice_ref, lines[])

// there are no execute tools. proposals execute only from the approval queue,
// under the approver's own POS or Metrc credential.

Every response carries provenance

source, as_of, taint (METRC · POS:<vendor> · LICENSED:<licensor> · OWN_CHECK) so an agent can cite what a human can check.

Rules are enforced at the API, not the prompt

Dutchie-connector rows never appear in benchmarks; Headset data never leaves internal analysis; cells with k < 8 return “—”. A client can't opt out.

REST API

REST endpoints, paths and what each returns
MethodPathReturns
GET/v1/locations/{id}/packagesPackage ledger rows; filters by tag, item, room, as_of
GET/v1/locations/{id}/receiptsReceipts with lines, tags, taxes, tender, metrc_receipt_id
GET/v1/proposals?state=proposedQueue items with evidence, confidence, rules_applied, precondition_hash
POST/v1/proposalsCreate a draft (same schema as MCP draft tools). Never executes.
POST/v1/proposals/{id}/reviewAttach a review note. Approval is UI-only, by a signed-in person.
GET/v1/audit?from=&to=Full audit trail export (JSON, CSV)
GET/v1/exports/{kind}ledger · members · consent_proofs · documents — the “your data leaves with you” endpoint
WEBHOOKproposal.created · proposal.executed · sync.stale · clock.warningSigned (HMAC), titles and ids only — details stay in-app

Data-use registry

Every adapter and every tool is governed by a readable registry. A few entries your integration will hit:

DU-DUT-03
Dutchie-connector rows are excluded from all cross-tenant benchmarks and medians.
DU-SCR-01
Automated collection of Weedmaps, Leafly, Dutchie or Jane menus is denied; uploads with scraper provenance are rejected and not stored.
DU-HDS-01
Licensed market data is internal-analysis only; never syndicated, never returned to vendor-operated MCP clients.
DU-LLM-01
Model providers: no training, ≤30-day retention; zero-retention tier on Chain Ops.
RI-ALL-10
No segment, cohort or median with fewer than 8 contributors is returned; the field reads “—, k < 8”.

© 2026 BudAlly, Inc. · Pre-release documentation; shapes may change before GA.