# Contacts ## List contacts `client.users.contacts.list(ContactListParamsparams?, RequestOptionsoptions?): CursorPage` **get** `/v2/contacts` Returns a list of contacts (customers and leads) in your organization using cursor-based pagination. ### Query Parameters - `limit` - Number of contacts to return (1-100, default 10) - `cursor` - Cursor from previous response for pagination - `contactType` - Filter by contact type: "customer" (default), "lead", or "all" ### Response Format Returns a list object with: - `object` - Always "list" - `data` - Array of contact objects - `nextCursor` - Cursor for the next page, or null if no more results ### Contact Object Each contact includes: - `id` - Unique contact identifier - `userId` - External user ID from SSO (if set) - `email` - Contact email address - `name` - Contact display name - `profilePicture` - Profile picture URL - `type` - Contact type ("customer" or "lead") - `companies` - Array of companies the contact belongs to - `customFields` - Custom field values - `postsCreated` - Number of posts created - `commentsCreated` - Number of comments created - `lastActivity` - Last activity timestamp ### Example ```json { "object": "list", "data": [ { "object": "contact", "id": "676f0f6765bdaa7d7d760f88", "email": "john@example.com", "name": "John Doe", "type": "customer", ... } ], "nextCursor": "eyJpZCI6IjUwN2YxZjc3YmNmODZjZDc5OTQzOTAxMSJ9" } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `params: ContactListParams` - `contactType?: "customer" | "lead" | "all"` Query param: Filter contacts by type. Defaults to "customer". - `"customer"` - `"lead"` - `"all"` - `cursor?: string` Query param: An opaque cursor for pagination. Use the nextCursor value from a previous response to fetch the next page of results. - `limit?: number` Query param: A limit on the number of objects to be returned, between 1 and 100. - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` Header param: API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `Data extends Contact | null` User who submitted the response ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); // Automatically fetches more pages as needed. for await (const contact of client.users.contacts.list()) { console.log(contact); } ``` #### Response ```json { "data": [ { "id": "676f0f6765bdaa7d7d760f88", "name": "John Steezy", "object": "contact", "type": "customer", "commentsCreated": 0, "companies": [ { "id": "507f1f77bcf86cd799439011", "companyId": "comp_12345", "companySize": 250, "createdAt": "2025-01-01T12:00:00.000Z", "industry": "Technology", "lastActivity": "2025-01-15T00:00:00.000Z", "linkedUsers": 15, "monthlySpend": 5000, "name": "Acme Inc", "object": "company", "plan": "enterprise", "updatedAt": "2025-01-10T15:30:00.000Z", "website": "https://acme.com", "customFields": { "location": "bar", "priority": "bar" } } ], "customFields": { "foo": "bar" }, "description": "", "email": "john@example.com", "lastActivity": "2025-01-03T21:42:30.181Z", "locale": "en", "manuallyOptedOutFromChangelog": false, "organizationId": "5febde12dc56d60012d47db6", "postsCreated": 0, "profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/anon_23.png", "roles": [ "string" ], "subscribedToChangelog": true, "userId": "676f0f673dbb299c8a4f3057", "verified": true } ], "nextCursor": "eyJpZCI6IjUwN2YxZjc3YmNmODZjZDc5OTQzOTAxMSJ9", "object": "list" } ``` ## Create or update a contact `client.users.contacts.createOrUpdate(ContactCreateOrUpdateParamsparams, RequestOptionsoptions?): ContactCreateOrUpdateResponse` **post** `/v2/contacts` Creates a new contact or updates an existing one. If a contact with the given `email` or `userId` already exists, it will be updated. Otherwise, a new contact will be created. **At least one of `email` or `userId` must be provided for identification.** ### Request Body | Field | Type | Required | Description | | ----------------------- | ------- | ------------------- | --------------------------------------- | | `email` | string | One of email/userId | Contact email address | | `userId` | string | One of email/userId | External user ID from your system | | `name` | string | No | Contact display name | | `profilePicture` | string | No | Profile picture URL | | `companies` | array | No | Companies the contact belongs to | | `customFields` | object | No | Custom field values | | `subscribedToChangelog` | boolean | No | Whether subscribed to changelog | | `locale` | string | No | Contact locale/language | | `phone` | string | No | Contact phone number | | `roles` | array | No | Role IDs to assign | | `userHash` | string | No | HMAC hash for identity verification | | `createdAt` | string | No | When the contact was created (ISO 8601) | ### Company Object Each company in the `companies` array can have: - `id` (required) - External company ID from your system - `name` (required) - Company name - `monthlySpend` - Monthly spend/revenue - `customFields` - Custom field values - `industry` - Industry - `website` - Company website URL - `plan` - Current plan/subscription - `companySize` - Number of employees - `createdAt` - When the company was created ### Response Returns the created or updated contact object. - **201 Created** - A new contact was created - **200 OK** - An existing contact was updated ### Example Request ```json { "email": "john@example.com", "name": "John Doe", "userId": "usr_12345", "companies": [ { "id": "company_123", "name": "Acme Inc", "monthlySpend": 500, "plan": "enterprise" } ], "customFields": { "plan": "pro", "signupSource": "website" }, "subscribedToChangelog": true } ``` ### Example Response ```json { "object": "contact", "id": "676f0f6765bdaa7d7d760f88", "email": "john@example.com", "name": "John Doe", "userId": "usr_12345", "type": "customer", "companies": [...], "customFields": {...}, ... } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `params: ContactCreateOrUpdateParams` - `companies?: Array` Body param: Companies the contact belongs to - `id: string` External company ID from your system - `name: string` Company name - `companyHash?: string` HMAC-SHA256 hash of company ID for identity verification - `companySize?: number | null` Number of employees in the company - `createdAt?: string | null` When the company was created (ISO 8601) - `customFields?: CustomFields` Custom field values on the company. Values can be string, number, boolean, null, or array of primitives. - `industry?: string` - `plan?: string` - `priority?: string` - `industry?: string` Industry the company operates in - `monthlySpend?: number` Monthly spend/revenue from this company - `plan?: string` Current plan/subscription name - `website?: string` Company website URL - `createdAt?: string | null` Body param: When the contact was created in your system (ISO 8601) - `customFields?: CustomFields` Body param: Custom field values on the contact. Values can be string, number, boolean, null, or array of primitives. - `accountType?: string` - `plan?: string` - `signupSource?: string` - `email?: string` Body param: Contact email address. Used for identification if userId is not provided. - `locale?: string` Body param: Contact locale/language preference - `name?: string` Body param: Contact display name - `phone?: string | null` Body param: Contact phone number - `profilePicture?: string | null` Body param: Profile picture URL - `roles?: Array` Body param: Array of role IDs to assign to the contact - `subscribedToChangelog?: boolean` Body param: Whether the contact is subscribed to changelog updates - `userHash?: string` Body param: HMAC-SHA256 hash of userId or email for identity verification - `userId?: string` Body param: External user ID from your system. Takes precedence over email for identification. - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` Header param: API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `ContactCreateOrUpdateResponse extends Contact | null` User who submitted the response ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const response = await client.users.contacts.createOrUpdate(); console.log(response); ``` #### Response ```json { "id": "676f0f6765bdaa7d7d760f88", "name": "John Steezy", "object": "contact", "type": "customer", "commentsCreated": 0, "companies": [ { "id": "507f1f77bcf86cd799439011", "companyId": "comp_12345", "companySize": 250, "createdAt": "2025-01-01T12:00:00.000Z", "industry": "Technology", "lastActivity": "2025-01-15T00:00:00.000Z", "linkedUsers": 15, "monthlySpend": 5000, "name": "Acme Inc", "object": "company", "plan": "enterprise", "updatedAt": "2025-01-10T15:30:00.000Z", "website": "https://acme.com", "customFields": { "location": "bar", "priority": "bar" } } ], "customFields": { "foo": "bar" }, "description": "", "email": "john@example.com", "lastActivity": "2025-01-03T21:42:30.181Z", "locale": "en", "manuallyOptedOutFromChangelog": false, "organizationId": "5febde12dc56d60012d47db6", "postsCreated": 0, "profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/anon_23.png", "roles": [ "string" ], "subscribedToChangelog": true, "userId": "676f0f673dbb299c8a4f3057", "verified": true } ``` ## Get contact by ID `client.users.contacts.retrieve(stringid, ContactRetrieveParamsparams?, RequestOptionsoptions?): ContactRetrieveResponse` **get** `/v2/contacts/{id}` Retrieves a single contact by their Featurebase ID. Returns both customers and leads. ### Path Parameters - `id` - The Featurebase contact ID (24-character ObjectId) ### Response Format Returns a single contact object with: - `object` - Always "contact" - `id` - Unique contact identifier - `userId` - External user ID from SSO (if set) - `email` - Contact email address - `name` - Contact display name - `profilePicture` - Profile picture URL - `type` - Contact type ("customer" or "lead") - `companies` - Array of companies the contact belongs to - `customFields` - Custom field values - `postsCreated` - Number of posts created - `commentsCreated` - Number of comments created - `lastActivity` - Last activity timestamp ### Example ```json { "object": "contact", "id": "676f0f6765bdaa7d7d760f88", "email": "john@example.com", "name": "John Doe", "type": "customer", ... } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `id: string` Featurebase contact ID - `params: ContactRetrieveParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `ContactRetrieveResponse extends Contact | null` User who submitted the response ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const contact = await client.users.contacts.retrieve('507f1f77bcf86cd799439011'); console.log(contact); ``` #### Response ```json { "id": "676f0f6765bdaa7d7d760f88", "name": "John Steezy", "object": "contact", "type": "customer", "commentsCreated": 0, "companies": [ { "id": "507f1f77bcf86cd799439011", "companyId": "comp_12345", "companySize": 250, "createdAt": "2025-01-01T12:00:00.000Z", "industry": "Technology", "lastActivity": "2025-01-15T00:00:00.000Z", "linkedUsers": 15, "monthlySpend": 5000, "name": "Acme Inc", "object": "company", "plan": "enterprise", "updatedAt": "2025-01-10T15:30:00.000Z", "website": "https://acme.com", "customFields": { "location": "bar", "priority": "bar" } } ], "customFields": { "foo": "bar" }, "description": "", "email": "john@example.com", "lastActivity": "2025-01-03T21:42:30.181Z", "locale": "en", "manuallyOptedOutFromChangelog": false, "organizationId": "5febde12dc56d60012d47db6", "postsCreated": 0, "profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/anon_23.png", "roles": [ "string" ], "subscribedToChangelog": true, "userId": "676f0f673dbb299c8a4f3057", "verified": true } ``` ## Delete contact by ID `client.users.contacts.delete(stringid, ContactDeleteParamsparams?, RequestOptionsoptions?): DeletedContact` **delete** `/v2/contacts/{id}` Permanently deletes a contact by their Featurebase ID. Supports deleting both customers and leads. ### Path Parameters - `id` - The Featurebase contact ID (24-character ObjectId) ### Deletion Behavior When a contact is deleted: - The contact record is permanently removed - Associated data cleanup is triggered asynchronously - Comments and posts created by the contact are handled according to retention policies ### Response Returns a deletion confirmation object: - `id` - The ID of the deleted contact - `object` - Always "contact" - `deleted` - Always `true` ### Example Response ```json { "id": "676f0f6765bdaa7d7d760f88", "object": "contact", "deleted": true } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `id: string` Featurebase contact ID - `params: ContactDeleteParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `DeletedContact` - `id: string` Unique identifier of the deleted contact - `deleted: true` Indicates the resource was deleted - `true` - `object: "contact"` Object type identifier - `"contact"` ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const deletedContact = await client.users.contacts.delete('507f1f77bcf86cd799439011'); console.log(deletedContact.id); ``` #### Response ```json { "id": "507f1f77bcf86cd799439011", "deleted": true, "object": "contact" } ``` ## Block a contact `client.users.contacts.block(stringid, ContactBlockParamsparams?, RequestOptionsoptions?): ContactBlockResponse` **post** `/v2/contacts/{id}/block` Blocks a contact by their Featurebase ID from the messenger/inbox. ### Path Parameters - `id` - The Featurebase internal ID of the contact (MongoDB ObjectId) ### Supported Contact Types This endpoint blocks both: - **Customers** - Users with registered accounts - **Leads** - Anonymous or unregistered visitors ### Blocking Behavior When a contact is blocked: - The contact cannot send new messages via messenger - Existing conversations are not deleted but no new messages can be added by the blocked user - The block can be removed by unblocking the contact ### Response Returns a block confirmation object: - `id` - The ID of the blocked contact - `object` - Always "contact" - `blocked` - Always `true` ### Example Response ```json { "id": "507f1f77bcf86cd799439011", "object": "contact", "blocked": true } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `id: string` Featurebase contact ID - `params: ContactBlockParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `ContactBlockResponse` - `id: string` Unique identifier of the blocked contact - `blocked: true` Indicates the contact was blocked - `true` - `object: "contact"` Object type identifier - `"contact"` ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const response = await client.users.contacts.block('507f1f77bcf86cd799439011'); console.log(response.id); ``` #### Response ```json { "id": "507f1f77bcf86cd799439011", "blocked": true, "object": "contact" } ``` ## Unblock a contact `client.users.contacts.unblock(stringid, ContactUnblockParamsparams?, RequestOptionsoptions?): ContactUnblockResponse` **post** `/v2/contacts/{id}/unblock` Unblocks a contact by their Featurebase ID from the messenger/inbox. ### Path Parameters - `id` - The Featurebase internal ID of the contact (MongoDB ObjectId) ### Supported Contact Types This endpoint unblocks both: - **Customers** - Users with registered accounts - **Leads** - Anonymous or unregistered visitors ### Unblocking Behavior When a contact is unblocked: - The contact can resume sending messages via messenger - Previously blocked conversations remain intact - The contact regains full messenger functionality ### Response Returns an unblock confirmation object: - `id` - The ID of the unblocked contact - `object` - Always "contact" - `unblocked` - Always `true` ### Example Response ```json { "id": "507f1f77bcf86cd799439011", "object": "contact", "unblocked": true } ``` ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `id: string` Featurebase contact ID - `params: ContactUnblockParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `ContactUnblockResponse` - `id: string` Unique identifier of the unblocked contact - `object: "contact"` Object type identifier - `"contact"` - `unblocked: true` Indicates the contact was unblocked - `true` ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const response = await client.users.contacts.unblock('507f1f77bcf86cd799439011'); console.log(response.id); ``` #### Response ```json { "id": "507f1f77bcf86cd799439011", "object": "contact", "unblocked": true } ``` ## Domain Types ### Contact - `Contact` User who submitted the response - `id: string` Unique identifier - `name: string` Contact display name - `object: "contact"` Object type identifier - `"contact"` - `type: "customer" | "lead"` Type of contact - `"customer"` - `"lead"` - `commentsCreated?: number` Number of comments created - `companies?: Array` Companies the contact belongs to - `id: string` Featurebase internal ID - `companyId: string` External company ID from your system - `companySize: number | null` Company employee headcount - `createdAt: string | null` ISO date when company was created - `industry: string | null` Industry - `lastActivity: string | null` ISO date of last activity - `linkedUsers: number | null` Number of users linked to this company - `monthlySpend: number | null` Monthly spend - `name: string` Company name - `object: "company"` Object type identifier - `"company"` - `plan: string | null` Plan or tier name - `updatedAt: string | null` ISO date when company was last updated - `website: string | null` Company website URL - `customFields?: Record` Custom field values - `customFields?: Record` Custom field values on the contact - `description?: string` Contact description/bio - `email?: string | null` Contact email - `lastActivity?: string` Last activity ISO timestamp - `locale?: string` Contact locale - `manuallyOptedOutFromChangelog?: boolean` Whether manually opted out from changelog - `organizationId?: string` Organization ID the contact belongs to - `postsCreated?: number` Number of posts created - `profilePicture?: string | null` Profile picture URL - `roles?: Array` Contact roles - `subscribedToChangelog?: boolean` Whether subscribed to changelog - `userId?: string` External user ID from SSO - `verified?: boolean` Whether email is verified ### Contact List - `ContactList` - `data: Array` Array of contacts - `nextCursor: string | null` Cursor for fetching the next page (cursor-based pagination) - `object: "list"` Object type identifier - `"list"` ### Deleted Contact - `DeletedContact` - `id: string` Unique identifier of the deleted contact - `deleted: true` Indicates the resource was deleted - `true` - `object: "contact"` Object type identifier - `"contact"` ### Contact Create Or Update Response - `ContactCreateOrUpdateResponse extends Contact | null` User who submitted the response ### Contact Retrieve Response - `ContactRetrieveResponse extends Contact | null` User who submitted the response ### Contact Block Response - `ContactBlockResponse` - `id: string` Unique identifier of the blocked contact - `blocked: true` Indicates the contact was blocked - `true` - `object: "contact"` Object type identifier - `"contact"` ### Contact Unblock Response - `ContactUnblockResponse` - `id: string` Unique identifier of the unblocked contact - `object: "contact"` Object type identifier - `"contact"` - `unblocked: true` Indicates the contact was unblocked - `true` # By User ID ## Get contact by external user ID `client.users.contacts.byUserID.retrieve(stringuserID, ByUserIDRetrieveParamsparams?, RequestOptionsoptions?): ByUserIDRetrieveResponse` **get** `/v2/contacts/by-user-id/{userId}` Retrieves a single contact by their external user ID (from your system via SSO). **Important:** This endpoint only returns customers (type: "customer"). Leads are not returned. ### Path Parameters - `userId` - The external user ID from your system (matched via SSO integration) ### Response Format Returns a single contact object with: - `object` - Always "contact" - `id` - Unique contact identifier - `userId` - External user ID from SSO - `email` - Contact email address - `name` - Contact display name - `profilePicture` - Profile picture URL - `type` - Always "customer" for this endpoint - `companies` - Array of companies the contact belongs to - `customFields` - Custom field values - `postsCreated` - Number of posts created - `commentsCreated` - Number of comments created - `lastActivity` - Last activity timestamp ### Example ```json { "object": "contact", "id": "676f0f6765bdaa7d7d760f88", "userId": "usr_12345", "email": "john@example.com", "name": "John Doe", "type": "customer", ... } ``` ### Use Case This endpoint is useful when you need to look up a contact using your own system's user identifier, such as when displaying Featurebase data alongside your user's information in your own application. ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `userID: string` External user ID from your system - `params: ByUserIDRetrieveParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `ByUserIDRetrieveResponse extends Contact | null` User who submitted the response ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const byUserID = await client.users.contacts.byUserID.retrieve('usr_12345'); console.log(byUserID); ``` #### Response ```json { "id": "676f0f6765bdaa7d7d760f88", "name": "John Steezy", "object": "contact", "type": "customer", "commentsCreated": 0, "companies": [ { "id": "507f1f77bcf86cd799439011", "companyId": "comp_12345", "companySize": 250, "createdAt": "2025-01-01T12:00:00.000Z", "industry": "Technology", "lastActivity": "2025-01-15T00:00:00.000Z", "linkedUsers": 15, "monthlySpend": 5000, "name": "Acme Inc", "object": "company", "plan": "enterprise", "updatedAt": "2025-01-10T15:30:00.000Z", "website": "https://acme.com", "customFields": { "location": "bar", "priority": "bar" } } ], "customFields": { "foo": "bar" }, "description": "", "email": "john@example.com", "lastActivity": "2025-01-03T21:42:30.181Z", "locale": "en", "manuallyOptedOutFromChangelog": false, "organizationId": "5febde12dc56d60012d47db6", "postsCreated": 0, "profilePicture": "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/anon_23.png", "roles": [ "string" ], "subscribedToChangelog": true, "userId": "676f0f673dbb299c8a4f3057", "verified": true } ``` ## Delete contact by external user ID `client.users.contacts.byUserID.delete(stringuserID, ByUserIDDeleteParamsparams?, RequestOptionsoptions?): DeletedContact` **delete** `/v2/contacts/by-user-id/{userId}` Permanently deletes a contact by their external user ID. **Important:** This endpoint only deletes customers (type: "customer"). Leads cannot be deleted using this endpoint. ### Path Parameters - `userId` - The external user ID from your system ### Deletion Behavior When a contact is deleted: - The contact record is permanently removed - Associated data cleanup is triggered asynchronously - Comments and posts created by the contact are handled according to retention policies ### Response Returns a deletion confirmation object: - `id` - The ID of the deleted contact - `object` - Always "contact" - `deleted` - Always `true` ### Example Response ```json { "id": "676f0f6765bdaa7d7d760f88", "object": "contact", "deleted": true } ``` ### Use Case Use this endpoint when you need to delete a contact using your own system's user identifier, such as when a user deletes their account in your application. ### Version Availability This endpoint is only available in API version 2026-01-01.nova and newer. ### Parameters - `userID: string` External user ID from your system - `params: ByUserIDDeleteParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `DeletedContact` - `id: string` Unique identifier of the deleted contact - `deleted: true` Indicates the resource was deleted - `true` - `object: "contact"` Object type identifier - `"contact"` ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const deletedContact = await client.users.contacts.byUserID.delete('usr_12345'); console.log(deletedContact.id); ``` #### Response ```json { "id": "507f1f77bcf86cd799439011", "deleted": true, "object": "contact" } ``` ## Domain Types ### By User ID Retrieve Response - `ByUserIDRetrieveResponse extends Contact | null` User who submitted the response # Email Preferences ## Get contact email preferences by external user ID `client.users.contacts.byUserID.emailPreferences.retrieve(stringuserID, EmailPreferenceRetrieveParamsparams?, RequestOptionsoptions?): PreferencesOutput` **get** `/v2/contacts/by-user-id/{userId}/email-preferences` Retrieves the email preference state for a customer contact by their external user ID. This endpoint only supports customer contacts and mirrors the existing `by-user-id` lookup pattern used across the contact API. ### Path Parameters - `userId` - The external user ID from your system ### Example Response ```json { "object": "contact_email_preferences", "contactId": "676f0f6765bdaa7d7d760f88", "userId": "usr_12345", "email": "john@example.com", "preferences": { "all": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" }, "postUpdates": { "status": "subscribed", "effectiveStatus": "unsubscribed" }, "postComments": { "status": "subscribed", "effectiveStatus": "unsubscribed" }, "commentReplies": { "status": "subscribed", "effectiveStatus": "unsubscribed" }, "changelog": { "status": "subscribed", "effectiveStatus": "unsubscribed" } } } ``` ### Parameters - `userID: string` External user ID from your system - `params: EmailPreferenceRetrieveParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `PreferencesOutput` - `contactId: string` Featurebase contact ID - `object: "contact_email_preferences"` Object type identifier - `"contact_email_preferences"` - `preferences: Preferences` Email preference state for this contact, including both stored status and final effective status. - `all: PreferenceState` Global email preference state for all email notifications. - `effectiveStatus: "subscribed" | "unsubscribed"` Final effective status after applying global preference overrides - `"subscribed"` - `"unsubscribed"` - `status: "subscribed" | "unsubscribed"` Stored preference status for this category - `"subscribed"` - `"unsubscribed"` - `changelog: PreferenceState` Global email preference state for all email notifications. - `commentReplies: PreferenceState` Global email preference state for all email notifications. - `postComments: PreferenceState` Global email preference state for all email notifications. - `postUpdates: PreferenceState` Global email preference state for all email notifications. - `email?: string | null` Contact email address, if available - `userId?: string | null` External user ID from your system, if available ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const preferencesOutput = await client.users.contacts.byUserID.emailPreferences.retrieve( 'usr_12345', ); console.log(preferencesOutput.contactId); ``` #### Response ```json { "contactId": "676f0f6765bdaa7d7d760f88", "object": "contact_email_preferences", "preferences": { "all": { "effectiveStatus": "unsubscribed", "status": "unsubscribed" }, "changelog": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "commentReplies": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postComments": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postUpdates": { "effectiveStatus": "unsubscribed", "status": "subscribed" } }, "email": "john@example.com", "userId": "usr_12345" } ``` ## Update contact email preferences by external user ID `client.users.contacts.byUserID.emailPreferences.update(stringuserID, EmailPreferenceUpdateParamsparams, RequestOptionsoptions?): PreferencesOutput` **patch** `/v2/contacts/by-user-id/{userId}/email-preferences` Updates one or more email preferences for a customer contact by their external user ID. This endpoint only supports customer contacts and mirrors the existing `by-user-id` lookup pattern used across the contact API. ### Path Parameters - `userId` - The external user ID from your system ### Request Body - `preferences` - A partial map of preference keys to their desired stored status. Only the preferences included in the request are updated; any preferences omitted are left unchanged. At least one preference must be provided. See `PATCH /v2/contacts/{id}/email-preferences` for the full list of supported preference keys and per-key values, the `all` delivery-gate semantics, and details on combining `all` with per-category keys in a single request. ### Example Request (partial update) ```json { "preferences": { "postUpdates": "unsubscribed", "changelog": "subscribed" } } ``` ### Example Request (full preference-center submit) ```json { "preferences": { "all": "subscribed", "postUpdates": "subscribed", "postComments": "unsubscribed", "commentReplies": "unsubscribed", "changelog": "unsubscribed" } } ``` ### Example Response ```json { "object": "contact_email_preferences", "contactId": "676f0f6765bdaa7d7d760f88", "userId": "usr_12345", "email": "john@example.com", "preferences": { "all": { "status": "subscribed", "effectiveStatus": "subscribed" }, "postUpdates": { "status": "subscribed", "effectiveStatus": "subscribed" }, "postComments": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" }, "commentReplies": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" }, "changelog": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" } } } ``` ### Parameters - `userID: string` External user ID from your system - `params: EmailPreferenceUpdateParams` - `preferences: Preferences` Body param - `all?: "subscribed" | "unsubscribed"` Master delivery gate. When `unsubscribed`, the contact receives no emails regardless of the per-category values. Per-category values are preserved. - `"subscribed"` - `"unsubscribed"` - `changelog?: "subscribed" | "unsubscribed"` Stored status for new changelog release notifications. - `"subscribed"` - `"unsubscribed"` - `commentReplies?: "subscribed" | "unsubscribed"` Stored status for replies to the contact’s own comments. - `"subscribed"` - `"unsubscribed"` - `postComments?: "subscribed" | "unsubscribed"` Stored status for new comments on posts the contact follows. - `"subscribed"` - `"unsubscribed"` - `postUpdates?: "subscribed" | "unsubscribed"` Stored status for post status changes and updates on posts the contact follows. - `"subscribed"` - `"unsubscribed"` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` Header param: API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `PreferencesOutput` - `contactId: string` Featurebase contact ID - `object: "contact_email_preferences"` Object type identifier - `"contact_email_preferences"` - `preferences: Preferences` Email preference state for this contact, including both stored status and final effective status. - `all: PreferenceState` Global email preference state for all email notifications. - `effectiveStatus: "subscribed" | "unsubscribed"` Final effective status after applying global preference overrides - `"subscribed"` - `"unsubscribed"` - `status: "subscribed" | "unsubscribed"` Stored preference status for this category - `"subscribed"` - `"unsubscribed"` - `changelog: PreferenceState` Global email preference state for all email notifications. - `commentReplies: PreferenceState` Global email preference state for all email notifications. - `postComments: PreferenceState` Global email preference state for all email notifications. - `postUpdates: PreferenceState` Global email preference state for all email notifications. - `email?: string | null` Contact email address, if available - `userId?: string | null` External user ID from your system, if available ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const preferencesOutput = await client.users.contacts.byUserID.emailPreferences.update( 'usr_12345', { preferences: {} }, ); console.log(preferencesOutput.contactId); ``` #### Response ```json { "contactId": "676f0f6765bdaa7d7d760f88", "object": "contact_email_preferences", "preferences": { "all": { "effectiveStatus": "unsubscribed", "status": "unsubscribed" }, "changelog": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "commentReplies": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postComments": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postUpdates": { "effectiveStatus": "unsubscribed", "status": "subscribed" } }, "email": "john@example.com", "userId": "usr_12345" } ``` # Email Preferences ## Get contact email preferences by ID `client.users.contacts.emailPreferences.retrieve(stringid, EmailPreferenceRetrieveParamsparams?, RequestOptionsoptions?): PreferencesOutput` **get** `/v2/contacts/{id}/email-preferences` Retrieves the email preference state for a customer contact by their Featurebase ID. **Important:** This endpoint only supports customer contacts. Leads do not have a customer email preference surface in the public API. ### Path Parameters - `id` - The Featurebase contact ID (24-character ObjectId) ### Response Format Returns a contact email preferences object with: - `object` - Always "contact_email_preferences" - `contactId` - Featurebase contact ID - `userId` - External user ID, if available - `email` - Contact email address, if available - `preferences` - Current email preference state ### Preference Semantics Each preference includes: - `status` - The stored preference state for that category - `effectiveStatus` - The final state after applying the global `all` preference override ### Example Response ```json { "object": "contact_email_preferences", "contactId": "676f0f6765bdaa7d7d760f88", "userId": "usr_12345", "email": "john@example.com", "preferences": { "all": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" }, "postUpdates": { "status": "subscribed", "effectiveStatus": "unsubscribed" }, "postComments": { "status": "subscribed", "effectiveStatus": "unsubscribed" }, "commentReplies": { "status": "subscribed", "effectiveStatus": "unsubscribed" }, "changelog": { "status": "subscribed", "effectiveStatus": "unsubscribed" } } } ``` ### Parameters - `id: string` Featurebase contact ID - `params: EmailPreferenceRetrieveParams` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `PreferencesOutput` - `contactId: string` Featurebase contact ID - `object: "contact_email_preferences"` Object type identifier - `"contact_email_preferences"` - `preferences: Preferences` Email preference state for this contact, including both stored status and final effective status. - `all: PreferenceState` Global email preference state for all email notifications. - `effectiveStatus: "subscribed" | "unsubscribed"` Final effective status after applying global preference overrides - `"subscribed"` - `"unsubscribed"` - `status: "subscribed" | "unsubscribed"` Stored preference status for this category - `"subscribed"` - `"unsubscribed"` - `changelog: PreferenceState` Global email preference state for all email notifications. - `commentReplies: PreferenceState` Global email preference state for all email notifications. - `postComments: PreferenceState` Global email preference state for all email notifications. - `postUpdates: PreferenceState` Global email preference state for all email notifications. - `email?: string | null` Contact email address, if available - `userId?: string | null` External user ID from your system, if available ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const preferencesOutput = await client.users.contacts.emailPreferences.retrieve( '507f1f77bcf86cd799439011', ); console.log(preferencesOutput.contactId); ``` #### Response ```json { "contactId": "676f0f6765bdaa7d7d760f88", "object": "contact_email_preferences", "preferences": { "all": { "effectiveStatus": "unsubscribed", "status": "unsubscribed" }, "changelog": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "commentReplies": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postComments": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postUpdates": { "effectiveStatus": "unsubscribed", "status": "subscribed" } }, "email": "john@example.com", "userId": "usr_12345" } ``` ## Update contact email preferences by ID `client.users.contacts.emailPreferences.update(stringid, EmailPreferenceUpdateParamsparams, RequestOptionsoptions?): PreferencesOutput` **patch** `/v2/contacts/{id}/email-preferences` Updates one or more email preferences for a customer contact by their Featurebase ID. **Important:** This endpoint only supports customer contacts. Leads do not have a customer email preference surface in the public API. ### Path Parameters - `id` - The Featurebase contact ID (24-character ObjectId) ### Request Body - `preferences` - A partial map of preference keys to their desired stored status. Only the preferences included in the request are updated; any preferences omitted are left unchanged. At least one preference must be provided. ### Supported Preference Keys - `all` - Master delivery gate. When `unsubscribed`, the contact will not receive any emails regardless of the per-category values. Per-category values are still persisted, so flipping `all` back to `subscribed` restores the contact's previous granular preferences. - `postUpdates` - Status changes and updates on posts the contact interacts with. - `postComments` - New comments on posts the contact follows. - `commentReplies` - Replies to the contact's own comments. - `changelog` - New changelog releases. ### Per-key Values - `subscribed` - The contact will receive this email category (subject to the `all` gate). - `unsubscribed` - The contact will not receive this email category. ### Combining `all` with per-category keys You can send `all` together with any per-category keys in the same request. The full map is applied atomically as the contact's new stored state — there is no implicit reset of the other keys. This makes the endpoint safe for preference-center UIs that POST the entire form state on submit. The computed per-category result (after applying the `all` gate) is surfaced as `effectiveStatus` in the response, while `status` reflects the value actually stored for that key. ### Example Request (partial update) ```json { "preferences": { "postUpdates": "unsubscribed", "changelog": "subscribed" } } ``` ### Example Request (full preference-center submit) ```json { "preferences": { "all": "subscribed", "postUpdates": "subscribed", "postComments": "unsubscribed", "commentReplies": "unsubscribed", "changelog": "unsubscribed" } } ``` ### Example Response ```json { "object": "contact_email_preferences", "contactId": "676f0f6765bdaa7d7d760f88", "userId": "usr_12345", "email": "john@example.com", "preferences": { "all": { "status": "subscribed", "effectiveStatus": "subscribed" }, "postUpdates": { "status": "subscribed", "effectiveStatus": "subscribed" }, "postComments": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" }, "commentReplies": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" }, "changelog": { "status": "unsubscribed", "effectiveStatus": "unsubscribed" } } } ``` ### Parameters - `id: string` Featurebase contact ID - `params: EmailPreferenceUpdateParams` - `preferences: Preferences` Body param - `all?: "subscribed" | "unsubscribed"` Master delivery gate. When `unsubscribed`, the contact receives no emails regardless of the per-category values. Per-category values are preserved. - `"subscribed"` - `"unsubscribed"` - `changelog?: "subscribed" | "unsubscribed"` Stored status for new changelog release notifications. - `"subscribed"` - `"unsubscribed"` - `commentReplies?: "subscribed" | "unsubscribed"` Stored status for replies to the contact’s own comments. - `"subscribed"` - `"unsubscribed"` - `postComments?: "subscribed" | "unsubscribed"` Stored status for new comments on posts the contact follows. - `"subscribed"` - `"unsubscribed"` - `postUpdates?: "subscribed" | "unsubscribed"` Stored status for post status changes and updates on posts the contact follows. - `"subscribed"` - `"unsubscribed"` - `featurebaseVersion?: "2026-01-01.nova" | "2025-12-12.clover"` Header param: API version for this request. Defaults to your organization's configured API version if not specified. - `"2026-01-01.nova"` - `"2025-12-12.clover"` ### Returns - `PreferencesOutput` - `contactId: string` Featurebase contact ID - `object: "contact_email_preferences"` Object type identifier - `"contact_email_preferences"` - `preferences: Preferences` Email preference state for this contact, including both stored status and final effective status. - `all: PreferenceState` Global email preference state for all email notifications. - `effectiveStatus: "subscribed" | "unsubscribed"` Final effective status after applying global preference overrides - `"subscribed"` - `"unsubscribed"` - `status: "subscribed" | "unsubscribed"` Stored preference status for this category - `"subscribed"` - `"unsubscribed"` - `changelog: PreferenceState` Global email preference state for all email notifications. - `commentReplies: PreferenceState` Global email preference state for all email notifications. - `postComments: PreferenceState` Global email preference state for all email notifications. - `postUpdates: PreferenceState` Global email preference state for all email notifications. - `email?: string | null` Contact email address, if available - `userId?: string | null` External user ID from your system, if available ### Example ```typescript import Featurebase from 'featurebase-node'; const client = new Featurebase({ apiKey: process.env['FEATUREBASE_API_KEY'], // This is the default and can be omitted }); const preferencesOutput = await client.users.contacts.emailPreferences.update( '507f1f77bcf86cd799439011', { preferences: {} }, ); console.log(preferencesOutput.contactId); ``` #### Response ```json { "contactId": "676f0f6765bdaa7d7d760f88", "object": "contact_email_preferences", "preferences": { "all": { "effectiveStatus": "unsubscribed", "status": "unsubscribed" }, "changelog": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "commentReplies": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postComments": { "effectiveStatus": "unsubscribed", "status": "subscribed" }, "postUpdates": { "effectiveStatus": "unsubscribed", "status": "subscribed" } }, "email": "john@example.com", "userId": "usr_12345" } ``` ## Domain Types ### Preference State - `PreferenceState` Global email preference state for all email notifications. - `effectiveStatus: "subscribed" | "unsubscribed"` Final effective status after applying global preference overrides - `"subscribed"` - `"unsubscribed"` - `status: "subscribed" | "unsubscribed"` Stored preference status for this category - `"subscribed"` - `"unsubscribed"` ### Preferences Output - `PreferencesOutput` - `contactId: string` Featurebase contact ID - `object: "contact_email_preferences"` Object type identifier - `"contact_email_preferences"` - `preferences: Preferences` Email preference state for this contact, including both stored status and final effective status. - `all: PreferenceState` Global email preference state for all email notifications. - `effectiveStatus: "subscribed" | "unsubscribed"` Final effective status after applying global preference overrides - `"subscribed"` - `"unsubscribed"` - `status: "subscribed" | "unsubscribed"` Stored preference status for this category - `"subscribed"` - `"unsubscribed"` - `changelog: PreferenceState` Global email preference state for all email notifications. - `commentReplies: PreferenceState` Global email preference state for all email notifications. - `postComments: PreferenceState` Global email preference state for all email notifications. - `postUpdates: PreferenceState` Global email preference state for all email notifications. - `email?: string | null` Contact email address, if available - `userId?: string | null` External user ID from your system, if available ### Update Preference Body - `UpdatePreferenceBody` - `preferences: Preferences` - `all?: "subscribed" | "unsubscribed"` Master delivery gate. When `unsubscribed`, the contact receives no emails regardless of the per-category values. Per-category values are preserved. - `"subscribed"` - `"unsubscribed"` - `changelog?: "subscribed" | "unsubscribed"` Stored status for new changelog release notifications. - `"subscribed"` - `"unsubscribed"` - `commentReplies?: "subscribed" | "unsubscribed"` Stored status for replies to the contact’s own comments. - `"subscribed"` - `"unsubscribed"` - `postComments?: "subscribed" | "unsubscribed"` Stored status for new comments on posts the contact follows. - `"subscribed"` - `"unsubscribed"` - `postUpdates?: "subscribed" | "unsubscribed"` Stored status for post status changes and updates on posts the contact follows. - `"subscribed"` - `"unsubscribed"`