Contact Record API
Create, read, update, and delete contact records. Contacts are individuals associated with customers, vendors, or partners.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /record/v1/contact | List all contacts |
GET | /record/v1/contact/{id} | Get specific contact |
POST | /record/v1/contact | Create new contact |
PATCH | /record/v1/contact/{id} | Update existing contact |
DELETE | /record/v1/contact/{id} | Delete contact |
Base URL
https://{account_id}.suitetalk.api.netsuite.com/services/rest/record/v1/contact
Key Fields
Identification
| Field | Type | Description | Required |
|---|---|---|---|
id | string | Internal ID (read-only) | - |
entityId | string | Contact ID | No |
salutation | string | Title/salutation (Mr., Mrs., Dr., etc.) | No |
firstName | string | First name | No |
middleName | string | Middle name | No |
lastName | string | Last name | Yes |
suffix | string | Name suffix (Jr., Sr., III, etc.) | No |
title | string | Job title | No |
subsidiary | object | Primary subsidiary | Yes (if OneWorld) |
Contact Information
| Field | Type | Description | Required |
|---|---|---|---|
email | string | Primary email address | No |
altEmail | string | Alternate email | No |
phone | string | Primary phone | No |
homePhone | string | Home phone | No |
mobilePhone | string | Mobile phone | No |
officePhone | string | Office phone | No |
fax | string | Fax number | No |
Relationships
| Field | Type | Description | Required |
|---|---|---|---|
company | object | Associated customer/vendor/partner | No |
supervisor | object | Reports to (contact reference) | No |
subsidiary | object | Primary subsidiary | Yes (if OneWorld) |
Status & Preferences
| Field | Type | Description | Required |
|---|---|---|---|
isInactive | boolean | Inactive flag | No |
isPrivate | boolean | Private contact (visible only to creator) | No |
globalSubscriptionStatus | object | Email subscription status | No |
Additional Information
| Field | Type | Description | Required |
|---|---|---|---|
comments | string | Notes/comments | No |
defaultAddress | string | Default address text | No |
image | object | Contact photo/image file | No |
assistantName | string | Assistant's name | No |
assistantPhone | string | Assistant's phone | No |
Social Media
| Field | Type | Description |
|---|---|---|
socialProfileFacebook | string | Facebook profile URL |
socialProfileTwitter | string | Twitter handle |
socialProfileLinkedIn | string | LinkedIn profile URL |
socialProfileGooglePlus | string | Google+ profile URL |
Sublists/Collections
| Field | Type | Description |
|---|---|---|
addressBook | collection | Contact addresses |
Example: Create Contact for Customer
POST /record/v1/contact
Content-Type: application/json
Authorization: Bearer {access_token}
{
"salutation": "Mr.",
"firstName": "John",
"middleName": "A.",
"lastName": "Smith",
"title": "Purchasing Manager",
"company": {
"id": "456"
},
"email": "john.smith@acmecorp.com",
"phone": "555-0500",
"mobilePhone": "555-0501",
"officePhone": "555-0100 ext. 234",
"subsidiary": {
"id": "1"
},
"comments": "Primary contact for purchasing decisions. Prefers email communication.",
"isPrivate": false
}
Response
{
"links": [
{
"rel": "self",
"href": "https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/contact/890"
}
],
"id": "890",
"refName": "John Smith",
"entityId": "CONT-890",
"salutation": "Mr.",
"firstName": "John",
"middleName": "A.",
"lastName": "Smith",
"title": "Purchasing Manager",
"email": "john.smith@acmecorp.com",
"phone": "555-0500",
"mobilePhone": "555-0501",
"company": {
"id": "456",
"refName": "Acme Corporation"
},
"subsidiary": {
"id": "1",
"refName": "Parent Company"
},
"isInactive": false,
"isPrivate": false
}
Example: Update Contact
PATCH /record/v1/contact/890
Content-Type: application/json
Authorization: Bearer {access_token}
{
"email": "j.smith@acmecorp.com",
"title": "Senior Purchasing Manager",
"mobilePhone": "555-0999",
"comments": "Promoted to Senior Purchasing Manager. Updated contact preferences."
}
Response
{
"links": [
{
"rel": "self",
"href": "https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/contact/890"
}
],
"id": "890",
"refName": "John Smith",
"firstName": "John",
"lastName": "Smith",
"title": "Senior Purchasing Manager",
"email": "j.smith@acmecorp.com",
"mobilePhone": "555-0999",
"company": {
"id": "456",
"refName": "Acme Corporation"
}
}
Example: Create Standalone Contact
Contacts don't require a company association:
POST /record/v1/contact
Content-Type: application/json
Authorization: Bearer {access_token}
{
"firstName": "Sarah",
"lastName": "Johnson",
"email": "sarah.j@email.com",
"phone": "555-0600",
"subsidiary": {
"id": "1"
},
"comments": "Industry analyst - not associated with specific account",
"isPrivate": false
}
Response
{
"links": [
{
"rel": "self",
"href": "https://1234567.suitetalk.api.netsuite.com/services/rest/record/v1/contact/891"
}
],
"id": "891",
"refName": "Sarah Johnson",
"firstName": "Sarah",
"lastName": "Johnson",
"email": "sarah.j@email.com",
"phone": "555-0600",
"isInactive": false
}
Example: Add Contact with Address
POST /record/v1/contact
Content-Type: application/json
Authorization: Bearer {access_token}
{
"firstName": "Michael",
"lastName": "Chen",
"company": {
"id": "456"
},
"email": "michael.chen@acmecorp.com",
"phone": "555-0700",
"subsidiary": {
"id": "1"
},
"addressBook": {
"items": [
{
"defaultShipping": false,
"defaultBilling": false,
"label": "Office Address",
"addressBookAddress": {
"addr1": "456 Business Park Drive",
"addr2": "Suite 200",
"city": "San Francisco",
"state": "CA",
"zip": "94105",
"country": {
"refName": "US"
},
"attention": "Michael Chen"
}
}
]
}
}
Query Filters
Find Contacts by Company
GET /record/v1/contact?q=company='456'
Find Contacts by Email
GET /record/v1/contact?q=email='john.smith@acmecorp.com'
Find Active Contacts
GET /record/v1/contact?q=isInactive=false
Find Contacts by Name
GET /record/v1/contact?q=firstName='John' AND lastName='Smith'
Find Contacts by Last Name Pattern
GET /record/v1/contact?q=lastName LIKE 'Smith%'
Find Contacts by Phone
GET /record/v1/contact?q=phone LIKE '555-05%'
Find Private Contacts
GET /record/v1/contact?q=isPrivate=true
Find Contacts by Subsidiary
GET /record/v1/contact?q=subsidiary='1'
Common Use Cases
1. Primary Contact on Customer Record
When creating a customer, you can reference a contact:
// First, create the contact
const contact = await createContact({
firstName: "John",
lastName: "Smith",
email: "john@acme.com",
company: { id: customerId },
subsidiary: { id: "1" }
});
// Then reference on customer record
await patchCustomer(customerId, {
contact: { id: contact.id }
});
2. Multiple Contacts per Customer
Use the Customer's contactRoles sublist to associate multiple contacts with different roles:
// On customer record
await patchCustomer(customerId, {
contactRoles: {
items: [
{
contact: { id: "890" },
role: { id: "1" }, // Purchasing
isPrimary: true,
email: true,
giveAccess: true
},
{
contact: { id: "891" },
role: { id: "2" }, // Billing
email: true,
giveAccess: false
},
{
contact: { id: "892" },
role: { id: "3" }, // Technical
email: true,
giveAccess: true
}
]
}
});
3. Link Contact to Address
Contacts can be associated with specific customer addresses:
await createContact({
firstName: "Jane",
lastName: "Doe",
company: { id: "456" },
email: "jane@acme.com",
subsidiary: { id: "1" },
addressBook: {
items: [
{
addressBookAddress: {
addr1: "789 Main Street",
city: "New York",
state: "NY",
zip: "10001",
country: { refName: "US" }
}
}
]
}
});
4. Set Contact as Transaction Contact
When creating transactions, specify the contact:
// Sales Order
await createSalesOrder({
entity: { id: "456" },
custbody_contact: { id: "890" },
// ... other fields
});
// Invoice
await createInvoice({
entity: { id: "456" },
custbody_contact: { id: "890" },
// ... other fields
});
5. Manage Email Subscription Status
// Opt-in contact for marketing emails
await patchContact(contactId, {
globalSubscriptionStatus: { id: "CONFIRMED_OPT_IN" }
});
// Opt-out contact from marketing emails
await patchContact(contactId, {
globalSubscriptionStatus: { id: "SOFT_OPT_OUT" }
});
6. Create Private Contact
// Create contact visible only to creator and admins
await createContact({
firstName: "Confidential",
lastName: "Contact",
email: "confidential@example.com",
subsidiary: { id: "1" },
isPrivate: true,
comments: "Confidential negotiation contact"
});
7. Update Contact Social Media
await patchContact(contactId, {
socialProfileLinkedIn: "https://linkedin.com/in/johnsmith",
socialProfileTwitter: "@johnsmith",
socialProfileFacebook: "https://facebook.com/johnsmith"
});
Important Notes
Required Fields
- lastName: Last name is required
- subsidiary: Required in OneWorld accounts
- firstName, middleName, and other fields are optional
Contact vs Customer
- Contact: Individual person
- Customer: Company or individual that you sell to
- Contacts are often associated with company customers but can exist independently
- Individual customers (isPerson=true) are both a customer record and represent a person
Private Contacts
Setting isPrivate=true makes the contact visible only to:
- The user who created it
- Administrators
- Users with "View Private Contacts" permission
Use private contacts for sensitive relationships or confidential negotiations.
Email Subscription Status
The globalSubscriptionStatus field controls whether the contact receives marketing emails:
| Status | Description |
|---|---|
SOFT_OPT_IN | Implied consent (default) |
CONFIRMED_OPT_IN | Explicitly opted in |
SOFT_OPT_OUT | Unsubscribed |
CONFIRMED_OPT_OUT | Explicitly opted out |
Respect these settings when sending marketing communications to comply with regulations like GDPR and CAN-SPAM.
Contact Roles
When associating contacts with customers via contactRoles:
- role: Define the contact's function (Purchasing, Billing, Technical, etc.)
- isPrimary: Designate one contact as primary
- email: Include in email communications
- giveAccess: Provide customer center access
Multiple Phone Numbers
NetSuite supports several phone number fields:
phone: Primary phone (general use)officePhone: Direct office linehomePhone: Personal/home numbermobilePhone: Cell/mobile numberfax: Fax numberassistantPhone: Assistant's contact number
Deleting Contacts
- Cannot delete contacts referenced on transactions
- Cannot delete contacts with customer center access
- Consider marking as inactive instead:
isInactive: true
Best Practices
- Always include email address for business contacts
- Use title field to capture job role
- Populate mobile and office phone when available
- Use comments field for important context or preferences
- Keep contact information up to date
- Use contact roles to define relationships clearly
- Respect privacy settings and email preferences
- Use entityId for external system integration
Contact Role Configuration
Common Contact Roles
| Role | Description | Typical Use |
|---|---|---|
| Purchasing | Buying decisions | Purchase orders, quotes |
| Billing/Accounting | Financial matters | Invoices, payments |
| Technical | Product/service support | Support cases, technical discussions |
| Executive Sponsor | Strategic relationship | High-level communications |
| Operations | Day-to-day operations | Shipping, delivery coordination |
| Legal | Contracts and agreements | Contract review, legal matters |
Setting Up Contact Roles
// Create customer with multiple contact roles
await patchCustomer(customerId, {
contactRoles: {
items: [
{
contact: { id: "890" },
role: { refName: "Purchasing" },
isPrimary: true,
email: true,
giveAccess: true
},
{
contact: { id: "891" },
role: { refName: "Billing" },
email: true,
giveAccess: false
},
{
contact: { id: "892" },
role: { refName: "Technical" },
email: true,
giveAccess: true
}
]
}
});
Integration Scenarios
1. CRM Integration
Sync contacts from external CRM:
// Map CRM contact to NetSuite
const crmContact = getCRMContact(crmId);
const nsContact = await createContact({
firstName: crmContact.firstName,
lastName: crmContact.lastName,
email: crmContact.email,
phone: crmContact.phone,
mobilePhone: crmContact.mobile,
title: crmContact.jobTitle,
company: { id: crmContact.nsCustomerId },
subsidiary: { id: "1" },
// Store CRM ID for future sync
externalId: crmContact.id
});
2. Customer Portal
Create contact with customer center access:
const contact = await createContact({
firstName: "Portal",
lastName: "User",
email: "user@customer.com",
company: { id: customerId },
subsidiary: { id: "1" }
});
// Enable customer center access via customer record
await patchCustomer(customerId, {
contactRoles: {
items: [
{
contact: { id: contact.id },
role: { refName: "Primary Contact" },
isPrimary: true,
giveAccess: true,
email: true
}
]
}
});
3. Email Marketing Integration
Manage email subscription status:
// Sync opt-in from marketing platform
async function syncEmailPreference(contactEmail, optInStatus) {
const contacts = await getContacts(`email='${contactEmail}'`);
if (contacts.length > 0) {
const status = optInStatus ? "CONFIRMED_OPT_IN" : "SOFT_OPT_OUT";
await patchContact(contacts[0].id, {
globalSubscriptionStatus: { id: status }
});
}
}
See Also
- Customer - Associate contacts with customers
- Vendor - Associate contacts with vendors
- Sales Order - Specify contact on transactions