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

# Research a single contact

> Research one contact by searchResultId from contact search results or Contact enrich



## OpenAPI

````yaml https://gist.githubusercontent.com/JustinAlia/6ff38a671f5f79895444b77c57f3afff/raw/openapi.json post /contacts/research/single
openapi: 3.0.0
info:
  title: Seamless API
  description: >-
    [Privacy Policy](https://seamless.ai/policies/privacy-policy)


    In order to dramatically improve our offerings to customers, Seamless will
    be introducing a Public API

    which can be used to search Companies & Contacts, Enrich Lists, and offer
    integrations as an Endpoint for our

    customers.


    The API is build using [RESTful](https://en.wikipedia.org/wiki/REST)
    principles and is secured using OAuth 2.0 with the implicit grant flow.


    # Authentication


    ## API Key


    ### 1. **Register Your Application**

    To use the Seamless API, you need to register your application to obtain an
    API key.

    To create a new API key, go to [Seamless.AI |
    Settings](https://login.seamless.ai/settings/public-api) > API Key and click
    the *Create New Connection* button.

    Note: The Public API Connections menu will only appear if your account has
    access to the Public API.


    ### 2. **Use the Access Token**

    For all authenticated API requests, include the API key in the header:


    ```

    Token: API_KEY

    ```


    ## OAuth 2.0


    ### 1. **Register Your Application**


    Before integrating, you have to setup your client credentials.


    To create a new API client, go to [Seamless.AI |
    Settings](https://login.seamless.ai/settings/public-api) > OAuth
    Connections, and click the *Create New Connection* button.


    Note: The Public API Connections menu will only appear if your account has
    access to the Public API.


    - `client_id`

    - `client_secret`

    - `redirect_uri`


    You’ll use these to authenticate and obtain tokens.


    ---


    ### 2. **Obtain Authorization Code**


    Redirect the user to Seamless.AI's OAuth authorization endpoint:


    ```

    GET https://login.seamless.ai/oauth/authorize

    ```


    ### Query Parameters:


    | Name | Description |

    | --- | --- |

    | `client_id` | Your client ID |

    | `redirect_uri` | The URL users are redirected to |

    | `state` | (Optional) CSRF protection string |


    **Example URL**:


    ```

    GET
    https://login.seamless.ai/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=https://yourapp.com/callback

    ```


    Once the user authenticates, they will be redirected to your `redirect_uri`
    with a `code` parameter.

    If your `redirect_uri` contains any query parameters (such as `?foo=bar`),
    you must URL encode your `redirect_uri` for this step.


    ---


    ### 3. **Exchange Code for Access Token**


    ```

    POST https://api.seamless.ai/api/client/v1/oauth/accessToken

    ```


    ### Request Body (JSON):


    ```json

    {
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "redirect_uri": "https://yourapp.com/callback",
      "grant_type": "authorization_code",
      "code": "AUTHORIZATION_CODE_FROM_STEP_2"
    }

    ```


    ### Response:


    ```json

    {
      "token_type": "Bearer",
      "access_token": "ACCESS_TOKEN",
      "refresh_token": "REFRESH_TOKEN",
      "expires_in": 10800,
      "expires_at": "2026-06-25T12:00:00.000Z",
      "refresh_token_expires_in": 604800,
      "refresh_token_expires_at": "2026-07-02T12:00:00.000Z"
    }

    ```


    Access tokens expire after **180 minutes** by default. Integrations must use
    the `refresh_token` grant before expiry to obtain a new token pair. Existing
    long-lived tokens issued before this change remain valid until their
    original expiry.


    ---


    ### 4. **Use the Access Token**


    For all authenticated API requests, include the token in the header:


    ```

    Authorization: Bearer ACCESS_TOKEN

    ```


    ---


    ### 5. **Refreshing the Token**


    To refresh the access token:


    ```

    POST https://api.seamless.ai/api/client/v1/oauth/accessToken

    ```


    ### Request Body:


    ```json

    {
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "redirect_uri": "https://yourapp.com/callback",
      "grant_type": "refresh_token",
      "refresh_token": "YOUR_REFRESH_TOKEN"
    }

    ```


    ### Response:


    ```json

    {
      "token_type": "Bearer",
      "access_token": "NEW_ACCESS_TOKEN",
      "refresh_token": "NEW_REFRESH_TOKEN",
      "expires_in": 10800,
      "expires_at": "2026-06-25T12:00:00.000Z",
      "refresh_token_expires_in": 604800,
      "refresh_token_expires_at": "2026-07-02T12:00:00.000Z"
    }

    ```


    Each refresh rotates both the access and refresh tokens. Store the new
    `refresh_token` from every response.


    # Rate Limiting


    Rate limits are enforced at the **organization** level. All API usage for
    your Seamless organization counts against the same quota for each
    endpoint—limits are not applied separately per API key or per user.


    The default limit is **60 requests per minute** per endpoint. If you exceed
    the limit, the API responds with **429 Too Many Requests** and a JSON error
    body.


    Some endpoints may use different limits (for example, OAuth routes). Your
    organization may also have custom limits. The `X-RateLimit-Limit` header on
    each response always reflects the maximum number of requests allowed for
    that endpoint in the current rate limit window.


    Rate limit and remaining credits information will be returned in the
    response header of each request. The parameters are:


    | Name | Example | Description |

    | --- | --- | --- |

    | `X-RateLimit-Limit` | 60 | The maximum number of requests you're permitted
    to make in the current rate limit window for this endpoint. |

    | `X-RateLimit-Remaining` | 42 | The number of requests remaining in the
    current rate limit window. |

    | `X-RateLimit-Reset` | 1745587198 | The time at which the current rate
    limit window resets in epoch seconds. |

    | `X-PublicAPI-Credits` | 1000 | The number of credits remaining that can be
    used in requests. |
  version: 1.0.0
  x-logo:
    url: https://s3.amazonaws.com/seamless.ai-public/logos/logo-full-dark.svg
    altText: Seamless logo
    href: https://login.seamless.ai
  termsOfService: https://seamless.ai/policies/terms-of-use
servers:
  - url: https://api.seamless.ai/api/client/v1
    description: Seamless API
security:
  - OAuth2: []
  - ApiKeyAuth: []
tags: []
paths:
  /contacts/research/single:
    post:
      tags:
        - Contact Research
      summary: Research a single contact
      description: >-
        Research one contact by searchResultId from contact search results or
        Contact enrich
      operationId: researchSingleContact
      requestBody:
        required: true
        content:
          application/json:
            examples:
              searchResultId:
                summary: Contact research via searchResultId
                value:
                  searchResultId: searchResultId1
              contact:
                summary: Contact research via contact
                value:
                  contact:
                    contactName: John Doe
                    companyName: Acme Corp
              jobChange:
                summary: Contact research with job change
                value:
                  isJobChange: true
                  contact:
                    contactName: Jane Doe
                    companyName: Acme Corp
                    title: Software Engineer
            schema:
              type: object
              properties:
                searchResultId:
                  type: string
                  description: >-
                    A search result ID obtained from a prior /search/contacts
                    call. Provide either searchResultId or contact, not both.
                    Consumes one credit.
                  example: 11ad7a1c-9a63-30e0-a1de-cd9a766805ca
                contact:
                  allOf:
                    - type: object
                      properties:
                        contactName:
                          type: string
                          description: >-
                            Full name of the contact to research. Required when
                            using companyName or domain for identification.
                          example: John Doe
                        companyName:
                          type: string
                          description: >-
                            Name of the company the contact is associated with.
                            Use together with contactName.
                          example: Acme Corp
                        title:
                          type: string
                          description: >-
                            Job title of the contact. Used alongside contactName
                            and companyName when isJobChange is true to match
                            the correct job change record.
                          example: Software Engineer
                        domain:
                          type: string
                          description: >-
                            Company website domain. Use as an alternative to
                            companyName together with contactName.
                          example: acme.com
                        email:
                          type: string
                          description: >-
                            Email address of the contact. Can be used as a
                            standalone identifier without contactName or
                            companyName.
                          example: john.doe@acme.com
                        liProfileUrl:
                          type: string
                          description: >-
                            LinkedIn public profile URL. Can be used as a
                            standalone identifier.
                          example: https://www.linkedin.com/in/johndoe
                        liSalesNavUrl:
                          type: string
                          description: >-
                            LinkedIn Sales Navigator profile URL. Can be used as
                            a standalone identifier.
                          example: https://www.linkedin.com/sales/lead/ACoAAA...
                        liRecruiterUrl:
                          type: string
                          description: >-
                            LinkedIn Recruiter profile URL. Can be used as a
                            standalone identifier.
                          example: >-
                            https://www.linkedin.com/talent/search/profile/AEMAA...
                  description: >
                    Contact enrich request. Provide either searchResultId or
                    contact, not both. Must include one of the following
                    combinations:

                    - contactName and companyName (optionally include title when
                    using isJobChange)

                    - contactName and domain

                    - email

                    - liProfileUrl

                    - liSalesNavUrl

                    - liRecruiterUrl
                isJobChange:
                  type: boolean
                  description: >-
                    When set to true, triggers a job change research for the
                    provided contact. Must be used together with contact; cannot
                    be used with searchResultId.
                  default: false
                  example: false
                listIds:
                  type: array
                  description: >
                    IDs of the contact lists to add the newly saved contact to.
                    A contact that was already researched is not saved again, so
                    it is not added to the lists.

                    The lists must already belong to the authenticated user; an
                    unknown ID fails the research request, which reports the
                    error when you poll for it.
                  maxItems: 50
                  items:
                    type: integer
                  example:
                    - 1234
                    - 5678
                skipDeduplicationCheck:
                  type: boolean
                  description: >-
                    When true, research will not check for duplicate records
                    that you already researched recently, and perform a research
                    (which can result in credit usage)
                  default: false
      responses:
        '202':
          description: The request ID for research
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    description: >-
                      Indicates whether the research request was accepted
                      successfully.
                    example: true
                  requestId:
                    type: string
                    description: >-
                      The request ID for the contact research request. Use it to
                      poll for results via /contacts/research/poll.
                    example: 6Ei5iKuSHzJXvqjVPWiZ_
        '400':
          description: >-
            Neither or both of searchResultId and contact provided, or the
            contact is missing required properties
          content:
            application/json:
              schema:
                type: object
                required:
                  - message
                properties:
                  message:
                    description: A human readable error message
                    type: string
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                required:
                  - message
                properties:
                  message:
                    description: A human readable error message
                    type: string
        '422':
          description: Insufficient credits or missing license
          content:
            application/json:
              schema:
                description: Insufficient credits or missing license
                type: object
                properties:
                  msg:
                    type: string
                  code:
                    type: string
                  data:
                    type: object
                    properties:
                      productCategory:
                        type: string
                      additionalCreditsNeeded:
                        type: integer
        '500':
          description: Unexpected error
          content:
            application/json:
              schema:
                type: object
                required:
                  - message
                properties:
                  message:
                    description: A human readable error message
                    type: string
      security:
        - OAuth2: []
        - ApiKeyAuth: []
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://login.seamless.ai/oauth/authorize
          tokenUrl: https://api.seamless.ai/api/client/v1/oauth/accessToken
          scopes: {}
    ApiKeyAuth:
      type: apiKey
      name: Token
      in: header
      description: API key passed via the Token header.

````

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