Programmatic API & AI Agents
Run your workspace from any AI or system: an MCP server for Claude, ChatGPT and Gemini, and a REST API for integrations — sales, products, inventory, invoicing, content and the inbox.
Built for AI assistants — Claude, ChatGPT, Gemini
MCP Protocolllms.txt standardPaste one URL into your AI app and sign in: Nine's MCP server gives it 86 tools across sales, products, inventory, invoicing, content and the inbox — also described as OpenAPI 3 and llms.txt.
Gemini app setup
- 1. Open Gemini → Settings → Connected apps → Custom apps → Add a custom app.
- 2. Enter the MCP server URL:
https://app.ninehoang.com/mcp - 3. Click Next and approve the connection in Nine — there is no client ID or secret to enter.
MCP tools
| Tool Name | Description | Parameters |
|---|---|---|
| get_workspace | Which workspace this connection belongs to, and whether it may write. | none |
| list_sales_orders | Orders, newest first, with customer, status and totals — before tax, tax, total, cost and profit. | search?, status?, customer_id?, start_date?, end_date?, limit?, offset? |
| create_sales_order | Record a sale from products and quantities; names, prices and taxes come from the catalogue. Confirm it in the same call if you like. | lines [{ product_id, quantity, unit_price?, discount_percent? }], customer_id?, ordered_at?, note?, confirm? |
| confirm_sales_order | Confirm a draft: its cost is fixed and goods leave stock — or a delivery is created, with Inventory installed. | id |
| sales_report | Revenue before tax, cost of goods sold and gross profit for any period, with the top products and customers. | start_date?, end_date?, top? |
| list_products | The catalogue with category, cost and sales price, margin per unit, taxes and quantity on hand. | search?, category_id?, kind?, include_archived?, limit?, offset? |
| create_product | Add a product or service with its prices, taxes, tracking and opening stock. | name, kind?, category_id?, tracking?, sales_price?, cost_price?, sales_tax_ids?, purchase_tax_ids?, quantity? |
| list_replenishment | Reorder rules with on hand, incoming, outgoing, forecast — and how much to order. | product_id?, warehouse_id?, to_order_only? |
| create_invoice | A customer invoice or a vendor bill, with lines; post it to give it its number. | kind, partner_id?, reference?, invoice_date?, due_date?, lines?, post?, note? |
| record_invoice_payment | Record money received or paid against a posted invoice or bill. | invoice_id, amount, method_id, received_at?, note? |
| list_entries | A collection's entries — blog posts, services, projects — in every language, with fields, categories, tags and status. | collection, status?, limit?, offset? |
| create_entry | A new draft in any collection, in one language; its article is written next, as Markdown. | collection, title, locale?, slug?, summary?, fields?, parent_id? |
| set_article | Write one language of an entry's article as Markdown — headings, lists, callouts, galleries, embeds. | kind, id, locale, markdown |
| publish_article | Publish a draft now or at a set time, or take it off the site — when the workspace lets assistants publish. | kind, id, action?, at? |
| list_messages | Leads from the website's contact form, newest first, with where each stands in triage. | status?, search?, limit?, offset? |
| create_many | Up to 50 records of any types in one call — one approval. A later item can use an earlier one's result: "$0.id". | items [{ tool, arguments }] |
Authentication
AI apps connect with OAuth 2.1: sign in, choose a workspace and an access level. Integrations send a workspace token on every request — Authorization: Bearer nh_ws_…. Nothing expires on its own, and revoking ends access at once.
curl "https://app.ninehoang.com/api/v1/sales_orders?select=*&order=ordered_at.desc&limit=20" \ -H "Authorization: Bearer nh_ws_YOUR_API_TOKEN"
curl -X POST "https://app.ninehoang.com/api/v1/tools/confirm_sales_order" \
-H "Authorization: Bearer nh_ws_YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "ORDER_UUID"}'SDK & Client Quickstart
Connect to your workspace using standard HTTP clients, the JavaScript/TypeScript SDK, or Python.
# 1. Read rows — any table, with PostgREST filters
curl "https://app.ninehoang.com/api/v1/sales_orders?select=*&order=ordered_at.desc&limit=20" \
-H "Authorization: Bearer nh_ws_YOUR_API_TOKEN"
# 2. Run an action — the same rules the MCP server applies
curl -X POST "https://app.ninehoang.com/api/v1/tools/confirm_sales_order" \
-H "Authorization: Bearer nh_ws_YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"id": "ORDER_UUID"}'Resource Endpoints & Schemas
Every table through PostgREST's query language, and every business step through /api/v1/tools — both scoped to the token's workspace by row-level security.
/api/v1/expenses_transactions| Field | Type | Description / Valid Options |
|---|---|---|
| id | uuid | Primary key identifier |
| name | text | Expense description / item (max 255 chars) |
| amount | numeric | Amount in workspace currency |
| category_id | enum | Options: 'food-drinks', 'entertainment', 'local-transport', 'clothing', 'beauty-care', 'sports', 'essentials', 'fixed-expenses', 'credit-repayment', 'installment-payment', 'family-support', 'travel', 'work-expenses', 'investments', 'other'. Read from `transaction_categories` (the rows offered to Expenses), so this list can grow without a deploy. |
| method_id | enum | Slugs from the transaction_methods table: 'cash', 'bank-transfer', 'mobile-wallet', 'credit-card', 'installment'. Read the live list from /openapi.json. |
| occurred_at | timestamptz | Date and time of transaction |
| note | text | Optional context or memo |
HTTP status codes
From the API itself, errors are { error } in words; from a table endpoint, PostgREST's { code, message }.
Rows read, updated or deleted, or an action's result.
Rows created through POST /api/v1/{resource}; the created rows come back.
An action refused its arguments — { error } says why, in words — or a malformed filter or payload.
Missing, revoked or expired token, or the workspace's API switched off. AI apps reconnect through OAuth.
A read-only token tried to write, or the app that owns the data is not installed.
No such resource or action; GET /api/v1 and GET /api/v1/tools list them.
Tenant Isolation & Security
Every API request is scoped by Postgres Row Level Security (RLS) via public.api_workspace_id(). System credentials and internal auth settings are completely inaccessible.
Ready to connect your workspace?
Generate and manage tokens with fine-grained read or read-write permissions directly inside your Workspace Settings.