nodestash

Contact Management

Create, organize, and search your contacts effectively

This guide covers common patterns for managing contacts — from creation and enrichment to searching and bulk operations.

Creating Contacts

Basic Contact

curl -X POST https://api.nodestash.io/v1/contacts \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alex@startup.io",
    "first_name": "Alex",
    "last_name": "Rivera"
  }'
const contact = await client.contacts.create({
  email: 'alex@startup.io',
  first_name: 'Alex',
  last_name: 'Rivera',
})

Fully Enriched Contact

curl -X POST https://api.nodestash.io/v1/contacts \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alex@startup.io",
    "first_name": "Alex",
    "last_name": "Rivera",
    "phone": "+1-555-0200",
    "title": "CTO",
    "company_id": "co_abc123",
    "source": "conference",
    "tags": ["decision-maker", "technical"],
    "custom_fields": {
      "linkedin": "https://linkedin.com/in/alexrivera"
    }
  }'
const contact = await client.contacts.create({
  email: 'alex@startup.io',
  first_name: 'Alex',
  last_name: 'Rivera',
  phone: '+1-555-0200',
  title: 'CTO',
  company_id: 'co_abc123',
  source: 'conference',
  tags: ['decision-maker', 'technical'],
  custom_fields: {
    linkedin: 'https://linkedin.com/in/alexrivera',
  },
})

Using Tags for Organization

Tags let you categorize contacts without rigid hierarchies. A contact can have up to 20 tags.

# Add tags when creating
curl -X POST https://api.nodestash.io/v1/contacts \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "buyer@corp.com",
    "first_name": "Jordan",
    "tags": ["lead", "inbound", "enterprise"]
  }'

# Update tags on existing contact
curl -X PATCH https://api.nodestash.io/v1/contacts/ct_abc123 \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": ["customer", "enterprise", "champion"]
  }'
// Add tags when creating
const contact = await client.contacts.create({
  email: 'buyer@corp.com',
  first_name: 'Jordan',
  tags: ['lead', 'inbound', 'enterprise'],
})

// Update tags on existing contact
await client.contacts.update('ct_abc123', {
  tags: ['customer', 'enterprise', 'champion'],
})

Updating tags replaces the entire tag array — include all desired tags in the update.

Adding Custom Fields

Define structured fields and attach values to contacts:

# 1. Define a custom field
curl -X POST https://api.nodestash.io/v1/custom-fields \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entity_type": "contact",
    "name": "Lead Score",
    "slug": "lead_score",
    "field_type": "number",
    "description": "Computed lead score from 0-100"
  }'

# 2. Set the value on a contact
curl -X PUT https://api.nodestash.io/v1/contacts/ct_abc123/custom-fields \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "lead_score": 85
    }
  }'
// 1. Define a custom field
await client.customFields.definitions.create({
  entity_type: 'contact',
  name: 'Lead Score',
  slug: 'lead_score',
  field_type: 'number',
  description: 'Computed lead score from 0-100',
})

// 2. Set the value on a contact
await client.customFields.values.set('contacts', 'ct_abc123', {
  fields: {
    lead_score: 85,
  },
})

Searching Contacts

Filter by Multiple Criteria

# Enterprise contacts from the website source
curl "https://api.nodestash.io/v1/contacts?tags=enterprise&source=website&sort=-created_at" \
  -H "Authorization: Bearer $NODESTASH_API_KEY"
const { data } = await client.contacts.list({
  tags: 'enterprise',
  source: 'website',
  sort: '-created_at',
})

Search by Name or Email

# Search by email domain (substring match)
curl "https://api.nodestash.io/v1/contacts?email=acme.com" \
  -H "Authorization: Bearer $NODESTASH_API_KEY"

# Search by name
curl "https://api.nodestash.io/v1/contacts?first_name=alex" \
  -H "Authorization: Bearer $NODESTASH_API_KEY"
// Search by email domain
const { data: acmeContacts } = await client.contacts.list({
  email: 'acme.com',
})

// Search by name
const { data: alexes } = await client.contacts.list({
  first_name: 'alex',
})

Iterating All Contacts

For bulk operations, use the SDK's auto-pagination:

// Export all contacts
const allContacts = []
for await (const contact of client.contacts.listAll({
  sort: 'created_at',
  limit: 100,
})) {
  allContacts.push(contact)
}

console.log(`Total contacts: ${allContacts.length}`)

Idempotent Creation

Use idempotency keys to safely retry contact creation:

curl -X POST https://api.nodestash.io/v1/contacts \
  -H "Authorization: Bearer $NODESTASH_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: import-contact-alex-rivera" \
  -d '{
    "email": "alex@startup.io",
    "first_name": "Alex",
    "last_name": "Rivera"
  }'
const contact = await client.contacts.create(
  {
    email: 'alex@startup.io',
    first_name: 'Alex',
    last_name: 'Rivera',
  },
  'import-contact-alex-rivera', // idempotency key
)

If the same idempotency key is used again, the API returns the original contact instead of creating a duplicate.

Next Steps

  • Link contacts to Companies for organizational hierarchy
  • Track interactions with Activities
  • Attach contacts to Deals in your sales pipeline

On this page