> ## Documentation Index
> Fetch the complete documentation index at: https://docs.groovin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Data models

> Every object the API answers with, field by field. New fields can appear at any time: ignore the ones you do not use.

Each endpoint page shows its full answer. This page lists the same objects in one place, which is handy to paste into your AI assistant.

Some names differ from one route to another, for historical reasons:

* A LinkedIn URL is called `profile_url`, `linkedin_profile_url` or `linkedin_url`.
* `linkedin/chat-messages` takes a `conversation_id` and answers with a `chat_id`: both are the same thing.
* A person's name is called `name` or `full_name`.
* `is_crm_contact_creation_blocked` is only present when `true`, except on `crm/contacts/synced` and in webhooks.

### Error

What every failed request answers, with an HTTP status. The text can change: decide what to do from the status, and show the text to a person.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `error` | string | Yes | What went wrong, and sometimes what to do next. |

### ConversationAttendee

A person from your LinkedIn conversations.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `linkedin_profile_id` | string | Yes | LinkedIn profile id, the `ACoAA…` identifier of a person. |
| `slug` | string, or null | Yes | The public part of the person's LinkedIn URL, as in `linkedin.com/in/<slug>`. |
| `name` | string | Yes | The person's name. |
| `headline` | string, or null | Yes | Their LinkedIn headline. |
| `occupation` | string, or null | Yes | Their occupation, as LinkedIn reports it. |
| `location` | string, or null | Yes | Their location, as free text. |
| `network_distance` | string, or null | Yes | How close they are in your network, such as `"DISTANCE_1"`. |
| `pending_invitation` | boolean, or null | Yes | Whether an invitation is pending with this person. |
| `emails` | list of string | Yes | Email addresses LinkedIn shows for this person. |
| `profile_url` | string, or null | Yes | Their LinkedIn profile URL. |
| `picture_url` | string, or null | Yes | Their profile picture URL. |
| `already_paired_in_groovin` | boolean | Yes | `true` when Groovin already links this person to a CRM contact. A quick Groovin check, not a live CRM search. |
| `is_crm_contact_creation_blocked` | true | No | Only present, as `true`, when you blocked this person from CRM contact creation in Groovin. `crm/contacts` does not enforce the block, so check it yourself before creating. |
| `last_message_at` | string, or null | No | When the last message was sent in their chat, or `null` if there is no chat. Conversation fields like this one are left out when you send `include_conversation_metadata: false`. |
| `unread_count` | integer | No | Messages you have not read yet, across all the chats listed under this person. |
| `conversation_id` | string, or null | No | Their most recent chat. Pass it to `linkedin/chat-messages` to read it. |
| `conversation_archived` | boolean, or null | No | Whether that chat is archived. |
| `conversation_pinned` | boolean, or null | No | Whether that chat is pinned. |
| `conversation_subject` | string, or null | No | That chat's subject. Usually `null` for a plain conversation. |
| `conversation_name` | string, or null | No | That chat's name, set for named or group threads. |
| `conversation_type` | string, or null | No | The kind of chat: `"MESSAGE"`, `"INMAIL"`, or another LinkedIn type in capitals. |

### ListConversationAttendeesResult

The people from your LinkedIn conversations.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `total` | integer | Yes | People matching your filters, before `limit`. |
| `returned` | integer | Yes | People in this answer. |
| `truncated` | boolean | Yes | `true` when `limit` left matching people out. |
| `attendees` | list of ConversationAttendee | Yes | Most recent conversation first, unless you sent `include_conversation_metadata: false`: the order is then not defined. |

### ConversationMessageAttachment

A file attached to a LinkedIn message.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `id` | string | Yes | Attachment id. |
| `type` | string | Yes | `"img"`, `"video"`, `"audio"` or `"file"`. |
| `url` | string, or null | Yes | Where to get the file, when known. |
| `unavailable` | boolean | Yes | `true` when LinkedIn can no longer provide the file. |

### ConversationMessage

