Floating Labs

NetSuite MCP API

AI-powered NetSuite integration using Claude and MCP

Overview

How it works

This API processes customer service emails and interacts with NetSuite. A classifier analyzes incoming emails and outputs structured JSON, which this API uses to query or write data to NetSuite via Claude AI agents.

šŸ“§ Emailā†’šŸ¤– Classifierā†’šŸ“‹ JSONā†’āš” This APIā†’šŸ—„ļø NetSuite

Built by @ishan_lakh


Pipeline

End-to-End Flow

1. Email Classification

The classifier prompt analyzes emails and extracts:

  • Customer identity (email, name, company)
  • Questions grouped by workflow type
  • PDF/attachment data (PO items, SKUs, quantities)
  • Boolean flags for which workflows to run

2. Workflow Routing

Based on classifier output, the API routes to appropriate workflows:

FlagTriggerAction
has_po2so: trueCSR says "create so from po"āš ļø Creates Sales Order in NetSuite
has_stock_price: trueCustomer asks about pricing/inventoryQueries items, prices, availability
has_ship_date: trueCustomer asks about order statusQueries orders, ship dates, fulfillments
has_other: trueGeneral NetSuite-answerable questionQueries account data, balances, history

3. NetSuite Interaction

Claude AI agents execute SuiteQL queries and return structured data. For po2so workflow, agents can also create records.


Classifier Output

Expected Input Format

The classifier produces this JSON structure, which becomes the API request body:

{
  "customer_email": "buyer@acmecorp.com",
  "customer_name": "Jane Doe",
  "customer_company": "ACME Corp",
  
  "has_po2so": false,
  "has_stock_price": true,
  "has_ship_date": false,
  "has_hold": false,
  "has_other": false,
  
  "po2so_questions": [],
  "stock_price_questions": [
    {
      "index": 0,
      "normalized_question": "What is the price for item SKU-001?",
      "source_quote": "can you send pricing for SKU-001?",
      "item_hints": ["SKU-001"],
      "po_number": null,
      "so_number": null
    }
  ],
  "ship_date_questions": [],
  "hold_questions": [],
  "other_questions": [],
  
  "pdf_data": {
    "document_type": "Purchase Order",
    "po_number": "PO-2025-001",
    "vendor": "ACME Corp",
    "items": [
      {
        "line": 1,
        "sku": "SKU-001",
        "description": "Widget A – Gold – 1 Inch",
        "quantity": 100,
        "unit_price": 10.50
      }
    ],
    "total": 1050.00,
    "notes": "Rush order"
  }
}

Write Operations

PO to SO Conversion

āš ļø This creates real records in NetSuite. The po2so workflow only triggers when an internal CSR explicitly requests it with phrases like "create so from po". Customer emails alone will NOT trigger this.

Trigger Phrases (from internal CSR)

āœ… "create so from po"
āœ… "convert this po to so"
āœ… "enter this po as a sales order"
āœ… "create sales order from this purchase order"

āŒ Customer: "Please confirm the attached PO" → routes to ship_date
āŒ Customer: "Here is our order" → routes to ship_date

What Happens

  1. Classifier sets has_po2so: true
  2. API runs PO2SO preview (matches PDF items to NetSuite items)
  3. If items matched successfully, creates the Sales Order
  4. Returns so_created with SO number

Response when SO is created

{
  "workflow": "po2so",
  "raw_data": {
    "customer": { "id": 12345, "name": "ACME Corp" },
    "so_created": {
      "id": 67890,
      "tranid": "SOSX25-12345"
    },
    "po_items": [
      {
        "original_sku": "SKU-001",
        "matched_item": { "itemid": "SKU-001-GOLD", "unit_price": 10.50 },
        "match_status": "matched"
      }
    ]
  },
  "summary": "Sales Order SOSX25-12345 created from PO PO-2025-001"
}

API Reference

Endpoints

POST/api/process

Main endpoint. Accepts classifier JSON output and routes to appropriate workflows. Handles all workflow types including po2so (which can write to NetSuite).

POST/api/po2so

Direct PO to SO endpoint. Use create_so: true to create, create_so: false for preview only.


Request Schema

All Input Fields

FieldTypeDescription
auth_keyrequiredstringAPI authentication key
customer_emailstringCustomer's email address
customer_namestringContact name (not used for lookup)
customer_companystringCompany name for NetSuite customer lookup
has_po2sobooleanāš ļø When true, creates Sales Order
has_stock_pricebooleanTriggers stock/price workflow
has_ship_datebooleanTriggers ship date workflow
has_holdbooleanTriggers hold status workflow
has_otherbooleanTriggers general query workflow
po2so_questionsarrayPO to SO requests (needs CSR trigger phrase)
stock_price_questionsarrayPricing and inventory questions
ship_date_questionsarrayOrder status and shipping questions
hold_questionsarrayAccount hold status questions
other_questionsarrayGeneral account inquiries
pdf_dataobjectExtracted PO/catalog data with items array

Question Schema

Question Object Format

Each question in the arrays follows this structure:

{
  "index": 0,
  "normalized_question": "What is the price for SKU-001?",
  "source_quote": "can you send pricing for SKU-001?",
  "item_hints": ["SKU-001", "Widget"],
  "po_number": "PO-2025-001",
  "so_number": null
}

PDF Schema

pdf_data Object Format

{
  "document_type": "Purchase Order",
  "po_number": "PO-2025-001",
  "vendor": "ACME Corp",
  "items": [
    {
      "line": 1,
      "sku": "SKU-001",
      "description": "Widget A – Gold – 1 Inch",
      "quantity": 100,
      "unit_price": 10.50
    }
  ],
  "total": 1050.00,
  "notes": "Rush order, ship by end of month"
}

Tip: The unit_price in pdf_data helps match items to customer's purchase history. Items with matching prices are prioritized.


Response

API Response Format

{
  "ok": true,
  "customer_identity": {
    "email": "buyer@acmecorp.com",
    "name": "Jane Doe",
    "company": "ACME Corp"
  },
  "workflow_results": [
    {
      "workflow": "stock_price",
      "raw_data": {
        "customer": { "id": 12345, "name": "ACME Corporation" },
        "items": [
          {
            "itemid": "SKU-001-GOLD",
            "description": "Widget A Gold",
            "unit_price": 10.50,
            "on_hand": 500,
            "available": 450,
            "committed": 50
          }
        ],
        "notes": ["Found in customer history at $10.50"]
      },
      "summary": "Found 1 item(s)",
      "errors": []
    }
  ],
  "debug": {
    "request_id": "req_abc123",
    "model_used": "claude-3-5-haiku-20241022",
    "timings": { "stock_price": 5000, "total": 5000 }
  }
}

Errors

Error Codes

StatusDescription
401Invalid or missing auth_key
400Invalid request body or no questions provided
500Internal server error or NetSuite connection failed

NetSuite MCP API v1.0