GFS Platform
Infrastructure
Worker endpoints, cron, bindings, secrets map
Custom domain
api.ai-globalfoodsolutions.co
Fallback
gfs-platform.mikelevine.workers.dev
Endpoints
19
Crons
2
DNS records
6
Cloudflare services
- Worker — gfs-platform, source src/index.ts. Routes api.ai-globalfoodsolutions.co/*.
- D1 — gfs-netsuite (3818ecd5-995e-4694-a08b-a273c94291da).
- KV — namespace CACHE (e880e40bc3674963bc37cf90e02f6369).
- R2 — bucket gfs-files.
- Pages — gfs-netsuite.pages.dev (this platform). Legacy: gfs-system-guide.pages.dev.
- DNS / zone — ai-globalfoodsolutions.co (owned). Corporate domain globalfoodsolutions.co also owned.
Worker endpoints — overview 19 detected
Detected by static analysis of src/index.ts. Detail per endpoint below.
| Path | Auth | Method |
|---|---|---|
| / | Public | GET |
| /api/ | Bearer | GET |
| /api/ar/aging | Bearer | GET |
| /api/briefing | Bearer | GET |
| /api/customers | Bearer | GET |
| /api/customers/ranking | Bearer | GET |
| /api/financials/monthly | Bearer | GET |
| /api/financials/summary | Bearer | GET |
| /api/gl/accounts | Bearer | GET |
| /api/health | Public | GET |
| /api/items | Bearer | GET |
| /api/items/performance | Bearer | GET |
| /api/kpis | Bearer | GET |
| /api/revenue/trend | Bearer | GET |
| /api/search | Bearer | GET |
| /api/sync-status | Public | GET |
| /api/transactions | Bearer | GET |
| /api/vendors | Bearer | GET |
| /api/vendors/spend | Bearer | GET |
Worker endpoints — per-endpoint detail 20 documented
Param tables, auth, and example responses for every public endpoint. Source: data/api-endpoints.json.
GET /api/healthPublicExample response
{
"status": "ok",
"database": "gfs-netsuite",
"counts": {
"customers": 283, "vendors": 484, "items": 1265,
"transactions": 102367, "invoice_lines": 28528,
"so_lines": 29098, "vb_lines": 21315, "pricing": 1264
},
"timestamp": "2026-05-19T13:33:03.674Z"
}
GET /api/kpisBearerExample response
{
"revenue_2026_ytd": 11272175.89,
"revenue_2025_total": 28435586.26,
"open_ar": { "amount": 2299955.6, "count": 216 },
"open_ap": { "amount": ..., "count": ... },
"open_so": { "amount": ..., "count": 90 },
"timestamp": "..."
}
GET /api/briefingBearerExample response
{
"revenue_2026_ytd": ...,
"open_ar": { "amount": ..., "count": ... },
"open_so": { "amount": ..., "count": ... },
"invoices_this_month": { "amount": ..., "count": ... },
"top_customers_2026": [ { "entity_name": "Driscoll Foods", "revenue": 4107918.47 }, ... ],
"timestamp": "..."
}
GET /api/customersBearerParameters
| Param | Type | Default | Description |
|---|---|---|---|
| q | string | — | Search by company name (LIKE %q%) |
| limit | int | 50 | 1-200 |
| offset | int | 0 | 0-100000 |
Example response
{ "items": [...], "total": 283, "limit": 50, "offset": 0 }
GET /api/customers/:idBearerExample response
{ "id": 475, "companyname": "Jkings", ..., "contacts": [...], "pricing": [...], "recent_orders": [...] }
GET /api/customers/:id/historyBearerExample response
{ "customer_id": "475", "yearly": [{ "year": 2026, "type": "CustInvc", "txn_count": 47, "total": ... }], "top_items": [...] }
GET /api/customers/rankingBearerParameters
| Param | Type | Default |
|---|---|---|
| year | int | 2026 |
Example response
{ "year": 2026, "items": [{ "customer": "Driscoll Foods", "customer_id": 539, "inv_count": ..., "revenue": 4107918.47 }, ...] }
GET /api/vendorsBearerGET /api/vendors/spendBearerParameters
| Param | Type | Default |
|---|---|---|
| year | int | 2026 |
GET /api/itemsBearerParameters
| Param | Type | Default | Allowed Values |
|---|---|---|---|
| type | string | — | InvtPart, Assembly, Kit, NonInvtPart |
| allergen | string | — | milk, eggs, peanuts, soybeans, wheat, fish, tree_nuts, crustacean, celery, lupin, molluscs, mustard, sesame, sulphur_dioxide |
| limit | int | 50 | 1-200 |
| offset | int | 0 | 0-100000 |
GET /api/items/:idBearerGET /api/items/performanceBearerParameters
| Param | Type | Default |
|---|---|---|
| year | int | 2026 |
GET /api/items/:id/customersBearerGET /api/transactionsBearerParameters
| Param | Type | Default | Allowed |
|---|---|---|---|
| type | string | CustInvc | 16 validated types |
| year | int | — | 2018-2027 |
| limit | int | 50 | 1-200 |
| offset | int | 0 | 0-100000 |
GET /api/ar/agingBearerExample response
{ "items": [{ "customer": "...", "customer_id": ..., "inv_count": ..., "total_ar": ..., "current_bal": ..., "days_1_30": ..., "days_31_60": ..., "days_61_90": ..., "days_90_plus": ... }] }
GET /api/financials/summaryBearerExample response
{ "revenue": [{ "year": 2026, "invoices": 712, "total": 11272175.89 }, ...], "cogs": [...], "collections": [...] }
GET /api/financials/monthlyBearerParameters
| Param | Type | Default |
|---|---|---|
| year | int | 2026 |
GET /api/revenue/trendBearerGET /api/gl/accountsBearerParameters
| Param | Type | Default | Values |
|---|---|---|---|
| type | string | — | Bank, AcctRec, AcctPay, Income, COGS, Expense, Equity, OthCurrAsset, OthCurrLiab, FixedAsset, OthIncome, OthExpense, NonPosting |
GET /api/searchBearerParameters
| Param | Type | Required |
|---|---|---|
| q | string | Yes (max 100 chars) |
Example response
{ "results": [{ "id": 475, "name": "Jkings", "type": "customer" }, { "id": 539, "name": "Driscoll Foods", "type": "customer" }, ...] }
Example requests
# Health (public)
curl https://api.ai-globalfoodsolutions.co/api/health
# KPIs (auth)
curl -H "Authorization: Bearer $API_KEY" \
https://api.ai-globalfoodsolutions.co/api/kpis
# Fallback when custom domain unavailable
curl https://gfs-platform.mikelevine.workers.dev/api/health
CORS & security headers
Origins allowed by the Worker: https://ai-globalfoodsolutions.co, https://www.ai-globalfoodsolutions.co, http://localhost:3000, http://localhost:8787.
Headers on every JSON response: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-origin, Content-Security-Policy: default-src 'none'; frame-ancestors 'none'.
DNS records 6 records
Records on the ai-globalfoodsolutions.co zone. Proxied = behind Cloudflare WAF/CDN.
| Type | Name | Value | Proxy |
|---|---|---|---|
| CNAME | api | gfs-platform.mikelevine.workers.dev | Proxied |
| CNAME | www | ai-globalfoodsolutions.co | Proxied |
| MX | @ | route1.mx.cloudflare.net (priority 87) | — |
| TXT | @ | v=spf1 include:_spf.mx.cloudflare.net ~all | — |
| TXT | _dmarc | v=DMARC1; p=none; ... | — |
| NS | @ | chance.ns.cloudflare.com · leanna.ns.cloudflare.com | — |
Cron schedules
Declared in wrangler.jsonc:
- */15 * * * *
- 0 19 * * *
Worker scheduled() handler is not implemented in src/index.ts. Periodic work runs locally — see next section.
Local cron (actually running)
| Script | Cadence | Function | Source |
|---|---|---|---|
| sync.sh | every 15 min via launchd | Queries Chartstone (localhost:56411) for modified NS transactions in the last 30 min, upserts into D1. | sync.sh |
| daily-report.sh | archived | (Out of scope — revenue report.) | archive/2026-05/daily-report.sh |
Single-laptop dependency: if the Mac is off, sync stops. Migration to Worker-side scheduled() handler calling SuiteAPI directly — Tier 2 GAP.
Bindings
| Binding | Type | Target |
|---|---|---|
| DB | D1 database | gfs-netsuite (3818ecd5-995e-4694-a08b-a273c94291da) |
| CACHE | KV namespace | e880e40bc3674963bc37cf90e02f6369 |
| STORAGE | R2 bucket | gfs-files |
| API_KEY | Secret | set via wrangler secret put API_KEY |
Secrets map
Names only. Rotation cadence in runbook → secret rotation.
| Name | Location | Use |
|---|---|---|
| API_KEY | Worker env (Cloudflare) | Bearer for protected REST endpoints |
| CHARTSTONE_SECRET | Local ~/.zshenv | Bearer used by sync.sh to call Chartstone |
| (NetSuite TBA tokens) | NetSuite Manage Auth Tokens | SuiteAttach, Analytics Warehouse, Chartstone Pro |
Deploy commands
# Worker
wrangler deploy
# Tail Worker logs
wrangler tail
# Run query against D1
wrangler d1 execute gfs-netsuite --remote --command="SELECT COUNT(*) FROM transactions"
# Manage secret
wrangler secret put API_KEY
# Pages deploy (this platform)
wrangler pages deploy . --project-name gfs-netsuite