NetSuiteFree generatorPDF, Excel, Word exportNetSuiteAll NetSuite tools

Query NetSuite Custom Lists and Custom Records with SuiteQL

Custom lists and custom record types each appear in SuiteQL as their own table named after the script ID. This generator writes the queries for list values, custom record rows, a join from transactions, and the REST calls to run them.

Fill in

Prefix each with r. so the query stays valid.

Generated code
Download:

1. Custom list values

SELECT id, name, scriptid, isinactive
FROM customlist_ship_method
WHERE isinactive = 'F'
ORDER BY name

2. Custom record rows with system columns

SELECT
  r.id,
  r.name,
  r.externalid,
  r.created,
  r.lastmodified,
  BUILTIN.DF(r.owner) AS owner,
  BUILTIN.DF(r.custrecord_qc_result) AS custrecord_qc_result_text,
  r.custrecord_qc_result, r.custrecord_qc_item
FROM customrecord_qc_inspection r
WHERE r.isinactive = 'F'
ORDER BY r.lastmodified DESC

3. Transactions linked to the custom record

SELECT
  t.id,
  t.tranid,
  BUILTIN.DF(t.type) AS type,
  t.trandate,
  t.custbody_qc_inspection AS linked_record_id,
  BUILTIN.DF(t.custbody_qc_inspection) AS linked_record_name,
  BUILTIN.DF(r.custrecord_qc_result) AS custrecord_qc_result_text
FROM transaction t
INNER JOIN customrecord_qc_inspection r ON r.id = t.custbody_qc_inspection
WHERE t.custbody_qc_inspection IS NOT NULL
ORDER BY t.trandate DESC

4. Run it through REST (query/v1/suiteql)

POST https://1234567-sb1.suitetalk.api.netsuite.com/services/rest/query/v1/suiteql?limit=1000&offset=0
Authorization: Bearer <access_token>
Content-Type: application/json
Prefer: transient

{
  "q": "SELECT id, name, scriptid, isinactive FROM customlist_ship_method WHERE isinactive = ?",
  "params": ["F"]
}

5. Read or create one custom record through the REST record API

GET https://1234567-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/customrecord_qc_inspection/42

POST https://1234567-sb1.suitetalk.api.netsuite.com/services/rest/record/v1/customrecord_qc_inspection
Content-Type: application/json

{
  "name": "QC-2026-0142",
  "custrecord_qc_result": { "id": "1" }
}

Before running, confirm in Setup > Records Catalog that the list and record tables exist with these columns in your account. The name column exists on a custom record only when Include Name Field is ticked on the record type; remove r.name otherwise. Blocks 2 and 3 are SQL; blocks 4 and 5 are HTTP requests. REST access to custom records needs the record type's permission on the integration role.

Get your custom record queries written

Send us your custom record definitions and the report you need and we will return tested SuiteQL for your account.

Optional. The tool and every export work without this. No spam.

Was this tool useful?

How to use it

Enter the script ID of the custom list and the custom record type exactly as shown at Customization > Lists, Records and Fields, in lower case. Add the custom record fields you want as a comma list, each prefixed with r., and name one List/Record field to show as text through BUILTIN.DF. If a transaction body field points to the custom record, enter its custbody ID to get the join. Copy block 1, 2 or 3 into your SuiteQL tool or N/query, or use block 4 to call it from an integration. Block 5 shows the record API alternative when you need one record by ID or want to create one.

Where custom objects live in SuiteQL

A custom list such as customlist_ship_method is a table with id, name, scriptid and isinactive. A custom record type such as customrecord_qc_inspection is a table with system columns (id, externalid, created, lastmodified, owner, isinactive, and name if enabled) plus one column per custrecord field. Fields of type List/Record store the internal ID of the target, so BUILTIN.DF turns them into the display value without a join. Body fields on transactions that point to custom records appear as columns on transaction; line fields appear on transactionline. Setup > Records Catalog lists the exact columns and joins for your account, which is the authority when a column name is in doubt.

Worked example

Quality inspections are stored in customrecord_qc_inspection, the result is a List/Record field custrecord_qc_result pointing to customlist_qc_result, and sales orders link to inspections through custbody_qc_inspection. Block 2 lists inspections newest first with the result as text. Block 3 returns every transaction with a linked inspection, its number, type, date and the inspection result, which is the report quality managers usually ask for. Called through REST with limit=1000, an integration can page through results using the offset rule (offset divisible by limit) and the hasMore flag in the response.

Gotchas

Table and column names are the script IDs in lower case; mixed case copied from a UI label fails. The name column is missing when the record type does not include a name field. Multi-select fields return the selected IDs rather than one value, so filtering them needs a different approach than an equality test; check how your account exposes them in the Records Catalog before writing that filter. Inactive list values are still referenced by old records, so do not filter them out when you are decoding historical data. Finally, SuiteQL respects record-level permissions on custom records: an integration role without access to the record type returns an error or no rows.

Frequently Asked Questions

How do I query a custom list from SuiteQL?

Use the list's script ID as the table: SELECT id, name, scriptid, isinactive FROM customlist_ship_method. To show a list value on another record without joining, wrap the referencing field in BUILTIN.DF, for example BUILTIN.DF(t.custbody_ship_method). Confirm the table in Setup > Records Catalog first.

What are the SuiteQL table names for custom record types?

The custom record type's script ID in lower case, for example customrecord_qc_inspection. Its custom fields are columns named by their custrecord script IDs. Standard tables use names like transaction, transactionline, customer and item. The Records Catalog lists every available table and its joins for your account and role.

Can I access custom records through the NetSuite REST API?

Yes. The record API supports custom records at /services/rest/record/v1/customrecord_x for create, read, update and delete, and SuiteQL reads them through /services/rest/query/v1/suiteql. A RESTlet is only needed when you want custom logic, validation or a combined response in a single call.

Why does BUILTIN.DF return a number instead of a name?

BUILTIN.DF returns the display value for fields that reference another record or list. On a plain number, text or date field it returns the value itself. Check that the field is a List/Record type in its definition. Multi-select fields may need different handling, so test them separately.

If you want users to ask about inspections, approvals or any custom record in plain English and get answers from NetSuite on your own servers, we can set that up.

ArchRay builder
Design the on-prem AI stack for NetSuite: model, GPUs, RAG pipeline, guardrails
See memory, speed and cost as you swap parts, then export the diagram. Free, in your browser.
Open the builder

Keep exploring

Free tools

ERP fixes and how-tos

AI on your ERP

Integrations

Comparisons

Software