Developer Portal

Programmatic API & AI Agents

Query, automate, and synchronize your Nine workspace data via standard PostgREST endpoints, Supabase Edge Functions, and AI-ready endpoints.

Built for AI Agents, Gemini & LLMs

MCP Protocolllms.txt standard

Connect Nine directly to Google Gemini Connected Apps, Claude Desktop, and IDE agents via our native Model Context Protocol (MCP) server, OpenAPI 3.0 spec, and llms.txt context.

Google Gemini Connected App Setup

  1. 1. Open Gemini > Extensions / Connected Apps > Set up a custom connected app.
  2. 2. In 'Add a custom app link', enter your MCP Server URL:
    https://ninehoang.com/mcp?token=YOUR_API_TOKEN
  3. 3. Leave Client ID and Client Secret blank, then click Next.

Supported MCP Tools

Tool NameDescriptionParameters
create_expenseRecord an expenditure in the workspace ledger.name (string), amount (number), category_id (enum), method_id (enum), occurred_at?, note?
list_expensesRetrieve recent expense records with date filtering, category filter, search, and pagination (up to 1,000).limit? (max 1000), offset?, category_id?, method_id?, start_date?, end_date?, search?
update_expenseModify an existing expense (amount, category, vendor title, payment method, date, or notes).id (uuid), name?, amount?, category_id?, method_id?, occurred_at?, note?
delete_expensePermanently delete an expense record by its UUID.id (uuid)
list_fundsList active collective funds, target budgets, and real-time balance totals.none (returns all funds in workspace)
get_fundRetrieve full details, budget targets, participants, and ledger for a specific fund.fund_id (uuid)
create_fundCreate a new group fund (trips, sports seasons, event budgets).name (string), kind? ('Travel' | 'Badminton'), currency?, target_amount?, description?
update_fundUpdate fund name, target goal, status ('Upcoming', 'In Progress', 'Completed'), or description.fund_id (uuid), name?, status?, target_amount?, description?
create_fund_transactionRecord an income contribution or expense payout in a group fund.fund_id (uuid), name (string), amount (number), category_id (enum), method_id (enum), occurred_at?
list_fund_transactionsRetrieve transactions and payouts across group funds with date filtering and pagination.fund_id?, limit? (max 1000), offset?, category_id?, start_date?, end_date?
delete_fund_transactionDelete a fund transaction record by its UUID.id (uuid)
list_contactsQuery member roster and contact address book in the workspace with optional search.search? (name, nickname, or phone query)
create_contactAdd a new member or participant to the workspace directory.name (string), nickname?, phone?, email?, gender?, nationality?
update_contactUpdate member information (name, nickname, phone, email).id (uuid), name?, nickname?, phone?, email?

Authentication & Token Exchange

External requests authenticate via a two-tier token flow: exchange your workspace bearer token for a short-lived 1-hour JWT.

Step 1: Exchange API Token for 1-hour JWT
curl -X POST \
  "https://pdkklibrvyqnatsqwtyg.supabase.co/functions/v1/api-token" \
  -H "Authorization: Bearer nh_ws_YOUR_API_TOKEN" \
  -H "Content-Type: application/json"
Step 2: Query PostgREST with Bearer JWT
curl "https://pdkklibrvyqnatsqwtyg.supabase.co/rest/v1/personal_transactions?select=*&order=occurred_at.desc&limit=20" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "apikey: sb_publishable_gZdZ09nTdrxLCHPa36rXeg_6DraJ4Ps"

SDK & Client Quickstart

Connect to your workspace using standard HTTP clients, the JavaScript/TypeScript SDK, or Python.

curl "https://pdkklibrvyqnatsqwtyg.supabase.co/rest/v1/personal_transactions?select=*&order=occurred_at.desc&limit=20" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "apikey: sb_publishable_gZdZ09nTdrxLCHPa36rXeg_6DraJ4Ps"

Resource Endpoints & Schemas

Access workspace resources directly through PostgREST with strict Row Level Security isolation.

GETPOSTPATCHDELETE
/rest/v1/personal_transactions
Workspace expense ledger, spending records, and day-to-day outlays.
FieldTypeDescription / Valid Options
iduuidPrimary key identifier
nametextExpense description / item (max 255 chars)
amountnumericAmount in workspace currency
category_idenumOptions: '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_idenumSlugs from the transaction_methods table: 'cash', 'bank-transfer', 'mobile-wallet', 'credit-card', 'installment'. Read the live list from /openapi.json.
occurred_attimestamptzDate and time of transaction
notetextOptional context or memo

HTTP Status Codes & Rate Limits

Standard HTTP response codes returned by PostgREST and Supabase Edge Functions.

200 OK

Standard successful response for GET, PATCH, and DELETE operations.

201 Created

Resource successfully created (POST personal_transactions, funds, etc.).

400 Bad Request

Malformed JSON payload, out-of-bounds numbers, or invalid enum selection.

401 Unauthorized

Missing API token, expired 1-hour JWT, or token revoked via 0-ms kill switch.

403 Forbidden

Attempted to access an ungranted table (e.g. workspace_members, passwords).

429 Too Many Requests

Rate limit exceeded (60 req/min). Returns Retry-After header with wait seconds.

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.

Zero Cross-Tenant LeakPostgres RLS filters every table query automatically by workspace ID.
Excluded TablesWorkspace members, passwords, billing, and credentials are completely ungranted.
0-ms Instant Kill SwitchTurning off the workspace API switch revokes access across all external tokens instantly.

Ready to connect your workspace?

Generate and manage tokens with fine-grained read or read-write permissions directly inside your Workspace Settings.

Go to Workspace API Settings