# Create or update a contact 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. Endpoint: POST /v2/contacts Version: 2026-01-01.nova Security: bearerAuth ## Header parameters: - `Featurebase-Version` (string) API version for this request. Defaults to your organization's configured API version if not specified. Example: "2026-01-01.nova" ## Request fields (application/json): - `email` (string) Contact email address. Used for identification if userId is not provided. Example: "john@example.com" - `name` (string) Contact display name Example: "John Doe" - `userId` (string) External user ID from your system. Takes precedence over email for identification. Example: "usr_12345" - `userHash` (string) HMAC-SHA256 hash of userId or email for identity verification Example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6" - `profilePicture` (string,null) Profile picture URL Example: "https://example.com/avatar.png" - `companies` (array) Companies the contact belongs to - `companies.id` (string, required) External company ID from your system Example: "company_123" - `companies.name` (string, required) Company name Example: "Acme Inc" - `companies.createdAt` (string,null) When the company was created (ISO 8601) Example: "2024-01-15T10:30:00Z" - `companies.monthlySpend` (number) Monthly spend/revenue from this company Example: 500 - `companies.customFields` (object) Custom field values on the company. Values can be string, number, boolean, null, or array of primitives. - `companies.customFields.plan` (string) Example: "enterprise" - `companies.customFields.industry` (string) Example: "Technology" - `companies.customFields.priority` (string) Example: "high" - `companies.companyHash` (string) HMAC-SHA256 hash of company ID for identity verification Example: "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6" - `companies.companySize` (number,null) Number of employees in the company Example: 50 - `companies.industry` (string) Industry the company operates in Example: "Technology" - `companies.website` (string) Company website URL Example: "https://acme.com" - `companies.plan` (string) Current plan/subscription name Example: "enterprise" - `createdAt` (string,null) When the contact was created in your system (ISO 8601) Example: "2024-01-15T10:30:00Z" - `customFields` (object) Custom field values on the contact. Values can be string, number, boolean, null, or array of primitives. - `customFields.signupSource` (string) Example: "website" - `customFields.accountType` (string) Example: "premium" - `subscribedToChangelog` (boolean) Whether the contact is subscribed to changelog updates Example: true - `locale` (string) Contact locale/language preference Example: "en" - `phone` (string,null) Contact phone number Example: "+1234567890" - `roles` (array) Array of role IDs to assign to the contact Example: ["role_vip","role_beta"] ## Response 201 fields (application/json): - `object` (string, required) Object type identifier Enum: "contact" - `id` (string, required) Unique identifier Example: "676f0f6765bdaa7d7d760f88" - `userId` (string) External user ID from SSO Example: "676f0f673dbb299c8a4f3057" - `organizationId` (string) Organization ID the contact belongs to Example: "5febde12dc56d60012d47db6" - `companies` (array) Companies the contact belongs to Example: [] - `companies.id` (string, required) Featurebase internal ID Example: "507f1f77bcf86cd799439011" - `companies.companyId` (string, required) External company ID from your system Example: "comp_12345" - `companies.name` (string, required) Company name Example: "Acme Inc" - `companies.monthlySpend` (number,null, required) Monthly spend Example: 5000 - `companies.industry` (string,null, required) Industry Example: "Technology" - `companies.website` (string,null, required) Company website URL Example: "https://acme.com" - `companies.plan` (string,null, required) Plan or tier name Example: "enterprise" - `companies.linkedUsers` (number,null, required) Number of users linked to this company Example: 15 - `companies.companySize` (number,null, required) Company employee headcount Example: 250 - `companies.lastActivity` (string,null, required) ISO date of last activity Example: "2025-01-15T00:00:00.000Z" - `companies.customFields` (object) Custom field values Example: {"location":"Europe","priority":"high"} - `companies.createdAt` (string,null, required) ISO date when company was created Example: "2025-01-01T12:00:00.000Z" - `companies.updatedAt` (string,null, required) ISO date when company was last updated Example: "2025-01-10T15:30:00.000Z" - `email` (string,null) Contact email Example: "john@example.com" - `name` (string, required) Contact display name Example: "John Steezy" - `profilePicture` (string,null) Profile picture URL Example: "https://fb-usercontent.fra1.cdn.digitaloceanspaces.com/anon_23.png" - `commentsCreated` (number) Number of comments created - `postsCreated` (number) Number of posts created - `lastActivity` (string) Last activity ISO timestamp Example: "2025-01-03T21:42:30.181Z" - `subscribedToChangelog` (boolean) Whether subscribed to changelog Example: true - `manuallyOptedOutFromChangelog` (boolean) Whether manually opted out from changelog - `roles` (array) Contact roles Example: [] - `locale` (string) Contact locale Example: "en" - `verified` (boolean) Whether email is verified Example: true - `type` (string, required) Type of contact Enum: "customer", "lead" - `description` (string) Contact description/bio - `customFields` (object) Custom field values on the contact ## Response 400 fields (application/json): - `error` (object, required) - `error.type` (string, required) The type of error returned Enum: "invalid_request_error" - `error.code` (string, required) Machine-readable error code Enum: "missing_parameter", "invalid_request" - `error.message` (string, required) Human-readable error message Example: "An error occurred" - `error.param` (string) The parameter that caused the error (if applicable) Example: "id" - `error.status` (number, required) HTTP status code Enum: 400