openapi: 3.0.3
info:
version: ''
x-affinity-api-version: '2024-01-01'
contact:
email: [email protected]
name: Affinity Support
url: https://support.affinity.co
description: "# Introduction\n\nWelcome to Affinity API v2! This API provides a\
\ RESTful interface for building internal apps,\nautomated workflows, 3rd party\
\ integrations, and for connecting Affinity to the rest of your tech\nstack.\n\
\nThe legacy Affinity v1 API can be found [here](https://api-docs.affinity.co/).\
\ The v2 API is not at\nfeature parity with v1 - we are continuing to develop\
\ new v2 APIs to support all v1 functionality\nover time.\n\n**The Affinity APIs\
\ are only available on select license types.** See\n[this Help Center article](https://support.affinity.co/hc/en-us/articles/5563700459533-Getting-started-with-the-Affinity-API-FAQs)\n\
or contact your Customer Success Manager for more information.\n\n# Getting Started\n\
\nAll Affinity API endpoints use the base URL `https://api.affinity.co`. All v2\
\ endpoint paths start\nwith `/v2`. Requests must be sent over HTTPS.\n\nThe first\
\ few sections of these docs cover general information on the API. Each subsequent\
\ section\ncovers a set of API endpoints.\n\nEach endpoint is documented with\
\ its accepted request parameters, expected response shapes, and a\nsample request\
\ and response. The shape of a given response can vary depending on what \"type\"\
\ of\nobject or data is being returned. When this is the case, the response documentation\
\ will include a\ndropdown that can be used to select the \"type\" for which to\
\ display the response shape.\n\n## Authentication\n\nAffinity API v2 uses API\
\ keys and **bearer authentication** (this is an important difference from\nAffinity\
\ API v1's use of basic authentication).\n\nTo generate an API key, navigate to\
\ the Settings page in the Affinity web app. You will need the\n\"Generate an\
\ API key\" role-based permission controlled by your Affinity admin. See\n[this\
\ Help Center article](https://support.affinity.co/hc/en-us/articles/360032633992-How-to-obtain-your-API-Key)\n\
for full instructions on API key generation, and\n[this article](https://support.affinity.co/hc/en-us/articles/360015976732-Account-Level-Permissions)\n\
for more information on role-based permissions in Affinity.\n\nProvide your API\
\ key as your bearer authentication token to start making calls to Affinity API\
\ v2.\n\nWe support one API key per user in your Affinity account. Your API key\
\ is able to read data and\nperform actions in Affinity on your behalf, so keep\
\ it safe as you would a password.\n\n## Permissions\n\n### Overall Requirements\n\
\nYou must have the \"Generate an API key\" permission to be able to work with\
\ the Affinity API. Most\nusers in Affinity have this by default — Contact your\
\ Affinity admin if you are not able to generate\nan API key, and see\n[this article](https://support.affinity.co/hc/en-us/articles/360015976732-Account-Level-Permissions)\n\
for more information on role-based permissions in Affinity.\n\n### Resource-Level\
\ Permissions\n\nThe Affinity API respects sharing permissions that are set in-product.\
\ For example, if a given user\ndoes not have access to a list, note, or interaction\
\ in-product, they will not be able to see or\nmodify it via API.\n\n### Endpoint-Level\
\ Permissions\n\nMany API endpoints require endpoint-specific permissions in-product.\
\ These permissions, along with\nthe \"Generate an API key\" permission, are managed\
\ by your Affinity admin in the Settings page. In\nthe description of each endpoint\
\ you will see the required permissions needed.\n\n## Rate Limits\n\nThe Affinity\
\ API sets a limit on the number of calls that a user can make per minute, and\
\ that all\nthe users on an account can make per month. It also sets a reasonable\
\ limit on the number of\nconcurrent requests it will support from an account\
\ at one time.\n\nRequests to **both** Affinity API versions will count toward\
\ the one pool of requests allowed for a\nuser or account. Once a per-minute,\
\ monthly, or concurrent rate limit is hit, subsequent requests\nwill return an\
\ error code of 429. **We highly recommend designing your application to handle\
\ 429\nerrors.**\n\n### Per-Minute Limits (User-Level)\n\nTo help protect our\
\ systems, API requests will be halted at **900 per user, per minute.** We may\n\
also lower this limit on a temporary basis to manage API availability.\n\n###\
\ Concurrent Request Limits (Account-Level)\n\nTo protect our systems and manage\
\ availability across customers, we set a reasonable limit on\nconcurrent requests\
\ at the account level. Customers should not expect to hit this limit unless they\n\
are hitting the API with heavy operations from many concurrent threads at once.\n\
\n### Monthly Plan Tier Limits (Account-Level)\n\nThe overall number of requests\
\ you can make per month will depend on your account's plan tier.\n**This monthly\
\ account-level limit resets at the end of each calendar month.** Current rate\
\ limits\nby plan tier are:\n\n| Plan Tier | Calls Per Month |\n| ----------\
\ | --------------- |\n| Essentials | None |\n| Scale | 100k \
\ |\n| Advanced | 100k |\n| Enterprise | Unlimited\\* \
\ |\n\n\\*Per-Minute and Concurrent Request Limits still apply.\n\n### Rate\
\ Limit Headers\n\nAll API calls will return the following response headers with\
\ information about per-minute and\nmonthly limits:\n\n| Header \
\ | Description |\n| --------------------------------\
\ | ------------------------------------------------------- |\n| X-Ratelimit-Limit-User\
\ | Number of requests allowed per minute for the user |\n| X-Ratelimit-Limit-User-Remaining\
\ | Number of requests remaining for the user |\n| X-Ratelimit-Limit-User-Reset\
\ | Time in seconds before the limit resets for the user |\n| X-Ratelimit-Limit-Org\
\ | Number of requests allowed per month for the account |\n| X-Ratelimit-Limit-Org-Remaining\
\ | Number of requests remaining for the account |\n| X-Ratelimit-Limit-Org-Reset\
\ | Time in seconds before the limit resets for the account |\n\n## Pagination\n\
\nWhen an endpoint is expected to return multiple results, we break the results\
\ into pages to make\nthem easier to handle. To cycle forward through multiple\
\ pages of data, look for the `nextUrl`\nproperty in the `pagination` portion\
\ of an API response, and use it for your next request. See\nendpoint documentation\
\ for more information.\n\n## Filtering\n\nSome endpoints support a filtering\
\ language for flexible and powerful queries. This allows for the\ncreation of\
\ complex filter expressions using different operators and boolean logic in a\
\ single\nfilter string. The description of each endpoint will contain information\
\ on which filter properties\nand operators are supported.\n\n### Rules\n\n- Spaces\
\ are insignificant by default. For example, `field = hello` and `field=hello`\
\ are both\n valid.\n- If spaces are significant, they need to be inside double\
\ quotes, for example,\n `field = \"hello world\"`\n- Special characters need\
\ to be escaped with a backslash: `field=\"hello\\\" world\"` <br> Full list of\n\
\ special characters: `\\ * ~ ! & = > < $ ^ | \" ' ( ) ] [ /`\n- Use `&` and\
\ `|` for boolean operations: `foo = 1 | baz = 2 & bar = 3`. Boolean Algebra Logic\
\ is\n assumed: `&` takes precedence over `|`. When evaluating the condition\
\ above, `baz = 2 & bar = 3`\n will be computed first, and then the result will\
\ be `or`'ed with `foo=1`\n- Parentheses can be used to specify the order of operations.\
\ In the example above, to make sure\n that `foo = 1 | baz = 2` is evaluated\
\ first, parentheses must be placed\n `(foo = 1 | baz = 2) & bar = 3`\n\n###\
\ Grammar\n\n#### Simple Types\n\n| Definition | Property Type \
\ | Operator | Example \
\ |\n| ------------------------\
\ | ---------------------------------------------------- | -------- | -----------------------------------------------------------------------------------------\
\ |\n| exact match | all \
\ | = | content = “hello world” <br> content=hello \
\ |\n| starts with | text \
\ | =^ | content =^ he \
\ |\n\
| ends with | text \
\ | =$ | content =$ llo \
\ |\n| contains | text \
\ | =~ | content =~ lo \
\ |\n| greater\
\ than | int32, int64, float, double, decimal, date, datetime | \\\
> | count > 1 \
\ |\n| greater than or equal to | int32, int64, float, double,\
\ decimal, date, datetime | \\>= | content >= 1 \
\ |\n| less than \
\ | int32, int64, float, double, decimal, date, datetime | \\< | count\
\ < 1 \
\ |\n| less than or equal to | int32, int64, float, double, decimal,\
\ date, datetime | \\<= | content <= 1 \
\ |\n| is NULL | all\
\ | != \\* | content != \\\
* \
\ |\n| is not NULL | all \
\ | =\\* | content = \\* \
\ |\n| is empty | text \
\ | =\"\" | content = \"\"\
\ \
\ |\n| negation | all \
\ | ! | content != ”hello world” <br> !(content = ”hello world”)\
\ <br> !(content =^ “hello world”) |\n\n#### Collections (all types)\n\n| Definition\
\ | Operator | Example |\n| -------------------------\
\ | -------- | ------------------------------------ |\n| exact match with ordering\
\ | = | industries = [Healthcare,Fintech] |\n| contains all \
\ | =~ | industries =~ [Healthcare,Fintech] |\n| empty \
\ | =[] | industries =[] |\n| negation \
\ | ! | !(industries = [Healthcare,Fintech]) |\n\n## Error\
\ Codes\n\nHere is a list of the error codes the API will return if something\
\ goes wrong (see endpoint\ndocumentation for endpoint-specific errors):\n\n|\
\ Error Code | Meaning \
\ \
\ |\n| ----------\
\ | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\
\ |\n| 400 | Bad Request — See endpoint documentation for more information.\
\ \
\ |\n| 401 \
\ | Unauthorized — Your API key is invalid. \
\ \
\ |\n| 403 |\
\ Forbidden — Insufficient rights to a resource. \
\ \
\ |\n| 404 | Not Found\
\ — Requested resource does not exist. See endpoint documentation for more information.\
\ \
\ |\n| 405 | Method Not Allowed — The method\
\ being used is not supported for this resource. \
\ \
\ |\n| 422 | Unprocessable Entity — Malformed parameters\
\ supplied. This can also happen in cases the parameters supplied logically cannot\
\ complete the request. In this case, an appropriate error message is delivered.\
\ |\n| 429 | Too Many Requests — You have exceeded the rate limit. \
\ \
\ |\n| 500\
\ | Internal Server Error — We had a problem with our server. Try again\
\ later. \
\ |\n| 503 \
\ | Service Unavailable — This shouldn't generally happen. Contact us if you encounter\
\ this error. \
\ |\n\n## Beta Endpoints\n\nYou’ll\
\ notice in our documentation that some endpoints will be marked as BETA. These\
\ endpoints are\nnewly released and will eventually progress to General Availability\
\ (GA). While an endpoint is in\nBETA there are some important things to consider:\n\
\n- The development of this endpoint may still be in progress. This means new\
\ capabilities, request\n parameters, response data, and performance improvements\
\ may be adjusted over time. Because of\n this, breaking changes may occur to\
\ the endpoint WITHOUT notice or versioning.\n- As this is an early release, bug\
\ fixes may still be ongoing as well, and we encourage you to\n report bugs to\
\ [[email protected]](mailto:[email protected]).\n- In addition, your feedback\
\ around the capabilities of the endpoint are highly valuable, please\n reach\
\ out to your CSM to provide feedback to our product team.\n\n# Data Model\n\n\
## The Basics\n\nThe three top-level objects in Affinity are **Persons, Companies,\
\ and Opportunities**. (Note:\nCompanies are called Organizations in the Affinity\
\ web app.) These have profiles in the Affinity web\napp and can be added to Lists.\n\
\nA **List** is a spreadsheet-like collection of rows tied to Persons, Companies,\
\ or Opportunities.\n\n- Each row on a List is a **List Entry**. A List Entry\
\ contains data and metadata about a given\n Person, Company, or Opportunity\
\ in the context of a List. This includes list-specific field data,\n and information\
\ about who added the row to the List and when.\n- A given entity can be added\
\ to a List more than once. These List Entries can have different\n List-specific\
\ field data and List Entry-level metadata.\n\nEach column on a List maps to a\
\ **Field**. Fields show up within Affinity profile pages, extensions,\nand integrations.\
\ There are two categories of fields:\n\n- **List-specific fields** are scoped\
\ to a single List. In the API, their data can only be accessed\n through the\
\ List Entry resource.\n- **Global fields** belong to entities directly. These\
\ can include default fields, fields created by\n you, enrichment fields, or\
\ relationship intelligence fields. They can be accessed through the\n Person/Company/Opportunity\
\ resources and the List Entry resource.\n\n## Working with Field Data\n\n###\
\ Field Types and IDs\n\nHere is a deeper look at the types of Fields in Affinity,\
\ differentiated by the scope and source of\ntheir data:\n\n| Field Type\
\ | Description \
\ \
\ | Example Fields \
\ \
\ | Field ID Pattern \
\ \
\ |\n| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------\
\ | -----------------------------------------------------------------------------------------------------------------------------------------------------------\
\ | --------------------------------------------------------------------------------------------------------------------------------------------\
\ |\n| `enriched` | Firmographic, funding, and people Fields\
\ populated by Affinity. These can be \"Affinity Data\" Fields or come from distinct\
\ data partners. | \"Affinity Data: Description\", \"Dealroom:\
\ Number of Employees\" \
\ | A string representing the enrichment\
\ source, followed by the field name, e.g. `affinity-data-description` or `dealroom-number-of-employees`.\
\ |\n| `list` | Fields that are specific to the context of\
\ a given list. These can only be accessed through `*/list-entries` endpoints\
\ in this version of the API. | Default \"Status\" and \"Amount\" columns,\
\ custom columns that pertain to a given List of deals or founders \
\ | `field-`, followed by a unique integer,\
\ e.g. `field-1234` \
\ |\n| `global` | Fields that persist\
\ across an Affinity account and are not list-specific. \
\ | \"My Firm's Founder\
\ Scoring Column\" \
\ | `field-`, followed\
\ by a unique integer, e.g. `field-1234` \
\ |\n| `relationship-intelligence`\
\ | Fields populated by Affinity from users' email and calendar data that provide\
\ insight into your firm's relationship with a given Person/Company/Opportunity.\
\ | \"Source of Introduction\", \"First Email\", \"Last Email\", \"First Event\"\
, \"Last Event\", \"Next Event\", \"First Chat Message\", \"Last Chat Message\"\
, \"Last Contact\" | A string similar to the field's name in-product, e.g. `source-of-introduction`\
\ |\n\n### Field\
\ Value Types\n\nField data can take a variety of shapes. These value types are\
\ described in the Affinity Help Center\n[here](https://support.affinity.co/hc/en-us/articles/115001608232-How-to-create-a-new-column-in-a-list).\n\
Here is a list of the same value types, as represented in this API. Notice how\
\ array types end with\n`-multi`:\n\n| Single Type | Array Type \
\ |\n| ------------------- | ------------------------- |\n| `text` \
\ | Not supported in Affinity |\n| `number` | `number-multi`\
\ |\n| `datetime` | Not supported in Affinity |\n| `location`\
\ | `location-multi` |\n| `dropdown` | `dropdown-multi`\
\ |\n| `ranked-dropdown` | Not supported in Affinity |\n| `person`\
\ | `person-multi` |\n| `company` | `company-multi`\
\ |\n| `filterable-text`\\* | `filterable-text-multi`\\* |\n\n\\*Note\
\ that `filterable-text` and `filterable-text-multi` are special types that operate\
\ similarly\nto `dropdown` and `dropdown-multi`. They are reserved for Affinity-populated\
\ Fields, and users\ncannot create Fields with these types.\n\nWhen an array-typed\
\ value has no data in it, the API will return `null` (rather than an empty\n\
array).\n\n### Retrieving Field Data\n\nTo retrieve field data on companies, persons,\
\ or opportunities, call GET `/v2/companies`, GET\n`/v2/persons`, or one of our\
\ GET `*/list-entries` endpoints. (Note that Opportunities only have\nlist-specific\
\ Fields, so all their field data will live on the `*/list-entries` endpoints.)\
\ For most\nof these endpoints, you will need to specify the Fields for which\
\ you want data returned via the\n`fieldIds` or `fieldTypes` parameter — Otherwise,\
\ entities will be returned without any field data\nattached.\n\nThe GET `/v2/companies`\
\ and `/v2/persons` endpoints can return entities with enriched, global, and\n\
relationship intelligence field data attached, but do not support list-specific\
\ field data. **To get\ncomprehensive field data including list-specific field\
\ data on Companies and Persons, use the GET\n`*/list-entries` endpoints.**\n\n\
### Specifying Desired Fields (Field Selection)\n\nAs mentioned above, you will\
\ need to specify the Fields (either by ID or by Type) for which you want\ndata\
\ returned when using the following endpoints:\n\n- GET `/v2/companies`\n- GET\
\ `/v2/companies/{id}`\n- GET `/v2/persons`\n- GET `/v2/persons/{id}`\n- GET `/v2/lists/{listId}/list-entries`\n\
\nEach of these endpoints has a `fieldIds` parameter that accepts an array of\
\ Field IDs, and a\n`fieldTypes` parameter that accepts an array of Field Types.\
\ Use the GET `*/fields` endpoints to get\nField IDs, Field Types, and other Field-level\
\ metadata:\n\n- Call GET `/v2/companies/fields` and `/v2/persons/fields` to get\
\ a list of the enriched, global,\n and relationship intelligence (AKA non-list-specific)\
\ Fields that exist on Companies and Persons,\n respectively. These are the Fields\
\ whose values are available to pull via GET `/v2/companies`, GET\n `/v2/companies/{id}`,\
\ GET `/v2/persons`, and `/v2/persons/{id}`.\n- Call GET `/v2/lists/{listId}/fields`\
\ to get a list of the enriched, global, relationship\n intelligence, **and list-specific**\
\ Fields for a given List. These are the Fields whose values are\n available\
\ to pull via GET `/v2/lists/{listId}/list-entries`.\n\nThe following endpoints\
\ don't require field selection:\n\n- GET `/v2/lists/{listId}/saved-views/{viewId}/list-entries`\
\ — See below. This endpoint returns just\n the field data that has been pulled\
\ into the given Saved View via UI.\n- GET `/v2/companies/{id}/list-entries` and\
\ GET `/v2/persons/{id}/list-entries` — These endpoints\n return comprehensive\
\ field data for the given person or company in the context of each List Entry.\n\
\n### Saved Views\n\nA Saved View allows a user to configure the Fields they want\
\ to see in the UI for a given List, and\nset filters and sorts on the rows on\
\ that List. A List can have multiple Saved Views. In the context\nof this API,\
\ Saved Views can be useful for specifying the exact Fields for which data is\
\ needed. The\n`*/saved-views/{viewId}/list-entries` endpoint also respects the\
\ filters that have been set on the\ngiven Saved View in the Affinity web app.\
\ (It does not, however, respect sorts just yet.)\n\n### Partner Data Restrictions\n\
\nThis API supports pulling data from\n[Affinity Data](https://support.affinity.co/hc/en-us/articles/360058255052-Affinity-Data)\
\ fields and\nselect\n[Dealroom fields](https://support.affinity.co/hc/en-us/articles/6106558518797-Dealroom-co-data-in-Affinity#h_01G2N22SVH7TJR3DJV3NQDE9HQ).\n\
Due the agreements we have with some of our data partners, the API does not expose\
\ data from the\nfollowing sources:\n\n- Crunchbase, including Crunchbase UUID\n\
- Pitchbook\n- [Dealroom \"exclusive\" fields](https://support.affinity.co/hc/en-us/articles/6106558518797-Dealroom-co-data-in-Affinity#h_01G2N22YEAZJ5TC1X9ENKZFWF5)\n\
\n## Nested Associations\n\nSome GET endpoints return \"association\" data under\
\ `fields`. For example, the Persons GET endpoints\nreturn data about which Companies\
\ a Person is associated with in Affinity. The Opportunities GET\nendpoints return\
\ similar data about associated Companies and Persons. The List Entries GET endpoints\n\
also return this data for Person and Opportunity List Entries.\n\nThe API truncates\
\ these nested arrays of Persons or Companies **at 100 entries**. For example,\
\ if an\nOpportunity is associated with 200 Persons in Affinity, only 100 of those\
\ Persons will be returned\nby the GET `/opportunities` or `/opportunities/{id}`\
\ endpoint.\n\n# User Guides\n\n## A Tour of Our GET Endpoints\n\n| Desired Data\
\ | Relevant Endpoints \
\ \
\ \
\ \
\ \
\ | Notes \
\ |\n| -----------------------------------------------------------\
\ | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\
\ | -----------------------------------------------------------------------------------------\
\ |\n| Company/Person/Opportunity rows from a List | Grab the\
\ List’s ID from its URL in the Affinity web app, then hit GET `/v2/lists/{listId}/list-entries`\
\ \
\ \
\ \
\ | Data returned will be restricted to the rows on the requested List\
\ |\n| Company/Person/Opportunity rows from a Saved View\
\ | In the Affinity web app, navigate to a List and [create a Saved\
\ View](https://support.affinity.co/hc/en-us/articles/115001508572-How-to-leverage-saved-views-within-a-list)\
\ with the desired field data and filters on it. Grab the List and Saved View\
\ IDs from the web app URL, then hit GET `/v2/lists/{listId}/saved-views/{viewId}/list-entries`\
\ | Data returned will be restricted to the rows and columns on the requested\
\ Saved View |\n| Full rolodex of Companies or Persons in Affinity \
\ | GET `/v2/companies`, GET `/v2/persons` \
\ \
\ \
\ \
\ | Data from list-specific Fields\
\ will not be returned |\n| All the rows\
\ for a given Company or Person across all Lists | GET `/v2/companies/{id}/list-entries`,\
\ GET `/v2/persons/{id}/list-entries` \
\ \
\ \
\ |\
\ \
\ |\n| Metadata on Fields, including Field IDs \
\ | GET `/v2/companies/fields`, GET `/v2/persons/fields`, GET `/v2/lists/{listId}/fields`\
\ \
\ \
\ \
\ | Metadata on list-specific Fields will only be\
\ returned by GET `/v2/lists/{listId}/fields` |\n| Metadata on Lists or Saved\
\ Views | GET `/v2/lists`, GET `/v2/lists/{listId}/saved-views`\
\ \
\ \
\ \
\ | \
\ \
\ |\n| Opportunity data | GET `/v2/opportunities`\
\ will only return Opportunity names and List IDs. For comprehensive Opportunity\
\ data, hit GET `/v2/lists/{listId}/list-entries` for an Opportunity List \
\ \
\ \
\ | \
\ |\n\nTip: The ID for a List, Saved View, Person,\
\ Company, or Opportunity can always be found in its\nAffinity web app URL.\n\n\
# Changelog\n\n## May 14th, 2025\n\n- Renamed all path parameters named simply\
\ \"id\" to a more descriptive name (eg. \"personId\"). This\n will not have\
\ any effect on the API at runtime, but may impact code relying on the OpenAPI\
\ spec\n doing type generation.\n\n## April 9th, 2025\n\n- The following endpoints\
\ are no longer in BETA:\n\n| Method | URL \
\ | Summary \
\ |\n| ------ | ----------------------------------------------------------------\
\ | ------------------------------------------------- |\n| GET | `/v2/lists/{listId}/list-entries/{listEntryId}`\
\ | Get a single List Entry on a List |\n| GET\
\ | `/v2/lists/{listId}/list-entries/{listEntryId}/fields` | Get\
\ field values on a single List Entry |\n| PATCH | `/v2/lists/{listId}/list-entries/{listEntryId}/fields`\
\ | Perform batch operations on a list entry's
# --- truncated at 32 KB (372 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/affinity/refs/heads/main/openapi/affinity-v2-openapi.yml