openapi: 3.1.0 info: description: 'Fixture''s public v1 CRM API for Accounts, Contacts, Deals, Leads, Activities, Pipelines, Notes, and Tasks. Authenticate with `Authorization: Bearer ...` using either a Fixture API key or a Fixture OAuth access token.' title: Fixture Accounts Contacts API version: v1 servers: - url: https://beta-api.fixture.app security: - bearerAuth: [] tags: - description: Create, read, update, and delete person records. name: Contacts paths: /api/v1/contacts: get: deprecated: false description: Return a paginated list of Contacts. Supports filtering by `email`, `name`, `account_id`, and created/updated timestamps. Sort supports `created_at` or `-created_at`; pagination uses `limit` and `cursor`. Contacts that have been merged into another Contact are excluded. Use `fields` to choose which public Contact fields appear in each record. operationId: listContacts parameters: - allowEmptyValue: false allowReserved: false deprecated: false description: Maximum number of records to return. in: query name: limit required: false schema: default: 50 example: 50 type: integer - allowEmptyValue: false allowReserved: false deprecated: false description: Opaque cursor returned by the previous page. Omit for the first page. in: query name: cursor required: false schema: example: eyJ2IjoxLCJzb3J0IjoiLWNyZWF0ZWRfYXQiLCJ2YWx1ZSI6IjIwMjYtMDMtMjJUMTQ6MDA6MDFaIiwiaWQiOiI2NjAxZDYxZC0xMTI5LTQyN2MtODI1NS0wOGI1ZjEyZGRhYjUifQ type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Sort by a supported field. Prefix with `-` for descending order. in: query name: sort required: false schema: default: -created_at example: -created_at type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Filter by an exact email address. in: query name: email required: false schema: example: alex@acme.example type: string - allowEmptyValue: false allowReserved: false deprecated: false in: query name: linkedin_url required: false schema: type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Filter Contacts by a partial, case-insensitive person name match. in: query name: name required: false schema: example: Taylor type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Opaque Account ID with the `account_` prefix. in: query name: account_id required: false schema: example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Return only records created after this ISO 8601 timestamp. in: query name: created_after required: false schema: example: '2026-03-01T00:00:00Z' format: date-time type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Return only records created before this ISO 8601 timestamp. in: query name: created_before required: false schema: example: '2026-03-31T23:59:59Z' format: date-time type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Return only records updated after this ISO 8601 timestamp. in: query name: updated_after required: false schema: example: '2026-03-01T00:00:00Z' format: date-time type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Return only records updated before this ISO 8601 timestamp. in: query name: updated_before required: false schema: example: '2026-03-31T23:59:59Z' format: date-time type: string - allowEmptyValue: false allowReserved: false deprecated: false description: Choose which public fields appear in each list record. Omit or pass a blank value for the default list fields, use `*` alone for every public detail field, or pass comma-separated names. in: query name: fields required: false schema: example: id,name,created_at type: string responses: '200': content: application/json: example: data: - account_id: account_7B5jXRFuLpTQ3nM4PkGvW2 created_at: '2026-03-18T11:15:00Z' email: alex@acme.example emails: - alex@acme.example - sales@acme.example id: contact_6M4jXRFuLpTQ3nM4PkGvW8 last_activity_at: '2026-03-24T17:30:00Z' name: Alex Morgan phone: +1-415-555-0130 title: VP Sales updated_at: '2026-03-22T14:00:01Z' pagination: has_more: false limit: 50 next_cursor: null schema: $ref: '#/components/schemas/V1ContactListPayload' description: Paginated Contact list. '400': content: application/json: example: error: code: invalid_parameter message: Invalid cursor schema: $ref: '#/components/schemas/V1ErrorResponse' description: Invalid filter or pagination parameter. '401': content: application/json: example: error: code: unauthorized message: Invalid or missing API key schema: $ref: '#/components/schemas/V1ErrorResponse' description: Missing or invalid API key. '403': content: application/json: example: error: code: forbidden message: 'Missing required scope: contacts:read' schema: $ref: '#/components/schemas/V1ErrorResponse' description: API key is missing the required scope. security: - bearerAuth: [] summary: List Contacts tags: - Contacts post: deprecated: false description: Create a new person Contact, optionally linked to an Account via `account_id`. Returns the full Contact detail payload including the generated `con_` ID. operationId: createContact requestBody: content: application/json: example: account_id: account_7B5jXRFuLpTQ3nM4PkGvW2 email: alex@acme.example emails: - alex@acme.example - sales@acme.example name: Alex Morgan title: VP Sales schema: $ref: '#/components/schemas/CreateContactRequest' required: true responses: '201': content: application/json: example: data: account_id: account_7B5jXRFuLpTQ3nM4PkGvW2 created_at: '2026-03-18T11:15:00Z' email: alex@acme.example emails: - alex@acme.example - sales@acme.example id: contact_6M4jXRFuLpTQ3nM4PkGvW8 last_activity_at: '2026-03-24T17:30:00Z' linkedin_url: https://www.linkedin.com/in/alex-morgan name: Alex Morgan notes: Prefers email follow-up. phone: +1-415-555-0130 title: VP Sales twitter_handle: '@alexmorgan' updated_at: '2026-03-22T14:00:01Z' schema: $ref: '#/components/schemas/V1ContactDetailResponsePayload' description: Contact created. '400': content: application/json: example: error: code: validation_error message: Provide a name, email, or LinkedIn URL schema: $ref: '#/components/schemas/V1ErrorResponse' description: Request validation failed. '401': content: application/json: example: error: code: unauthorized message: Invalid or missing API key schema: $ref: '#/components/schemas/V1ErrorResponse' description: Missing or invalid API key. '403': content: application/json: example: error: code: forbidden message: 'Missing required scope: contacts:write' schema: $ref: '#/components/schemas/V1ErrorResponse' description: API key is missing the required scope. '404': content: application/json: example: error: code: not_found message: Account not found schema: $ref: '#/components/schemas/V1ErrorResponse' description: Referenced Account not found. security: - bearerAuth: [] summary: Create a Contact tags: - Contacts /api/v1/contacts/{contact_id}: delete: deprecated: false description: Delete a Contact by ID. Returns `410 gone` if the Contact was merged into another — merged Contacts cannot be deleted directly. operationId: deleteContact parameters: - deprecated: false description: Opaque Contact ID with the `contact_` prefix. in: path name: contact_id required: true schema: example: contact_6M4jXRFuLpTQ3nM4PkGvW8 type: string responses: '200': content: application/json: example: deleted: true id: contact_6M4jXRFuLpTQ3nM4PkGvW8 schema: $ref: '#/components/schemas/V1ContactDeletePayload' description: Contact deleted. '400': content: application/json: example: error: code: invalid_parameter message: Invalid Contact ID schema: $ref: '#/components/schemas/V1ErrorResponse' description: Invalid Contact ID. '401': content: application/json: example: error: code: unauthorized message: Invalid or missing API key schema: $ref: '#/components/schemas/V1ErrorResponse' description: Missing or invalid API key. '403': content: application/json: example: error: code: forbidden message: 'Missing required scope: contacts:write' schema: $ref: '#/components/schemas/V1ErrorResponse' description: API key is missing the required scope. '404': content: application/json: example: error: code: not_found message: Contact not found schema: $ref: '#/components/schemas/V1ErrorResponse' description: Contact not found. '410': content: application/json: example: error: code: gone message: This Contact was merged. merged_into: contact_6M4jXRFuLpTQ3nM4PkGvW9 schema: $ref: '#/components/schemas/V1MergedContactGoneResponse' description: The Contact was merged and can no longer be deleted. security: - bearerAuth: [] summary: Delete a Contact tags: - Contacts get: deprecated: false description: Return a single Contact by its `con_` ID. If the requested Contact was merged into another, responds with `301` and a `Location` header pointing to the survivor Contact's canonical URL. operationId: getContact parameters: - deprecated: false description: Opaque Contact ID with the `contact_` prefix. in: path name: contact_id required: true schema: example: contact_6M4jXRFuLpTQ3nM4PkGvW8 type: string responses: '200': content: application/json: example: data: account_id: account_7B5jXRFuLpTQ3nM4PkGvW2 created_at: '2026-03-18T11:15:00Z' email: alex@acme.example emails: - alex@acme.example - sales@acme.example id: contact_6M4jXRFuLpTQ3nM4PkGvW8 last_activity_at: '2026-03-24T17:30:00Z' linkedin_url: https://www.linkedin.com/in/alex-morgan name: Alex Morgan notes: Prefers email follow-up. phone: +1-415-555-0130 title: VP Sales twitter_handle: '@alexmorgan' updated_at: '2026-03-22T14:00:01Z' schema: $ref: '#/components/schemas/V1ContactDetailResponsePayload' description: Contact detail. '301': content: application/json: example: merged_into: contact_6M4jXRFuLpTQ3nM4PkGvW9 schema: $ref: '#/components/schemas/V1MergedContactRedirectResponse' description: The Contact was merged. Follow the survivor Contact URL in the `Location` header. headers: Location: description: Canonical URL for the survivor Contact. schema: example: /api/v1/contacts/contact_6M4jXRFuLpTQ3nM4PkGvW9 type: string '400': content: application/json: example: error: code: invalid_parameter message: Invalid Contact ID schema: $ref: '#/components/schemas/V1ErrorResponse' description: Invalid Contact ID. '401': content: application/json: example: error: code: unauthorized message: Invalid or missing API key schema: $ref: '#/components/schemas/V1ErrorResponse' description: Missing or invalid API key. '403': content: application/json: example: error: code: forbidden message: 'Missing required scope: contacts:read' schema: $ref: '#/components/schemas/V1ErrorResponse' description: API key is missing the required scope. '404': content: application/json: example: error: code: not_found message: Contact not found schema: $ref: '#/components/schemas/V1ErrorResponse' description: Contact not found. security: - bearerAuth: [] summary: Get a Contact tags: - Contacts patch: deprecated: false description: Partially update a Contact by ID. Omitted fields are left untouched; `null` clears nullable fields. Returns `410 gone` if the Contact was merged into another and can no longer be mutated directly. operationId: updateContact parameters: - deprecated: false description: Opaque Contact ID with the `contact_` prefix. in: path name: contact_id required: true schema: example: contact_6M4jXRFuLpTQ3nM4PkGvW8 type: string requestBody: content: application/json: example: notes: Prefers email follow-up. title: VP Revenue schema: $ref: '#/components/schemas/UpdateContactRequest' required: true responses: '200': content: application/json: example: data: account_id: account_7B5jXRFuLpTQ3nM4PkGvW2 created_at: '2026-03-18T11:15:00Z' email: alex@acme.example emails: - alex@acme.example - sales@acme.example id: contact_6M4jXRFuLpTQ3nM4PkGvW8 last_activity_at: '2026-03-24T17:30:00Z' linkedin_url: https://www.linkedin.com/in/alex-morgan name: Alex Morgan notes: Prefers email follow-up. phone: +1-415-555-0130 title: VP Sales twitter_handle: '@alexmorgan' updated_at: '2026-03-22T14:00:01Z' schema: $ref: '#/components/schemas/V1ContactDetailResponsePayload' description: Updated Contact. '400': content: application/json: example: error: code: validation_error message: emails must be a list of email addresses schema: $ref: '#/components/schemas/V1ErrorResponse' description: Invalid ID or request body. '401': content: application/json: example: error: code: unauthorized message: Invalid or missing API key schema: $ref: '#/components/schemas/V1ErrorResponse' description: Missing or invalid API key. '403': content: application/json: example: error: code: forbidden message: 'Missing required scope: contacts:write' schema: $ref: '#/components/schemas/V1ErrorResponse' description: API key is missing the required scope. '404': content: application/json: example: error: code: not_found message: Contact not found schema: $ref: '#/components/schemas/V1ErrorResponse' description: Contact not found. '410': content: application/json: example: error: code: gone message: This Contact was merged. merged_into: contact_6M4jXRFuLpTQ3nM4PkGvW9 schema: $ref: '#/components/schemas/V1MergedContactGoneResponse' description: The Contact was merged and can no longer be updated. security: - bearerAuth: [] summary: Update a Contact tags: - Contacts components: schemas: V1ContactDetailPayload: properties: account_id: description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 oneOf: - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: string - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: 'null' created_at: example: '2026-03-22T14:00:01Z' format: date-time type: string email: description: Primary email address. example: alex@acme.example oneOf: - description: Primary email address. example: alex@acme.example type: string - description: Primary email address. example: alex@acme.example type: 'null' emails: description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example items: description: Primary email address. example: alex@acme.example type: string type: array id: description: Opaque `contact_` identifier. example: contact_6M4jXRFuLpTQ3nM4PkGvW8 type: string last_activity_at: example: '2026-03-24T17:30:00Z' oneOf: - example: '2026-03-24T17:30:00Z' format: date-time type: string - example: '2026-03-24T17:30:00Z' type: 'null' linkedin_url: example: https://www.linkedin.com/company/acme oneOf: - example: https://www.linkedin.com/company/acme type: string - example: https://www.linkedin.com/company/acme type: 'null' name: oneOf: - type: string - type: 'null' notes: oneOf: - type: string - type: 'null' phone: example: +1-415-555-0100 oneOf: - example: +1-415-555-0100 type: string - example: +1-415-555-0100 type: 'null' title: oneOf: - type: string - type: 'null' twitter_handle: oneOf: - type: string - type: 'null' updated_at: example: '2026-03-22T14:00:01Z' format: date-time type: string required: - account_id - created_at - email - emails - id - last_activity_at - linkedin_url - name - notes - phone - title - twitter_handle - updated_at title: V1ContactDetailPayload type: object V1PaginationPayload: description: Cursor pagination block for public list responses. properties: has_more: description: Whether another page is available. example: false type: boolean limit: description: Requested page size. example: 50 type: integer next_cursor: description: Opaque cursor to pass as `cursor` for the next page, or null when this is the last page. example: null type: - string - 'null' required: - limit - next_cursor - has_more type: object V1ContactDeletePayload: properties: deleted: const: true type: boolean id: description: Opaque `contact_` identifier. example: contact_6M4jXRFuLpTQ3nM4PkGvW8 type: string required: - deleted - id title: V1ContactDeletePayload type: object V1ErrorResponse: description: Standard error envelope for all public v1 API errors. properties: error: properties: code: description: Stable machine-readable error code. example: not_found type: string message: description: Human-readable error message. example: Account not found type: string required: - code - message type: object required: - error type: object CreateContactRequest: description: Request body for creating a Contact. properties: account_id: description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 oneOf: - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: string - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: 'null' email: description: Primary email address. example: alex@acme.example oneOf: - description: Primary email address. example: alex@acme.example type: string - description: Primary email address. example: alex@acme.example type: 'null' emails: description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example oneOf: - description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example items: description: Primary email address. example: alex@acme.example type: string type: array - description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example type: 'null' linkedin_url: example: https://www.linkedin.com/company/acme oneOf: - example: https://www.linkedin.com/company/acme type: string - example: https://www.linkedin.com/company/acme type: 'null' name: oneOf: - type: string - type: 'null' notes: oneOf: - type: string - type: 'null' phone: example: +1-415-555-0100 oneOf: - example: +1-415-555-0100 type: string - example: +1-415-555-0100 type: 'null' title: oneOf: - type: string - type: 'null' twitter_handle: oneOf: - type: string - type: 'null' required: [] title: CreateContactRequest type: object UpdateContactRequest: description: Request body for partially updating a Contact. properties: account_id: description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 oneOf: - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: string - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: 'null' email: description: Primary email address. example: alex@acme.example oneOf: - description: Primary email address. example: alex@acme.example type: string - description: Primary email address. example: alex@acme.example type: 'null' emails: description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example oneOf: - description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example items: description: Primary email address. example: alex@acme.example type: string type: array - description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example type: 'null' linkedin_url: example: https://www.linkedin.com/company/acme oneOf: - example: https://www.linkedin.com/company/acme type: string - example: https://www.linkedin.com/company/acme type: 'null' name: oneOf: - type: string - type: 'null' notes: oneOf: - type: string - type: 'null' phone: example: +1-415-555-0100 oneOf: - example: +1-415-555-0100 type: string - example: +1-415-555-0100 type: 'null' title: oneOf: - type: string - type: 'null' twitter_handle: oneOf: - type: string - type: 'null' required: [] title: UpdateContactRequest type: object V1MergedContactGoneResponse: description: Error payload for mutations that target a merged Contact. properties: error: properties: code: description: Stable machine-readable error code. example: gone type: string message: description: Human-readable error message. example: This Contact was merged. type: string required: - code - message type: object merged_into: description: Canonical survivor Contact ID. example: contact_6M4jXRFuLpTQ3nM4PkGvW9 type: string required: - merged_into - error type: object V1ContactListPayload: description: Paginated list response for Contacts. properties: data: items: $ref: '#/components/schemas/V1ContactSelectedFieldsPayload' type: array pagination: $ref: '#/components/schemas/V1PaginationPayload' required: - data - pagination title: V1ContactListPayload type: object V1ContactDetailResponsePayload: description: Single-Contact response envelope. properties: data: $ref: '#/components/schemas/V1ContactDetailPayload' required: - data title: V1ContactDetailResponsePayload type: object V1MergedContactRedirectResponse: description: Redirect payload for requests that hit a merged Contact. properties: merged_into: description: Canonical survivor Contact ID. example: contact_6M4jXRFuLpTQ3nM4PkGvW9 type: string required: - merged_into type: object V1ContactSelectedFieldsPayload: properties: account_id: description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 oneOf: - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: string - description: Opaque `account_` identifier. example: account_7B5jXRFuLpTQ3nM4PkGvW2 type: 'null' created_at: example: '2026-03-22T14:00:01Z' format: date-time type: string email: description: Primary email address. example: alex@acme.example oneOf: - description: Primary email address. example: alex@acme.example type: string - description: Primary email address. example: alex@acme.example type: 'null' emails: description: All known email addresses for the Contact. example: - alex@acme.example - sales@acme.example items: description: Primary email address. example: alex@acme.example type: string type: array id: description: Opaque `contact_` identifier. example: contact_6M4jXRFuLpTQ3nM4PkGvW8 type: string last_activity_at: example: '2026-03-24T17:30:00Z' oneOf: - example: '2026-03-24T17:30:00Z' format: date-time type: string - example: '2026-03-24T17:30:00Z' type: 'null' linkedin_url: example: https://www.linkedin.com/company/acme oneOf: - example: https://www.linkedin.com/company/acme type: string - example: https://www.linkedin.com/company/acme type: 'null' name: oneOf: - type: string - type: 'null' notes: oneOf: - type: string - type: 'null' phone: example: +1-415-555-0100 oneOf: - example: +1-415-555-0100 type: string - example: +1-415-555-0100 type: 'null' title: oneOf: - type: string - type: 'null' twitter_handle: oneOf: - type: string - type: 'null' updated_at: example: '2026-03-22T14:00:01Z' format: date-time type: string required: [] title: V1ContactSelectedFieldsPayload type: object securitySchemes: bearerAuth: bearerFormat: API key or OAuth access token description: Send either a Fixture API key or a Fixture OAuth access token in the Authorization header as a bearer token. scheme: bearer type: http