# Grinfi.io API

Complete API reference for Grinfi.io — the all-in-one LinkedIn & email outreach platform.
Use this API to manage your CRM contacts, run outreach automations, send messages, and integrate Grinfi with your own tools.

## Authentication
All requests require a Bearer token in the `Authorization` header.
1. Log in at [leadgen.grinfi.io](https://leadgen.grinfi.io/)
2. Go to [Settings → API Keys](https://leadgen.grinfi.io/settings/api-keys)
3. Copy your key and pass it as:
   ```
   Authorization: Bearer YOUR_API_KEY
   ```


## Pagination
List endpoints support `limit` (default 20) and `offset` (default 0) query parameters. Responses include `total` count and `has_more` boolean.

## Filtering
Most list endpoints accept a `filter` object. Supported value types:
| Type | Example | SQL equivalent | |------|---------|----------------| | Scalar | `"status": "ok"` | `= 'ok'` | | Array | `"status": ["ok", "pending"]` | `IN ('ok', 'pending')` | | Object | `"created_at": {">=": "2024-01-01"}` | `>= '2024-01-01'` | | `"is_null"` | `"email": "is_null"` | `IS NULL` | | `"is_not_null"` | `"email": "is_not_null"` | `IS NOT NULL` |
Supported operators: `=`, `!=`, `<`, `<=`, `>`, `>=`, `<>`

## Rate Limits
API requests are rate-limited to **300 requests per minute** per API key. If you exceed the limit, you'll receive a `429` response. Use exponential backoff when retrying.

## Contact Deduplication
When creating contacts via upsert, the system checks for duplicates using the following field priority (first match wins):
1. `ln_member_id` (LinkedIn member ID)
2. `ln_id` (LinkedIn public ID)
3. `sn_id` (Sales Navigator ID)
4. LinkedIn nickname
5. `work_email`
6. `personal_email`
7. `name` + `company_name` combination


Version: 2.0.0
License: Copyright

## Servers

Production
```
https://leadgen.grinfi.io
```

## Security

### bearerAuth

[object Object]

Type: http
Scheme: bearer
Bearer Format: JWT

## Download OpenAPI description

 - [Grinfi.io API](https://api.grinfi.io/_bundle/openapi.yaml)

## User

 - [GET /id/api/users/current](https://api.grinfi.io/openapi/user/getcurrentuser.md): Retrieve the authenticated user's profile and configuration.
## Teams

 - [GET /id/api/teams](https://api.grinfi.io/openapi/teams/listteams.md): List all teams (workspaces) the authenticated user has access to.
 - [GET /id/api/teams/{id}](https://api.grinfi.io/openapi/teams/getteam.md): Get details of a specific team by ID.
 - [POST /id/api/teams/{id}/check-limits](https://api.grinfi.io/openapi/teams/checkteamlimits.md): Check whether the team has capacity for the requested number of additional sender profiles within its current subscription limits. Returns monthly and yearly usage information (or `null` for each if t
## API Keys

 - [POST /id/api/jwt-tokens/create-api-key](https://api.grinfi.io/openapi/api-keys/createapikey.md): Create a new API key bound to your current team. The returned `last_token` is the actual JWT to use in the `Authorization: Bearer <token>` header on subsequent requests. Tokens have a 3-year expiry. *
## Contacts

 - [POST /leads/api/leads/lookup-one](https://api.grinfi.io/openapi/contacts/findonecontact.md): Look up a single contact by LinkedIn ID, email address, or name + company combination. At least one identifier must be provided. This is useful for checking if a contact already exists before creating
 - [POST /leads/api/leads/search](https://api.grinfi.io/openapi/contacts/searchcontacts.md): Search contacts using advanced filters with pagination and sorting. Use this to find contacts by any combination of fields — name, company, email status, pipeline stage, tags, and more.
 - [GET /leads/api/leads/{uuid}](https://api.grinfi.io/openapi/contacts/getlead.md): Retrieve full details of a contact by their UUID.
 - [PUT /leads/api/leads/{uuid}](https://api.grinfi.io/openapi/contacts/updatelead.md): Update one or more fields on an existing contact. Only include the fields you want to change. **Important:** this endpoint only accepts the standard contact fields listed below. Custom field values ar
 - [DELETE /leads/api/leads/{uuid}](https://api.grinfi.io/openapi/contacts/deletelead.md): Permanently delete a contact by UUID. This creates a background deletion job.
 - [POST /leads/api/leads/upsert](https://api.grinfi.io/openapi/contacts/upsertcontact.md): Create a new contact in a list, or update an existing one if found. The contact is identified by `linkedin_id`. If the contact already exists and `update_if_exists` is true, their data will be updated
 - [PUT /leads/api/leads/mass-action](https://api.grinfi.io/openapi/contacts/leadsmassaction.md): Perform a bulk action on contacts matching a filter. **Supported action types:** | Type | Payload | Description | |------|---------|-------------| | `contact_add_tags` | `{tag_uuid}` | Add a tag | | `
 - [POST /leads/api/leads/count](https://api.grinfi.io/openapi/contacts/countcontacts.md): Count contacts matching a filter without returning the full data. Use `all: true` to count every contact in the team, or pass an explicit list of contact UUIDs in `ids` (with `all: false`) to count a
 - [POST /leads/api/leads/metrics](https://api.grinfi.io/openapi/contacts/getleadmetrics.md): Returns aggregated outreach metrics across the whole team for the requested period. **Important:** despite accepting a `filter` field, this endpoint currently returns team-wide totals only — `filter.s
 - [PUT /leads/api/leads/advanced-enrichment](https://api.grinfi.io/openapi/contacts/enrichleadsadvanced.md): Enqueue advanced LinkedIn enrichment on a set of contacts. Enrichment consumes credits — returns `402 Payment Required` if your team has insufficient balance.
 - [GET /leads/api/enrichment-queue](https://api.grinfi.io/openapi/contacts/listenrichmentqueue.md): List entries in the enrichment processing queue.
 - [POST /leads/api/enrichment-queue/metrics](https://api.grinfi.io/openapi/contacts/getenrichmentmetrics.md): Return aggregate metrics about enrichment activity for the team — currently the count of enrichment jobs queued/processed in the current calendar month.
## Companies

 - [GET /leads/api/companies](https://api.grinfi.io/openapi/companies/listcompanies.md): Retrieve a paginated list of companies in your CRM. Supports filtering by name, domain, industry, and other fields.
 - [POST /leads/api/companies](https://api.grinfi.io/openapi/companies/createcompanies.md): Create one or more company records. Optionally assign them to lists and a data source.
 - [GET /leads/api/companies/{uuid}](https://api.grinfi.io/openapi/companies/getcompany.md): Retrieve full details of a company by UUID.
 - [PUT /leads/api/companies/{uuid}](https://api.grinfi.io/openapi/companies/updatecompany.md): Update one or more fields on an existing company.
 - [DELETE /leads/api/companies/{uuid}](https://api.grinfi.io/openapi/companies/deletecompany.md): Permanently delete a company by UUID.
 - [POST /leads/api/companies/list](https://api.grinfi.io/openapi/companies/searchcompanies.md): Search and filter companies with pagination. Same filtering capabilities as `GET /leads/api/companies` but as a POST so you can pass complex `filter` objects in the request body instead of query strin
 - [POST /leads/api/companies/lookup](https://api.grinfi.io/openapi/companies/lookupcompanies.md): Find companies by LinkedIn ID, website URL, or name. Pass an array of lookup criteria — each item should contain at least one identifier.
 - [POST /leads/api/companies/leads](https://api.grinfi.io/openapi/companies/getcompanyleads.md): Retrieve all contacts belonging to the specified companies. Returns an object mapping company UUIDs to arrays of contacts.
 - [PUT /leads/api/companies/advanced-enrichment](https://api.grinfi.io/openapi/companies/enrichcompanies.md): Queue advanced enrichment for companies. Provide either a filter to select companies or an array of specific company UUIDs. Enrichment uses credits from your account balance.
 - [PUT /leads/api/companies/mass-action](https://api.grinfi.io/openapi/companies/companiesmassaction.md): Perform a bulk action on companies matching a filter.
## Lists

 - [GET /leads/api/lists](https://api.grinfi.io/openapi/lists/listlists.md): Retrieve all contact lists in your account. Lists are used to organize contacts into groups for outreach campaigns.
 - [POST /leads/api/lists](https://api.grinfi.io/openapi/lists/createlist.md): Create a new contact list.
 - [GET /leads/api/lists/{uuid}](https://api.grinfi.io/openapi/lists/getlist.md): Retrieve details of a specific contact list.
 - [PUT /leads/api/lists/{uuid}](https://api.grinfi.io/openapi/lists/updatelist.md): Rename an existing contact list.
 - [DELETE /leads/api/lists/{uuid}](https://api.grinfi.io/openapi/lists/deletelist.md): Permanently delete a contact list.
 - [POST /leads/api/lists/metrics](https://api.grinfi.io/openapi/lists/getlistmetrics.md): Get lead counts for specified lists.
## Tags

 - [GET /leads/api/tags](https://api.grinfi.io/openapi/tags/listtags.md): Retrieve all tags in your account.
 - [POST /leads/api/tags](https://api.grinfi.io/openapi/tags/createtag.md): Create a new tag with optional color.
 - [PUT /leads/api/tags/{uuid}](https://api.grinfi.io/openapi/tags/updatetag.md): Update a tag's name or color.
 - [DELETE /leads/api/tags/{uuid}](https://api.grinfi.io/openapi/tags/deletetag.md): Permanently delete a tag.
 - [POST /leads/api/tags/metrics](https://api.grinfi.io/openapi/tags/gettagmetrics.md): Get lead and company counts for specified tags.
## Pipeline

 - [GET /leads/api/pipeline-stages](https://api.grinfi.io/openapi/pipeline/listpipelinestages.md): Retrieve all pipeline stages. Use the `filter` parameter (JSON string) to narrow results by object type or stage type.
 - [POST /leads/api/pipeline-stages](https://api.grinfi.io/openapi/pipeline/createpipelinestage.md): Create a new custom pipeline stage.
 - [PUT /leads/api/pipeline-stages/{uuid}](https://api.grinfi.io/openapi/pipeline/updatepipelinestage.md): Update a pipeline stage's name, category, or order.
 - [DELETE /leads/api/pipeline-stages/{uuid}](https://api.grinfi.io/openapi/pipeline/deletepipelinestage.md): Delete a custom pipeline stage.
## Custom Fields

 - [GET /leads/api/custom-fields](https://api.grinfi.io/openapi/custom-fields/listcustomfields.md): Retrieve all custom field definitions for contacts and companies.
 - [POST /leads/api/custom-fields](https://api.grinfi.io/openapi/custom-fields/createcustomfield.md): Define a new custom field for contacts or companies.
 - [PUT /leads/api/custom-fields/{uuid}](https://api.grinfi.io/openapi/custom-fields/updatecustomfield.md): Update a custom field's name or order.
 - [DELETE /leads/api/custom-fields/{uuid}](https://api.grinfi.io/openapi/custom-fields/deletecustomfield.md): Permanently remove a custom field definition and all its values.
 - [POST /leads/api/custom-field-values](https://api.grinfi.io/openapi/custom-fields/upsertcustomfieldvalue.md): Set (or update) a custom field value on a contact or company. Pass `null` as value to clear the field.
## Notes

 - [GET /leads/api/notes](https://api.grinfi.io/openapi/notes/listnotes.md): Retrieve notes with pagination.
 - [POST /leads/api/notes](https://api.grinfi.io/openapi/notes/createnote.md): Add a note to a contact or company.
 - [PUT /leads/api/notes/{uuid}](https://api.grinfi.io/openapi/notes/updatenote.md): Update the text of an existing note.
 - [DELETE /leads/api/notes/{uuid}](https://api.grinfi.io/openapi/notes/deletenote.md): Permanently delete a note.
## Activities

 - [GET /leads/api/activities](https://api.grinfi.io/openapi/activities/listactivities.md): List activity records for contacts or companies. Activities track events like messages sent, emails opened, pipeline stage changes, and more. **Known activity types:** `pipeline_stage_changed`, `linke
 - [POST /leads/api/activities](https://api.grinfi.io/openapi/activities/createactivity.md): Create a new activity record for a contact or company.
## Blacklist

 - [GET /leads/api/leads-blacklist](https://api.grinfi.io/openapi/blacklist/listleadsblacklist.md): Returns blacklisted contact entries for the team. Blacklisted contacts are excluded from imports, enrichment, automations, and mass actions.
 - [POST /leads/api/leads-blacklist](https://api.grinfi.io/openapi/blacklist/addleadtoblacklist.md): Blacklist a contact by LinkedIn handle, email, name, or company name. Provide at least one identifier; the entry is matched on import and outreach.
 - [DELETE /leads/api/leads-blacklist/{uuid}](https://api.grinfi.io/openapi/blacklist/deleteleadblacklistentry.md): Delete a blacklist entry by its UUID.
 - [GET /leads/api/companies-blacklist](https://api.grinfi.io/openapi/blacklist/listcompaniesblacklist.md): Returns blacklisted company entries for the team. Blacklisted companies are excluded from imports, enrichment, automations, and mass actions.
 - [POST /leads/api/companies-blacklist](https://api.grinfi.io/openapi/blacklist/addcompanytoblacklist.md): Blacklist a company by LinkedIn handle, domain, or name. Provide at least one identifier; the entry is matched on import and outreach.
 - [DELETE /leads/api/companies-blacklist/{uuid}](https://api.grinfi.io/openapi/blacklist/deletecompanyblacklistentry.md): Delete a blacklist entry by its UUID.
## Data Sources

 - [GET /leads/api/data-sources](https://api.grinfi.io/openapi/data-sources/listdatasources.md): List LinkedIn import jobs with pagination.
 - [POST /leads/api/data-sources](https://api.grinfi.io/openapi/data-sources/createdatasource.md)
 - [GET /leads/api/data-sources/{uuid}](https://api.grinfi.io/openapi/data-sources/getdatasource.md)
 - [PUT /leads/api/data-sources/{uuid}](https://api.grinfi.io/openapi/data-sources/updatedatasource.md)
 - [DELETE /leads/api/data-sources/{uuid}](https://api.grinfi.io/openapi/data-sources/deletedatasource.md)
 - [PUT /leads/api/data-sources/metrics](https://api.grinfi.io/openapi/data-sources/getdatasourcemetrics.md): Return per-data-source counts of queued, saved, duplicate, blacklisted, and error records. Pass an array of data source UUIDs in `uuids`. The response is a map keyed by UUID.
## File Operations

 - [POST /leads/api/file-imports/upload-csv](https://api.grinfi.io/openapi/file-operations/uploadcsvfile.md): Upload a CSV file to be imported as contacts or companies. Returns a file-import record with a UUID. Pass that UUID to `import-leads` or `import-companies` to actually create the records. **Note:** th
 - [POST /leads/api/file-imports/{uuid}/import-leads](https://api.grinfi.io/openapi/file-operations/importleadsfromfile.md): Trigger contact import from a previously uploaded CSV file. Required field: `columns` — an ordered list of column-mapping objects describing how to map CSV columns to contact fields.
 - [POST /leads/api/file-imports/{uuid}/import-companies](https://api.grinfi.io/openapi/file-operations/importcompaniesfromfile.md): Trigger company import from a previously uploaded CSV file.
 - [POST /leads/api/file-exports/leads](https://api.grinfi.io/openapi/file-operations/exportleadstocsv.md): Queue a CSV export of contacts matching the filter. Returns a file-export record with status `queued`. Once the job completes, use `download` to retrieve the file.
 - [POST /leads/api/file-exports/companies](https://api.grinfi.io/openapi/file-operations/exportcompaniestocsv.md): Queue a CSV export of companies matching the filter.
 - [POST /leads/api/file-exports/download](https://api.grinfi.io/openapi/file-operations/downloadexportfile.md): Retrieve a previously generated export file by name. The `file_name` is returned as part of the export record once the job completes.
## Automations

 - [GET /flows/api/flows](https://api.grinfi.io/openapi/automations/listflows.md): Retrieve all outreach automations in your account. Automations are multi-step sequences that send LinkedIn messages, emails, and other actions on a schedule.
 - [POST /flows/api/flows](https://api.grinfi.io/openapi/automations/createflow.md): Create a new outreach automation (flow) programmatically. The automation is created in `draft` status with no node tree yet — add the workflow steps in a second call to [`POST /flows/api/flows/{flowUu
 - [GET /flows/api/flows/{flowUuid}](https://api.grinfi.io/openapi/automations/getflow.md): Retrieve full details of an automation by UUID.
 - [PUT /flows/api/flows/{flowUuid}](https://api.grinfi.io/openapi/automations/updateflow.md): Update an automation's name, description, or schedule.
 - [DELETE /flows/api/flows/{flowUuid}](https://api.grinfi.io/openapi/automations/deleteflow.md): Permanently delete an automation. This cannot be undone.
 - [PUT /flows/api/flows/{flowUuid}/start](https://api.grinfi.io/openapi/automations/startflow.md): Activate an automation so it begins processing contacts and executing outreach steps on its schedule.
 - [PUT /flows/api/flows/{flowUuid}/stop](https://api.grinfi.io/openapi/automations/stopflow.md): Pause an automation. Contacts already in progress will finish their current step.
 - [PUT /flows/api/flows/{flowUuid}/archive](https://api.grinfi.io/openapi/automations/archiveflow.md): Archive an automation. Archived automations cannot be started.
 - [PUT /flows/api/flows/{flowUuid}/unarchive](https://api.grinfi.io/openapi/automations/unarchiveflow.md): Restore an archived automation so it can be started again.
 - [POST /flows/api/flows/clone](https://api.grinfi.io/openapi/automations/cloneflow.md): Create a copy of an existing automation with a new name. The cloned automation will be in a stopped state.
 - [POST /flows/api/flows/{flowUuid}/statistics/nodes](https://api.grinfi.io/openapi/automations/getflownodestatistics.md): Per-step funnel for an automation — **the accurate per-campaign engagement source, matching the web app**. For each node you get how many contacts reached each status and the real conversions at that
 - [POST /flows/api/flows/{flowUuid}/statistics/contact-sources](https://api.grinfi.io/openapi/automations/getflowcontactsourcestatistics.md): Funnel broken down by **contact source** (audience) of an automation, with a per-channel conversion breakdown. Use it to compare how different audiences of the same flow perform. `contact_source_ids`
 - [POST /flows/api/flows-leads/list](https://api.grinfi.io/openapi/automations/listflowleads.md): Search contacts enrolled in automations. Returns flow-lead records that link a contact to a flow with status, current node, and timing fields.
 - [DELETE /flows/api/flows/leads/{leadUuid}](https://api.grinfi.io/openapi/automations/deleteflowleadhistory.md): Permanently delete all flow-lead records for a contact across all automations. This removes the enrollment history; the contact itself is not deleted.
 - [GET /flows/api/flow-workspaces](https://api.grinfi.io/openapi/automations/listflowworkspaces.md): List all automation folders (workspaces) for organizing automations.
 - [POST /flows/api/flow-workspaces](https://api.grinfi.io/openapi/automations/createflowworkspace.md)
 - [PUT /flows/api/flow-workspaces/{uuid}](https://api.grinfi.io/openapi/automations/updateflowworkspace.md)
 - [DELETE /flows/api/flow-workspaces/{uuid}](https://api.grinfi.io/openapi/automations/deleteflowworkspace.md)
 - [POST /flows/api/flows/metrics](https://api.grinfi.io/openapi/automations/getflowmetrics.md): Retrieve current-state metrics for one or more automations: contact counts and the **pending task queue** per automation UUID. **`task_counts` is queue depth, not sent volume.** It counts tasks still
 - [POST /flows/api/flows/{flowUuid}/leads/{leadUuid}](https://api.grinfi.io/openapi/automations/addleadtoflow.md): Add an existing contact to an automation. The contact will enter the automation from the beginning of the sequence.
 - [POST /flows/api/flows/{flowUuid}/add-new-lead](https://api.grinfi.io/openapi/automations/addnewleadtoflow.md): Create a new contact and immediately add them to an automation. The contact is created in the specified list and starts the automation sequence. If `skip_if_lead_exists` is true, existing contacts won
 - [PUT /flows/api/flows/leads/{leadUuid}/cancel](https://api.grinfi.io/openapi/automations/cancelleadfromflows.md): Remove a contact from specific automations. The contact's progress in those automations will be cancelled.
 - [PUT /flows/api/flows/leads/{leadUuid}/cancel-all](https://api.grinfi.io/openapi/automations/cancelleadfromallflows.md): Remove a contact from all active automations at once.
## Flow Versions

 - [GET /flows/api/flows/{flowUuid}/flow-versions](https://api.grinfi.io/openapi/flow-versions/listflowversions.md): List all versions saved for a flow. Each version is an immutable snapshot.
 - [POST /flows/api/flows/{flowUuid}/flow-versions](https://api.grinfi.io/openapi/flow-versions/createflowversion.md): Save a new version (snapshot) of the flow's node tree and contact sources. Versions are immutable; activating a different version replaces the running config.
 - [GET /flows/api/flow-versions/{uuid}](https://api.grinfi.io/openapi/flow-versions/getflowversion.md): Retrieve a specific flow version by UUID.
 - [DELETE /flows/api/flow-versions/{uuid}](https://api.grinfi.io/openapi/flow-versions/deleteflowversion.md): Permanently delete a flow version. Active versions cannot be deleted.
 - [POST /flows/api/flow-versions/validate-node](https://api.grinfi.io/openapi/flow-versions/validateflownode.md): Validate a single node configuration without saving it. Useful for pre-flight checks when building a flow programmatically. Send the **same node object shape** you would put inside a flow version (see
 - [POST /flows/api/flow-versions/validate-contact-source](https://api.grinfi.io/openapi/flow-versions/validatecontactsource.md): Validate a contact source configuration without saving it.
## Tasks

 - [GET /flows/api/tasks](https://api.grinfi.io/openapi/tasks/listtasks.md): Retrieve outreach tasks. Tasks are the individual actions an automation executes (or that you create manually) — one task per contact per step. **All filters use the `filter[...]` form** (URL-encode t
 - [POST /flows/api/tasks](https://api.grinfi.io/openapi/tasks/createtask.md): Create a manual outreach task. Common types: `linkedin_send_message`, `linkedin_send_connection_request`, `linkedin_send_inmail`, `linkedin_like_latest_post`, `linkedin_endorse_skills`.
 - [GET /flows/api/tasks/{uuid}](https://api.grinfi.io/openapi/tasks/gettask.md): Retrieve details of a specific task.
 - [PUT /flows/api/tasks/{uuid}/complete](https://api.grinfi.io/openapi/tasks/completetask.md): Mark a manual task as completed. Only works for manual tasks.
 - [PUT /flows/api/tasks/{uuid}/cancel](https://api.grinfi.io/openapi/tasks/canceltask.md): Cancel a manual task. Only works for manual tasks.
 - [PUT /flows/api/tasks/{uuid}/fail](https://api.grinfi.io/openapi/tasks/failtask.md): Mark a manual task as failed. Only works for manual tasks.
 - [PUT /flows/api/tasks/continue-automation](https://api.grinfi.io/openapi/tasks/continueautomation.md): Resume a paused automation for a specific contact. The contact will continue from where they were paused in the automation sequence.
 - [GET /flows/api/tasks/schedule](https://api.grinfi.io/openapi/tasks/gettasksschedule.md): Get the tasks schedule for a specific sender profile on a given date. Returns the timeline of scheduled tasks.
 - [PUT /flows/api/tasks/mass-cancel](https://api.grinfi.io/openapi/tasks/masscanceltasks.md): Cancel multiple manual tasks at once. Only works for manual tasks.
 - [PUT /flows/api/tasks/mass-complete](https://api.grinfi.io/openapi/tasks/masscompletetasks.md): Mark multiple manual tasks as completed at once.
 - [PUT /flows/api/tasks/mass-retry](https://api.grinfi.io/openapi/tasks/massretrytasks.md): Retry multiple failed manual tasks at once.
 - [PUT /flows/api/tasks/mass-skip](https://api.grinfi.io/openapi/tasks/massskiptasks.md): Skip multiple manual tasks at once.
 - [POST /flows/api/tasks/group-counts](https://api.grinfi.io/openapi/tasks/groupcounttasks.md): Return task counts **broken down by a field**, in a single request — the efficient way to get per-campaign, per-sender or per-type activity without one call per slice. `group_field` chooses the breakd
## Sender Profiles

 - [GET /flows/api/sender-profiles](https://api.grinfi.io/openapi/sender-profiles/listsenderprofiles.md): Retrieve all sender profiles. A sender profile represents a person (with linked LinkedIn account and/or email mailbox) who sends outreach messages.
 - [POST /flows/api/sender-profiles](https://api.grinfi.io/openapi/sender-profiles/createsenderprofile.md): Create a sender profile — the channel identity that sends messages. This is step 1 of connecting a LinkedIn account for an end user; attach a LinkedIn seat next with [`POST /browsers/api/linkedin-brow
 - [GET /flows/api/sender-profiles/{uuid}](https://api.grinfi.io/openapi/sender-profiles/getsenderprofile.md): Retrieve details of a sender profile.
 - [PUT /flows/api/sender-profiles/{uuid}](https://api.grinfi.io/openapi/sender-profiles/updatesenderprofile.md): Update a sender profile's name, label, or schedule.
 - [DELETE /flows/api/sender-profiles/{uuid}](https://api.grinfi.io/openapi/sender-profiles/deletesenderprofile.md): Permanently delete a sender profile.
 - [PUT /flows/api/sender-profiles/{uuid}/enable](https://api.grinfi.io/openapi/sender-profiles/enablesenderprofile.md): Enable a sender profile so it can be used in automations.
 - [PUT /flows/api/sender-profiles/{uuid}/disable](https://api.grinfi.io/openapi/sender-profiles/disablesenderprofile.md): Disable a sender profile. It will no longer be used in automations.
## AI Agents

 - [GET /flows/api/ai-agents](https://api.grinfi.io/openapi/ai-agents/listaiagents.md): Returns all AI agents in the team with their LLM configuration and metadata.
 - [POST /flows/api/ai-agents](https://api.grinfi.io/openapi/ai-agents/createaiagent.md): Create a new AI agent that will use the configured LLM for classification and similar tasks. Requires a connected LLM (`classification_llm_uuid`).
 - [GET /flows/api/ai-agents/{uuid}](https://api.grinfi.io/openapi/ai-agents/getaiagent.md): Retrieve a single AI agent by UUID.
 - [PUT /flows/api/ai-agents/{uuid}](https://api.grinfi.io/openapi/ai-agents/updateaiagent.md): Update fields on an existing AI agent. Only the supplied fields are changed.
 - [DELETE /flows/api/ai-agents/{uuid}](https://api.grinfi.io/openapi/ai-agents/deleteaiagent.md): Permanently delete an AI agent. Cannot be undone.
## AI Templates

 - [GET /flows/api/ai-templates](https://api.grinfi.io/openapi/ai-templates/listaitemplates.md): List all AI templates (reusable AI-driven message snippets) for the team.
 - [POST /flows/api/ai-templates](https://api.grinfi.io/openapi/ai-templates/createaitemplate.md): Create a reusable message template. Templates are referenced from flow nodes by their `uuid` (the `template_uuid` field on `linkedin_send_message`, `email_send_message`, etc.). **`is_public` is requir
 - [GET /flows/api/ai-templates/{uuid}](https://api.grinfi.io/openapi/ai-templates/getaitemplate.md): Retrieve a single AI template by UUID, including its prompt and LLM config.
 - [PUT /flows/api/ai-templates/{uuid}](https://api.grinfi.io/openapi/ai-templates/updateaitemplate.md): Update fields on an existing AI template.
 - [DELETE /flows/api/ai-templates/{uuid}](https://api.grinfi.io/openapi/ai-templates/deleteaitemplate.md): Delete an AI template. Returns `204`; the deletion takes effect (the template disappears from the web app). **Known issue:** deletion appears to be a soft-delete that the API read path does not filter
 - [POST /flows/api/ai-templates/render](https://api.grinfi.io/openapi/ai-templates/renderaitemplate.md): Render a template for a specific contact and sender profile. The simplest usage is to pass an existing template `uuid` along with `lead_uuid` and `sender_profile_uuid` — the saved template configurati
## LinkedIn Messages

 - [GET /flows/api/linkedin-messages](https://api.grinfi.io/openapi/linkedin-messages/listlinkedinmessages.md): Retrieve LinkedIn messages from your unified inbox. Filter by contact, sender profile, conversation, message type (inbox/outbox), and status.
 - [POST /flows/api/linkedin-messages](https://api.grinfi.io/openapi/linkedin-messages/sendlinkedinmessage.md): Send a LinkedIn message to a contact through a sender profile. The message will be queued and sent via the linked LinkedIn account.
 - [DELETE /flows/api/linkedin-messages/{uuid}](https://api.grinfi.io/openapi/linkedin-messages/deletelinkedinmessage.md): Delete a LinkedIn message record.
 - [PUT /flows/api/linkedin-messages/{uuid}/retry](https://api.grinfi.io/openapi/linkedin-messages/retrylinkedinmessage.md): Retry sending a LinkedIn message that previously failed.
 - [POST /flows/api/linkedin-messages/group-counts](https://api.grinfi.io/openapi/linkedin-messages/groupcountlinkedinmessages.md): Return LinkedIn-message counts **broken down by a field**, in one request. This is the right way to get per-sender messaging activity — including **replies per sender** (`group_field: sender_profile_u
## Emails

 - [GET /emails/api/emails](https://api.grinfi.io/openapi/emails/listemails.md): Retrieve emails from your unified inbox. Filter by contact, mailbox, automation (`flow_uuid`), type (`inbox`/`outbox`), status, and date range. Filters use the **`filter[...]`** form (URL-encode the b
 - [GET /emails/api/emails/{uuid}](https://api.grinfi.io/openapi/emails/getemail.md): Retrieve full details of an email by UUID.
 - [DELETE /emails/api/emails/{uuid}](https://api.grinfi.io/openapi/emails/deleteemail.md): Delete an email record.
 - [POST /emails/api/emails/send-email](https://api.grinfi.io/openapi/emails/sendemail.md): Send a new email to a contact through a connected mailbox.
 - [GET /emails/api/email-bodies](https://api.grinfi.io/openapi/emails/listemailbodies.md): List email body records (HTML content, subject, attachments).
 - [GET /emails/api/email-bodies/{uuid}](https://api.grinfi.io/openapi/emails/getemailbody.md): Get the HTML content, subject, and attachments of an email body.
 - [GET /emails/api/emails/{uuid}/thread](https://api.grinfi.io/openapi/emails/getemailthread.md): Get the conversation thread for a reply email.
 - [POST /emails/api/emails/latest-by-leads](https://api.grinfi.io/openapi/emails/getlatestemailsbyleads.md): Get the most recent email for each of the specified contact UUIDs.
 - [POST /emails/api/emails/llm-thread](https://api.grinfi.io/openapi/emails/getemailllmthread.md): Get an email conversation thread formatted for LLM processing. Optimized for AI analysis and response generation.
## Mailboxes

 - [GET /emails/api/mailboxes](https://api.grinfi.io/openapi/mailboxes/listmailboxes.md): Retrieve all email mailboxes (SMTP/IMAP, Gmail, Outlook) configured in your account.
 - [POST /emails/api/mailboxes](https://api.grinfi.io/openapi/mailboxes/createmailbox.md): Add a new SMTP/IMAP mailbox with connection settings.
 - [GET /emails/api/mailboxes/{uuid}](https://api.grinfi.io/openapi/mailboxes/getmailbox.md): Retrieve details of a specific mailbox.
 - [PUT /emails/api/mailboxes/{uuid}](https://api.grinfi.io/openapi/mailboxes/updatemailbox.md): Update mailbox settings such as sender name, daily limits, or connection details.
 - [DELETE /emails/api/mailboxes/{uuid}](https://api.grinfi.io/openapi/mailboxes/deletemailbox.md): Delete a mailbox. Optionally reassign automations to another mailbox.
 - [PUT /emails/api/mailboxes/{uuid}/activate](https://api.grinfi.io/openapi/mailboxes/activatemailbox.md): Enable a mailbox so it can send and sync emails.
 - [PUT /emails/api/mailboxes/{uuid}/deactivate](https://api.grinfi.io/openapi/mailboxes/deactivatemailbox.md): Disable a mailbox. It will stop sending and syncing emails.
 - [GET /emails/api/mailbox-errors](https://api.grinfi.io/openapi/mailboxes/listmailboxerrors.md): List mailbox send/sync errors for debugging. Shows errors with timestamps and details.
## Attachments

 - [GET /flows/api/attachments](https://api.grinfi.io/openapi/attachments/listattachments.md): List files uploaded to your team's attachment storage. Attachments can be referenced by UUID when sending LinkedIn messages, emails, or from automation message nodes.
 - [POST /flows/api/attachments](https://api.grinfi.io/openapi/attachments/uploadattachment.md): Upload a file (image, PDF, document) to attachment storage. Use `multipart/form-data`. Returns an attachment UUID that can be used in `attachments: [{ "uuid": "..." }]` when sending LinkedIn messages
 - [GET /flows/api/attachments/{uuid}](https://api.grinfi.io/openapi/attachments/getattachment.md)
 - [DELETE /flows/api/attachments/{uuid}](https://api.grinfi.io/openapi/attachments/deleteattachment.md)
## LinkedIn Browsers

 - [POST /browsers/api/linkedin-browsers/list](https://api.grinfi.io/openapi/linkedin-browsers/listlinkedinbrowsers.md): List all LinkedIn browser profiles with pagination.
 - [GET /browsers/api/linkedin-browsers/{id}](https://api.grinfi.io/openapi/linkedin-browsers/getlinkedinbrowser.md)
 - [PUT /browsers/api/linkedin-browsers/{id}](https://api.grinfi.io/openapi/linkedin-browsers/updatelinkedinbrowser.md)
 - [DELETE /browsers/api/linkedin-browsers/{id}](https://api.grinfi.io/openapi/linkedin-browsers/deletelinkedinbrowser.md)
 - [POST /browsers/api/linkedin-browsers](https://api.grinfi.io/openapi/linkedin-browsers/createlinkedinbrowser.md): Create a LinkedIn browser "seat" bound to a sender profile. This is step 2 of connecting a LinkedIn account without the user ever logging into Grinfi: 1. Create a sender profile — [`POST /flows/api/se
 - [POST /browsers/api/linkedin-browsers/{id}/generate-external-access-key](https://api.grinfi.io/openapi/linkedin-browsers/generatebrowseraccesskey.md): Mint a **public, no-auth Smart Login link** for a seat — the way an end user connects their LinkedIn account without a Grinfi login. Returns `external_access_key` and a `cloud_browser_url`; opening th
 - [POST /browsers/api/linkedin-browsers/{id}/run](https://api.grinfi.io/openapi/linkedin-browsers/runlinkedinbrowser.md): Resume a **previously logged-in** LinkedIn browser session that was intentionally stopped. **Do not call this during onboarding** — starting a never-logged-in seat forces `login_issue`. The backend st
 - [POST /browsers/api/linkedin-browsers/{id}/stop](https://api.grinfi.io/openapi/linkedin-browsers/stoplinkedinbrowser.md)
 - [POST /browsers/api/linkedin-browsers/{id}/set-proxy](https://api.grinfi.io/openapi/linkedin-browsers/setlinkedinbrowserproxy.md): Change the proxy configuration for a LinkedIn browser.
 - [POST /browsers/api/linkedin-browsers/{id}/share](https://api.grinfi.io/openapi/linkedin-browsers/sharelinkedinbrowser.md): Share a LinkedIn browser profile with another team member.
## Webhooks

 - [GET /integrations/api/webhooks](https://api.grinfi.io/openapi/webhooks/listwebhooks.md): List all webhooks configured in your account. Webhooks send HTTP requests to your target URL when specified events occur.
 - [POST /integrations/api/webhooks](https://api.grinfi.io/openapi/webhooks/createwebhook.md): Create a new webhook that fires on the specified event. Optionally add filters to narrow which contacts trigger the webhook.
 - [GET /integrations/api/webhooks/{uuid}](https://api.grinfi.io/openapi/webhooks/getwebhook.md): Retrieve full details of a webhook by UUID.
 - [PUT /integrations/api/webhooks/{uuid}](https://api.grinfi.io/openapi/webhooks/updatewebhook.md): Update one or more fields on an existing webhook. Only include the fields you want to change.
 - [DELETE /integrations/api/webhooks/{uuid}](https://api.grinfi.io/openapi/webhooks/deletewebhook.md): Permanently remove a webhook.
 - [POST /integrations/api/webhooks/test](https://api.grinfi.io/openapi/webhooks/testwebhook.md): Send a sample payload for the given event to a target URL and return the target's response — use it to verify connectivity and see the payload shape for an event. **Send the full webhook config**, not