One message of a LinkedIn chat.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `id` | string | Yes | Message id. |
| `provider_id` | string, or null | Yes | LinkedIn's own id for this message. |
| `text` | string | Yes | The message text. |
| `timestamp` | string, or null | Yes | When it was sent (ISO 8601). |
| `sent_by_me` | boolean | Yes | `true` when you sent this message. |
| `sender_id` | string, or null | Yes | The sender's LinkedIn profile id. |
| `sender_attendee_id` | string, or null | Yes | The sender's id within this chat. Most integrations can ignore it. |
| `message_type` | string, or null | Yes | `"MESSAGE"` or `"INMAIL"`. |
| `subject` | string, or null | Yes | Subject line, set for InMails and some threads. |
| `seen` | boolean | Yes | A read receipt. `true` means LinkedIn reported it read. `false` proves nothing: see [Known issues](https://docs.groovin.ai/reference/known-issues.md). |
| `edited` | boolean | Yes | `true` when the message was edited. |
| `deleted` | boolean | Yes | `true` when the message was deleted. |
| `is_event` | boolean | Yes | `true` for a system event, such as someone joining, rather than a real message. |
| `attachments` | list of ConversationMessageAttachment | Yes | Files attached to this message. |
| `quoted` | object, or null | Yes | The message this one quotes, if any. |
| `reply_to_message_id` | string, or null | Yes | The message this one replies to. |
| `attendee_distance` | integer, or null | Yes | How close the sender is in your network, when LinkedIn says. |

### ListChatMessagesResult

One page of a chat's messages, newest first.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `chat_id` | string | Yes | The chat you read. It is the `conversation_id` you sent, under another name. |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `messages` | list of ConversationMessage | Yes | The messages. |
| `cursor` | string, or null | Yes | Send it back as `cursor` to get older messages. `null` when there are no more. |

### SetChatReadStatusResult

The chat's new state.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `conversation_id` | string | Yes | The chat that was changed. |
| `read` | boolean | Yes | The state you asked for. |
| `unread_count_before` | integer, or null | Yes | Unread messages known just before the change. A hint, not proof of the previous state. |
| `updated` | true | Yes | Always `true` on success. |

### FetchLinkedinProfileResult

One LinkedIn profile, read live.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `linkedin_profile_id` | string | Yes | LinkedIn profile id, the `ACoAA…` identifier of a person. |
| `full_name` | string | Yes | First and last name. It can be `""` when LinkedIn hides the name: `crm/contacts` then needs a name from you. |
| `slug` | string, or null | Yes | The public part of the person's LinkedIn URL, as in `linkedin.com/in/<slug>`. |
| `sales_nav_profile_id` | string, or null | Yes | The Sales Navigator profile id, when that is what you sent. |
| `linkedin_profile_url` | string, or null | Yes | The LinkedIn profile URL. |
| `is_crm_contact_creation_blocked` | true | No | Only present, as `true`, when you blocked this person from CRM contact creation in Groovin. `crm/contacts` does not enforce the block, so check it yourself before creating. |
| `profile` | LinkedinProfile | Yes | |

### SendLinkedinMessageResult

LinkedIn accepted the message.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `sent` | true | Yes | Always `true` on success. |
| `conversation_id` | string, or null | Yes | The conversation the message went to. |
| `message_id` | string, or null | Yes | The new message's id, when LinkedIn gives one. |
| `recipient_linkedin_profile_id` | string, or null | Yes | Who it was addressed to. `null` when you sent a `conversation_id`. |
| `recipient_resolution` | string | Yes | How Groovin found the recipient. |
| `used_live_profile_fetch` | boolean | Yes | `true` when finding the recipient cost one live LinkedIn profile view. |

### SendLinkedinInvitationResult

LinkedIn accepted the invitation.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `sent` | true | Yes | Always `true` on success. |
| `invitation_id` | string, or null | Yes | The invitation's id, when LinkedIn gives one. |
| `recipient_linkedin_profile_id` | string | Yes | Who it was addressed to. |
| `recipient_resolution` | string | Yes | How Groovin found the recipient. |
| `used_live_profile_fetch` | boolean | Yes | `true` when finding the recipient cost one live LinkedIn profile view. Automatic contact creation can cost one more. |
| `crm_contact_id` | string, or null | Yes | The CRM contact the invitation was recorded on, if any. |
| `crm_contact_auto_created` | boolean | Yes | `true` when this call created a brand-new CRM contact. `false` when it only linked an existing one. |

### RelationItem

One of your LinkedIn connections.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `linkedin_profile_id` | string | Yes | LinkedIn profile id, the `ACoAA…` identifier of a person. |
| `slug` | string, or null | Yes | The public part of the person's LinkedIn URL, as in `linkedin.com/in/<slug>`. |
| `name` | string | Yes | Their name. |
| `first_name` | string, or null | Yes | First name. |
| `last_name` | string, or null | Yes | Last name. |
| `headline` | string, or null | Yes | Their LinkedIn headline. |
| `profile_url` | string, or null | Yes | Their LinkedIn profile URL. |
| `picture_url` | string, or null | Yes | Their profile picture URL. |
| `member_urn` | string, or null | Yes | LinkedIn's internal reference for this person. Use `linkedin_profile_id` instead. |
| `connection_urn` | string, or null | Yes | LinkedIn's internal reference for this connection. |
| `created_at` | integer, or null | Yes | When you connected, in milliseconds since 1970. `connected_at` is the same date, easier to read. |
| `connected_at` | string, or null | Yes | When you connected (ISO 8601). |
| `already_paired_in_groovin` | boolean | Yes | `true` when Groovin already links this person to a CRM contact. A quick Groovin check, not a live CRM search. |
| `is_crm_contact_creation_blocked` | true | No | Only present, as `true`, when you blocked this person from CRM contact creation in Groovin. `crm/contacts` does not enforce the block, so check it yourself before creating. |

### ListRelationsResult

Your LinkedIn connections, newest first.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `total_matched` | integer | Yes | Matches among the pages actually read. When `truncated` is `true`, the real total can be higher. |
| `returned` | integer | Yes | Connections in this answer. |
| `truncated` | boolean | Yes | `true` when more matches may exist than were returned. |
| `linkedin_requests` | integer | Yes | Live LinkedIn requests this call made. |
| `relations` | list of RelationItem | Yes | The connections. |

### PendingInvitationItem

One pending LinkedIn invitation.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `invitation_id` | string | Yes | The invitation's id. |
| `direction` | string | Yes | `sent`: you invited them. `received`: they invited you. |
| `linkedin_profile_id` | string, or null | Yes | The other person's LinkedIn profile id. |
| `slug` | string, or null | Yes | The public part of the person's LinkedIn URL, as in `linkedin.com/in/<slug>`. |
| `name` | string, or null | Yes | The other person's name. |
| `headline` | string, or null | Yes | Their LinkedIn headline. |
| `message` | string, or null | Yes | The invitation note, if any. |
| `sent_at` | string, or null | Yes | When it was sent. Usually ISO 8601, but it can be a LinkedIn label such as `"Sent 2 weeks ago"`. |
| `already_paired_in_groovin` | boolean | Yes | `true` when Groovin already links this person to a CRM contact. A quick Groovin check, not a live CRM search. |
| `is_crm_contact_creation_blocked` | true | No | Only present, as `true`, when you blocked this person from CRM contact creation in Groovin. `crm/contacts` does not enforce the block, so check it yourself before creating. |

### ListPendingInvitationsResult

Your pending LinkedIn invitations, newest first.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `direction` | string | Yes | The direction you asked for. |
| `total_matched` | integer | Yes | Invitations passing your date filter, before `limit`. |
| `returned` | integer | Yes | Invitations in this answer. |
| `truncated` | boolean | Yes | `true` when results were cut. |
| `excluded_missing_date` | integer | Yes | Invitations a date filter dropped because LinkedIn gave no readable date. |
| `linkedin_requests` | integer | Yes | Live LinkedIn requests this call made. |
| `invitations` | list of PendingInvitationItem | Yes | The invitations. |

### LookupCrmContactItemResult

Whether one person is already in your CRM.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `linkedin_profile_id` | string, or null | Yes | LinkedIn profile id, the `ACoAA…` identifier of a person. |
| `slug` | string, or null | Yes | The public part of the person's LinkedIn URL, as in `linkedin.com/in/<slug>`. |
| `exists` | boolean | Yes | `true` when the person matches an existing CRM contact. |
| `source` | string | Yes | How that was decided. |
| `crm_contact_id` | string, or null | Yes | The matching contact. `null` with `exists: true` means several CRM records match: merge them in your CRM. |
| `crm_searched` | boolean | Yes | `true` when a live CRM search finished for this person. `false` is not proof that they are absent: run them again later. |
| `crm_match_count` | integer | No | CRM records the live search matched, when there is at least one. |
| `is_crm_contact_creation_blocked` | true | No | Only present, as `true`, when you blocked this person from CRM contact creation in Groovin. `crm/contacts` does not enforce the block, so check it yourself before creating. |

### LiveCrmSearchReport

How much of the live CRM search finished.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `supported` | boolean | Yes | `true` when your CRM has a live search (Attio and HubSpot). |
| `eligible` | integer | Yes | Unlinked people who have a `slug`, so can be searched. |
| `searched` | integer | Yes | People whose search finished. |
| `not_searched` | integer | Yes | People whose search did not finish. Run these again later. |
| `rate_limited` | boolean | Yes | `true` when your CRM slowed the search down. Wait about a minute before running the rest. |

### LookupCrmContactsResult

One answer per person you asked about.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `total` | integer | Yes | People checked. |
| `crm_search` | LiveCrmSearchReport | Yes | |
| `results` | list of LookupCrmContactItemResult | Yes | One item per person. |

### CreateCrmContactItemResult

What happened for one person. A `null` `crm_contact_id` means this item failed.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `linkedin_profile_id` | string | Yes | LinkedIn profile id, the `ACoAA…` identifier of a person. |
| `crm_contact_id` | string, or null | Yes | The CRM contact, or `null` on failure. |
| `outcome` | string, or null | Yes | What the creation did. `multiple_*_matches` and `uniqueness_conflict` mean the person probably already exists: review the records in `matched_crm_contact_ids`. |
| `email` | string, or null | Yes | A verified work email found and saved on a newly created Attio contact. Finding one spends an email credit. `null` otherwise. |
| `sync_enabled` | boolean | Yes | `true` when message sync was turned on. |
| `history_import_triggered` | boolean | Yes | `true` when this call started importing the chat history. |
| `error` | string, or null | Yes | What went wrong for this item, or `null`. Always read it: the rest of the batch can still have succeeded. |
| `error_status` | integer, or null | Yes | HTTP status behind `error`. `429` means rate limited and `5xx` usually means temporary: retry later. `null` when there is no error. |
| `matched_crm_contact_ids` | list of string, or null | Yes | Existing records to review, with `multiple_*_matches` or `uniqueness_conflict`. `null` otherwise. |

### CreateCrmContactsResult

The result of a batch. HTTP 200 does not mean every person succeeded: check each item.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `total` | integer | Yes | People in the batch. |
| `succeeded` | integer | Yes | People who now have a CRM contact. |
| `failed` | integer | Yes | People who do not. |
| `summary` | string | Yes | A one-line summary of the batch, worth reading. |
| `results` | list of CreateCrmContactItemResult | Yes | One item per person. |
| `retry_guidance` | string, or null | Yes | Plain-text advice when some items failed for a temporary reason, otherwise `null`. Follow it: it says when to retry, and which items. |

### SyncedCrmContact

A CRM contact whose LinkedIn conversation Groovin syncs.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `crm_contact_id` | string | Yes | The CRM contact. |
| `crm_url` | string, or null | Yes | A link to the contact in your CRM. |
| `linkedin_profile_id` | string | Yes | LinkedIn profile id, the `ACoAA…` identifier of a person. |
| `sales_nav_profile_id` | string, or null | Yes | Their Sales Navigator profile id. |
| `linkedin_profile_slugs` | list of string | Yes | The public URL slugs known for this person. |
| `last_sync_msg_at` | string, or null | Yes | When the last message was imported. `null` when nothing has been imported yet. |
| `is_msg_sync_enabled` | boolean | Yes | `true` when message sync is on. |
| `is_crm_contact_creation_blocked` | boolean | Yes | `true` when you blocked this person from CRM contact creation. Unlike the other routes, this one always returns it. |
| `full_name` | string, or null | No | From your CRM, with `include_crm_details: true`. The fields below work the same way. |
| `picture_url` | string, or null | No | Attio only. |
| `job_title` | string, or null | No | Attio and HubSpot. |
| `description` | string, or null | No | Attio only. |
| `primary_email` | string, or null | No | Their main email. |
| `linkedin_url` | string, or null | No | Attio and HubSpot. |
| `location` | string, or null | No | Attio and HubSpot. |

### ListSyncedCrmContactsResult

Your synced contacts, most recently synced first.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `crm_name` | string | Yes | Your CRM, such as `"attio"`. |
| `crm_details_included` | boolean | Yes | `true` when you asked for CRM details. |
| `total_matched` | integer | Yes | Synced contacts, before `limit`. |
| `returned` | integer | Yes | Contacts in this answer. |
| `truncated` | boolean | Yes | `true` when `limit` left contacts out. |
| `contacts` | list of SyncedCrmContact | Yes | The contacts. |

### ToggleLinkedinSyncItemResult

What happened for one contact. A contact linked to several LinkedIn profiles gets one item per profile.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `crm_contact_id` | string | Yes | The contact you asked about. |
| `relocated_to_crm_contact_id` | string, or null | Yes | Set when that record was merged away and Groovin moved the link to the surviving record. |
| `linkedin_profile_id` | string, or null | Yes | The LinkedIn profile that was toggled. |
| `enabled` | boolean | Yes | The state you asked for. |
| `status` | string | Yes | `skipped` usually means no LinkedIn profile could be linked: `error` says why. |
| `history_import_triggered` | boolean | Yes | On only: `true` when a first history import started. |
| `connection_state` | string, or null | Yes | On only: how your LinkedIn network sees this person. With `unknown`, nothing was recorded. |
| `conversation_notes_deleted` | integer | Yes | Off only: how many CRM notes Groovin tried to delete. This is the number attempted, not confirmed. |
| `pair_created` | boolean | Yes | `true` when this call linked the contact to a LinkedIn profile. |
| `crm_linkedin_url_write_status` | string, or null | Yes | What happened to the URL you sent on the CRM record. `null` when you sent none. |
| `crm_linkedin_url_write_error` | string, or null | Yes | Why that URL was not written. |
| `error` | string, or null | Yes | What went wrong for this item, or `null`. Always read it: the rest of the batch can still have succeeded. |
| `error_status` | integer, or null | Yes | HTTP status behind `error`. `429` means rate limited and `5xx` usually means temporary: retry later. `null` when there is no error. |

### ToggleLinkedinSyncResult

The result of a batch. HTTP 200 does not mean every contact succeeded: check each item.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `org_linkedin_account_id` | integer | Yes | Groovin's id for the LinkedIn account this answer is about. |
| `enabled` | boolean | Yes | The state you asked for. |
| `total` | integer | Yes | Items in `results`. |
| `succeeded` | integer | Yes | Items toggled. |
| `failed` | integer | Yes | Items that failed. |
| `results` | list of ToggleLinkedinSyncItemResult | Yes | One item per profile. |
| `retry_guidance` | string, or null | Yes | Plain-text advice when some items failed for a temporary reason, otherwise `null`. Follow it: it says when to retry, and which items. |

### FindLinkedinProfileUrlsItemResult

What happened for one contact.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `crm_contact_id` | string | Yes | The contact. |
| `status` | string | Yes | `found`: saved on the contact, and one credit spent. `already_present`, `not_found` and `ambiguous` spend nothing. |
| `linkedin_profile_url` | string, or null | Yes | The URL, when there is one. |
| `error` | string, or null | Yes | Read it on every status. On `found`, it means the URL could not be saved: add it by hand. On `not_found` or `ambiguous`, it means the search could not run in full, so the result proves nothing. |
| `error_status` | integer, or null | Yes | HTTP status behind `error`. `429` means rate limited and `5xx` usually means temporary: retry later. `null` when there is no error. |

### FindLinkedinProfileUrlsResult

The result of a batch. The batch can stop early: send what is in `not_processed` again.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `total` | integer | Yes | Contacts asked for, without duplicates. |
| `processed` | integer | Yes | Contacts actually searched. |
| `found` | integer | Yes | URLs found. |
| `failed` | integer | Yes | Searches that failed. |
| `not_processed` | list of string | Yes | Contacts this call did not search. Nothing was spent for them. Send only these again, never the whole list. |
| `not_processed_reason` | string, or null | Yes | Why the batch stopped early. `upstream_blocked` usually means your CRM must be reconnected. |
| `remaining_credits` | integer | Yes | Your finder credits after this call. |
| `retry_guidance` | string, or null | Yes | Plain-text advice when some items failed for a temporary reason, otherwise `null`. Follow it: it says when to retry, and which items. |
| `results` | list of FindLinkedinProfileUrlsItemResult | Yes | One item per contact searched. |

### CompanyDomainItemResult

What happened for one company.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `crm_company_id` | string, or null | Yes | The CRM company record, if you sent one. |
| `company_name` | string, or null | Yes | The company name. |
| `outcome` | string | Yes | `updated`: found and saved. `resolved`: found, nothing written. `ambiguous` and `not_found` are normal answers, not failures. |
| `domain` | string, or null | Yes | The domain, when there is one. |
| `source` | string, or null | Yes | How it was established: `company_search`, `contact_email`, `previously_found` or `already_present`. |
| `linkedin_url` | string, or null | Yes | The company's LinkedIn page, when known. It is only saved together with a domain. |
| `crm_updated` | boolean | Yes | `true` when the CRM record was changed. |
| `error` | string, or null | Yes | What went wrong for this item, or `null`. Always read it: the rest of the batch can still have succeeded. |
| `error_status` | integer, or null | Yes | HTTP status behind `error`. `429` means rate limited and `5xx` usually means temporary: retry later. `null` when there is no error. |

### FindCompanyDomainsResult

The result of a batch. The batch can stop early: send what is in `not_processed` again.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `total` | integer | Yes | Companies asked for, without duplicates. |
| `processed` | integer | Yes | Companies actually handled. |
| `found` | integer | Yes | Domains found. |
| `updated` | integer | Yes | CRM records changed. |
| `failed` | integer | Yes | Lookups that failed. |
| `not_processed` | list of string | Yes | Companies this call did not start, by id or name. |
| `not_processed_reason` | string, or null | Yes | Why the batch stopped early, in plain text. |
| `remaining_credits` | integer | Yes | Your domain credits after this call. |
| `retry_guidance` | string, or null | Yes | Plain-text advice when some items failed for a temporary reason, otherwise `null`. Follow it: it says when to retry, and which items. |
| `results` | list of CompanyDomainItemResult | Yes | One item per company. |

### ImportCounts

The running totals of an import. On a preview, `*_would_create` says what a real run would create.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `contacts_found` | integer | Yes | Contacts already in your CRM and recognised. |
| `contacts_found_by_name_and_company` | integer | Yes | Of those, how many were recognised by name and company alone. |
| `contacts_created` | integer | Yes | New contacts created. |
| `contacts_would_create` | integer | Yes | New contacts a real run would create. |
| `contacts_possible_duplicate` | integer | Yes | Rows left alone because someone in your CRM may be the same person. Only you can settle these. |
| `companies_found` | integer | Yes | Companies already in your CRM. |
| `companies_created` | integer | Yes | New companies created. |
| `companies_would_create` | integer | Yes | New companies a real run would create. |
| `company_domains_found` | integer | Yes | Companies whose web domain was found. |
| `companies_domain_pending` | integer | Yes | Companies to create whose domain was not found for free. |
| `skipped_blocked` | integer | Yes | Rows skipped because the person is blocked. |
| `skipped_duplicate_in_file` | integer | Yes | Rows repeated in the file. |
| `skipped_unusable` | integer | Yes | Rows without a usable LinkedIn URL. |
| `errors` | integer | Yes | Rows in error. |
| `ambiguous` | integer | Yes | Rows that matched several records. |

### ImportRowView

One row of an import.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `row_number` | integer | Yes | 1 is the first data row after the header. |
| `first_name` | string, or null | Yes | First name. |
| `last_name` | string, or null | Yes | Last name. |
| `linkedin_url` | string, or null | Yes | LinkedIn URL. |
| `company_name` | string, or null | Yes | Company. |
| `outcome` | string | Yes | What happened to this row, or `not_processed` if the import never reached it. |
| `match_reason` | string, or null | Yes | How an existing contact was recognised. |
| `crm_contact_id` | string, or null | Yes | The CRM contact. |
| `crm_contact_url` | string, or null | Yes | A link to it in your CRM. |
| `company_outcome` | string, or null | Yes | What happened to the company. |
| `crm_company_id` | string, or null | Yes | The CRM company. |
| `possible_duplicate_crm_contact_ids` | list of string | Yes | Same-name contacts that stopped a creation. |
| `possible_duplicate_urls` | list of string | Yes | Links to them, to settle by hand. |
| `error_source` | string, or null | Yes | Where an error came from. |
| `message` | string, or null | Yes | Why the row was left alone, or what failed. |

### ImportAnswer

The state of an import. Every import route answers with this.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `import_id` | string | Yes | The import. |
| `status` | string | Yes | `ready` or `running` while it works, then `completed`, `cancelled` or `failed`. |
| `dry_run` | boolean | Yes | `true` for a preview. |
| `crm_name` | string | Yes | Your CRM: `"attio"` or `"hubspot"`. |
| `file_name` | string, or null | Yes | The name of the result file. |
| `created_at` | string | Yes | When the import was created. |
| `started_at` | string, or null | Yes | When it started. |
| `finished_at` | string, or null | Yes | When it finished. |
| `total_rows` | integer | Yes | Data rows in the file. Compare this with your file: a mismatch means the file was cut on the way in. |
| `processed_rows` | integer | Yes | Rows done. |
| `pending_rows` | integer | Yes | Rows left. |
| `counts` | ImportCounts | Yes | |
| `lists` | object | Yes | The CRM lists the import adds records to. |
| `column_map` | object | Yes | Which column of the file was read as what. |
| `parse_warnings` | list of string | Yes | What the file reader could not read. |
| `last_error` | string, or null | Yes | The latest problem, if any. |
| `is_processing` | boolean | Yes | `true` while rows are being worked on right now. |
| `cancel_requested_at` | string, or null | Yes | When you asked to stop. |
| `rows_purged_at` | string, or null | Yes | When the row data was deleted. No row detail and no re-run after that. |
| `finished_notified_at` | string, or null | Yes | When you were emailed. |
| `retention_hours` | integer | Yes | How long row data is kept, in hours. |
| `company_domain_credits_remaining` | integer, or null | Yes | Your domain credits when this run last looked. |
| `domain_credits_exhausted_at` | string, or null | Yes | When credits ran out. Later companies were created with a name but no domain. |
| `on_behalf_of` | object, or null | Yes | The teammate whose connections these are. `null` means your own. |
| `update_recognised_contacts` | boolean | Yes | `true` when a real run updates the contacts it recognises. |
| `poll_after_seconds` | integer, or null | Yes | Wait this long before asking again. `null` once the import can no longer change. |
| `next_step` | string | Yes | What to do now, in one sentence. |
| `rows_available` | boolean | Yes | `false` once the row data was deleted: counts only. |
| `rows` | list of ImportRowView | No | One page of rows, if you asked. |
| `rows_total_matched` | integer | No | Rows matching your filter. |
| `rows_returned` | integer | No | Rows in this answer. |
| `rows_offset` | integer | No | The `offset` you sent. |
| `rows_truncated` | boolean | No | `true` when more rows exist: ask with a new `offset`. |

### LinkedinProfile

A LinkedIn profile, as Groovin models it. Field names use camelCase here, unlike the rest of the API. Every field is optional.

| Field | Type | Always there | What it means |
| - | - | - | - |
| `id` | string, or null | No | LinkedIn profile id (ACoAA…). |
| `url` | string, or null | No | Canonical profile URL. |
| `slugs` | list of string, or null | No | All known slugs / ids for the profile. |
| `salesNavId` | string, or null | No | Sales Navigator profile id (ACwAA…/ADEAA…), when known. |
| `firstName` | string, or null | No | First name. |
| `lastName` | string, or null | No | Last name. |
| `emailAddress` | string, or null | No | LinkedIn-registered personal email, when visible. |
| `headline` | string, or null | No | LinkedIn headline. |
| `summary` | string, or null | No | Long-form bio. |
| `locationName` | string, or null | No | Flat location string, e.g. "Paris, Île-de-France, France". |
| `location` | object, or null | No | Structured location. |
| `industryName` | string, or null | No | Industry, read from the profile's ongoing positions. |
| `educationSchoolNames` | list of string, or null | No | All school names. |
| `phoneNumbers` | list of string, or null | No | Phone numbers LinkedIn exposes, when visible. |
| `websites` | list of string, or null | No | Websites listed on the profile. |
| `currentPosition` | object, or null | No | The single current position, with its snapshot of the company. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.