CRED Enterprise API Documentation

Integration guide for the CRED Commercial Platform's GraphQL API, covering authentication, API key management, filtering, and schema reference.

Commercial Data Platform – Integration Guide

1. Overview

The CRED Commercial Platform exposes a secure, high-availability GraphQL API designed for enterprise-scale data enrichment, identity resolution, and commercial intelligence workflows.

This guide provides an end-to-end implementation blueprint covering:

  • Authentication
  • API key lifecycle management
  • Filtering and search capabilities
  • Schema reference

This documentation is optimized for:

  • Platform engineering teams
  • Solution architects
  • Enterprise IT stakeholders

2. Environments

EnvironmentBase URLPurpose
Productionhttps://api.external.credplatform.com/graphqlLive datasets, production workloads
Staginghttps://api-staging.external.credplatform.com/graphqlLive datasets, staging rate limits for testing

All functionality is consistent across environments except dataset size and SLA guarantees.

3. Authentication & Access Control

The platform supports a two-step authentication model designed for enterprise governance.

3.1 User Authentication (Login)

First, authenticate with your credentials to obtain a JWT token.

Mutation:

mutation AuthenticateUser($input: AuthenticateUserInput!) {
  authenticateUser(input: $input) {
    token
  }
}

Variables:

{
  "input": {
    "email": "[email protected]",
    "password": "your_password"
  }
}

Response:

{
  "data": {
    "authenticateUser": {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
  }
}

3.2 API Key Creation

Use the JWT token from authentication to create an API key.

HTTP Header:

Authorization: Bearer <JWT_TOKEN>

Mutation:

mutation CreateApiKey($input: CreateApiKeyInput!) {
  createApiKey(input: $input)
}

Note: The expiresInDays field is optional. If not specified, the API key defaults to 1 year (365 days) validity (see Rate Limiting & Governance for details).

Variables:

{
  "input": {
    "name": "My API Key",
    "expiresInDays": 30
  }
}

Example without expiration (uses default 1 year):

{
  "input": {
    "name": "My API Key"
  }
}

Response:

{
  "data": {
    "createApiKey": "cred_xxxxx..."
  }
}

!!! warning "API Key Security" API keys are shown only once — store securely.

4. Authorization for API Requests

Endpoint: POST /graphql

HTTP

Authorization: Bearer cred_<YOUR_API_KEY>
Content-Type: application/json

5. Filter Fields

Filter Syntax

Every filter field takes a list of filter objects, each shaped as:

{ values: [ ... ], comparison: IS_ANY_OF }
  • comparison is an enum (SearchComparisonType) — see Comparison Operators. Because filters are supplied via a GraphQL variable (see below), comparison is written as a JSON string ("IS_ANY_OF").
  • values is always a list, even for a single value.

Important — passing filters. Filters must be supplied as a GraphQL variable named exactly searchFilters (likewise topMarkets / officeLocation for companies). Inline object literals written directly in the query fail at the upstream service (400 Bad Request / INTERNAL_SERVER_ERROR) — the gateway applies its filter transformation only when the variable name is exactly searchFilters. This was confirmed against staging on 2026-06-29; see the verified shapes in Section 6.

Use these fields in searchFilters:

Comparison Operators

  • IS_ANY_OF - Matches any of the provided values (default for inclusion filters)
  • IS_NOT_ANY_OF - Excludes any of the provided values
  • IS_ALL_OF - Matches all of the provided values
  • BETWEEN - Matches values within a range (requires 2 values)
  • MORE_THAN - Greater than
  • MORE_OR_EQUALS_THAN - Greater than or equal to
  • LESS_THAN - Less than
  • LESS_OR_EQUALS_THAN - Less than or equal to

Note — boolean fields. For boolean filters (isExclusive, isEstimate), use IS_ANY_OF. The SearchComparisonType enum also defines a bare IS member, but the examples in this guide standardize on IS_ANY_OF for consistency with every other filter.

Pagination

All connection queries use cursor-based pagination. There is no first or limit argument — page size is controlled by the server (Staging returns 1 result per call).

Each response includes:

  • totalCount — total number of matching records
  • edges[].cursor — the cursor for that individual record
  • pageInfo.hasNextPage — whether more results exist
  • pageInfo.endCursor — the cursor to request the next page

To fetch the next page, pass the previous response's endCursor into the after argument:

query Companies($searchFilters: InputCompanySearchFilters, $after: String) {
  companiesConnection(after: $after, searchFilters: $searchFilters) {
    edges {
      cursor
      node { id name }
    }
    pageInfo { hasNextPage endCursor }
  }
}

Variables:

{
  "after": "PREVIOUS_END_CURSOR",
  "searchFilters": {
    "keywords": [{ "values": ["software"], "comparison": "IS_ANY_OF" }]
  }
}

Person Filters (InputPersonsSearchFilters)

Identity:

  • identity - Search by name or role
  • name - Search by full name

Demographics:

  • age - Filter by age range
  • birthDate - Filter by birth date
  • gender - Filter by gender

Location:

  • location - Filter by location
  • country - Filter by country
  • regionId - Filter by region ID

Salary:

  • salary - Filter by salary (maps to grossSalary)
  • grossSalary - Filter by gross salary
  • netSalary - Filter by net salary

Skills & Education:

  • skills - Filter by skills
  • educationLevel - Filter by education level

Other:

  • languageIds - Filter by language IDs

Company Connection Filters

searchFilters (InputCompanySearchFilters)

  • keywords - Text-based search across company data (filter list; values are strings, e.g. ["software development"])
  • country - Filter by country (accepts country names or IDs: ["United States", "USA"] or [234])
  • headquarters - Filter by headquarters location (accepts location names or IDs: ["Silicon Valley"] or [234])
  • industry - Filter by industry. values are Industry enum members (e.g. Accounting, Aerospace___Defense, AI___Machine_Learning_Services), not free-text like "IT". Query the Industry enum via introspection for the full list (415 members).
  • location - Filter by location (accepts location names or IDs: ["New York"] or [234])
  • region - Filter by region (accepts region names or IDs: ["California"] or [1])
  • numberOfEmployees - Filter by number of employees (integer)
  • employeeCount - Filter by number of employees - friendly name (integer, can be used with BETWEEN)
  • revenue - Filter by revenue (integer, can be used with BETWEEN)

topMarkets

Filter companies by their top markets (regions where they operate). Accepts region names (e.g., ["United States", "France"]). Uses IS_ANY_OF (default) or IS_NOT_ANY_OF comparison.

officeLocation

Filter companies by office locations (regions where they have offices). Accepts region names (e.g., ["United States", "France"]). Uses IS_ANY_OF (default) or IS_NOT_ANY_OF comparison.

Note: Both topMarkets and officeLocation accept region names as strings, which are automatically converted to internal region IDs. The comparison field is optional and defaults to IS_ANY_OF if not specified.

Deal Connection Filters

searchFilters (InputDealSearchFilters)

Deal Identification:

  • id - Filter by deal ID (string)
  • title - Filter by deal title (string search)
  • type - Filter by deal type. values are DealType enum members: SPONSORSHIP, MEDIA, FULL_DEAL, RELATIONSHIP.
  • status - Filter by deal status. values are DealStatus enum members: ACTIVE, PAST, FUTURE.

Dates & Duration:

  • announcedDate - Filter by announcement date (date range)
  • startDate - Filter by start date (date range)
  • endDate - Filter by end date (date range)
  • dealLength - Filter by deal length/duration (integer range)

Financial:

  • annualValue - Filter by annual value (integer range)
  • totalValue - Filter by total value (integer range)
  • isEstimate - Filter by whether the value is estimated (boolean)

Deal Terms:

  • isExclusive - Filter by exclusivity (boolean)
  • renewalOption - Filter by renewal option type. values are DealRenewalOptionType enum members: NEW, CONFIRMED, RENEWAL.

Buyer Company Filters:

  • buyerCompanyIds - Filter by buyer company IDs (integer range)
  • buyerCompanyKeywords - Filter by buyer company keywords (string)
  • buyerCompanyNormalizedKeywords - Filter by buyer company normalized keywords (string)
  • buyerCompanyCategoryId - Filter by buyer company category ID (integer)
  • buyerCompanyRegionId - Filter by buyer company region ID (integer)
  • buyerCompanyRevenue - Filter by buyer company revenue (big integer range)
  • buyerNormalizedIndustryId - Filter by buyer normalized industry ID (string)
  • buyerParentCompanyId - Filter by buyer parent company ID (integer)

Seller Company Filters:

  • sellerCompanyIds - Filter by seller company IDs (integer range)
  • sellerCompanyKeywords - Filter by seller company keywords (string)
  • sellerCompanyNormalizedKeywords - Filter by seller company normalized keywords (string)
  • sellerCompanyCategoryId - Filter by seller company category ID (integer)
  • sellerCompanyRegionId - Filter by seller company region ID (integer)
  • sellerNormalizedIndustryId - Filter by seller normalized industry ID (string)
  • sellerParentCompanyId - Filter by seller parent company ID (integer)

Persons & Sports:

  • sellerPersonIds - Filter by seller person IDs (integer range)
  • sportId - Filter by sport ID (integer range)

sorters

Sort deal results by field in ascending (ASC) or descending (DESC) order.

Note — sorters uses [JSONObject!] intentionally (confirmed via introspection). Unlike searchFilters, which must be passed as a typed variable for gateway filter-transformation to work, the gateway does not expose a dedicated sorter input type in the current schema version. sorters therefore accepts a generic JSON object list (e.g. [{ "field": "announcedDate", "direction": "DESC" }]). The searchFilters-variable-name constraint described in the filter-syntax section does not apply to sorters.

6. Examples

Filters are passed as GraphQL variables — the inline object-literal form fails at the upstream service (see the verification note at the top of this guide). Each example below shows the query and its accompanying Variables block.

Person Search

query Persons($searchFilters: InputPersonsSearchFilters) {
  personsConnection(searchFilters: $searchFilters) {
    edges {
      node {
        id
        name
        firstName
        lastName
        skills
        gender
        categoryIds
        age
        languages {
          id
          name
        }
        identifiers {
          name
          value
        }
        salary {
          grossSalary {
            value
            currency
            multiplier
            isVerified
            localCurrency
            localCurrencyValue
            localCurrencyValueMultiplier
          }
          grossSalaryLowerRange {
            value
            currency
            multiplier
            isVerified
            localCurrency
            localCurrencyValue
            localCurrencyValueMultiplier
          }
          grossSalaryUpperRange {
            value
            currency
            multiplier
            isVerified
            localCurrency
            localCurrencyValue
            localCurrencyValueMultiplier
          }
        }
      }
      cursor
    }
    totalCount
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

Variables:

{
  "searchFilters": {
    "identity": [{ "values": ["John"], "comparison": "IS_ANY_OF" }],
    "gender": [{ "values": ["MALE", "FEMALE"], "comparison": "IS_ANY_OF" }],
    "skills": [{ "values": ["JavaScript", "TypeScript"], "comparison": "IS_ANY_OF" }],
    "educationLevel": [{ "values": ["POSTGRADUATE_MASTERS", "PHD"], "comparison": "IS_ANY_OF" }],
    "salary": [{ "values": [50000000, 500000000], "comparison": "BETWEEN" }]
  }
}

Retrieving Contact Data (Email)

query ContactExample {
  contactsConnection {
    totalCount
    edges {
      cursor
      node {
        id
        name
        firstName
        lastName
        email
        emails
        company { id name }
        person { id name }
      }
    }
    pageInfo { hasNextPage endCursor }
  }
}

Company Search

query Companies(
  $topMarkets: [InputTopMarketsFilter!]
  $officeLocation: [InputOfficeLocationFilter!]
  $searchFilters: InputCompanySearchFilters
) {
  companiesConnection(
    topMarkets: $topMarkets
    officeLocation: $officeLocation
    searchFilters: $searchFilters
  ) {
    edges {
      node {
        id
        name
        websiteUrl
        parentCompanyId
        isPublic
        hasSubsidiary
        imageUrl
        marketCap {
          value
          currency
          multiplier
          isVerified
          localCurrency
          localCurrencyValue
          localCurrencyValueMultiplier
        }
        marketingBudget {
          value
          currency
          multiplier
          isVerified
          localCurrency
          localCurrencyValue
          localCurrencyValueMultiplier
        }
        fundingRaised {
          value
          currency
          multiplier
          isVerified
          localCurrency
          localCurrencyValue
          localCurrencyValueMultiplier
        }
        revenue {
          value
          currency
          multiplier
          isVerified
          localCurrency
          localCurrencyValue
          localCurrencyValueMultiplier
        }
        industry {
          id
          name
        }
        sector {
          id
          name
        }
        country {
          id
          name
          imageUrl
          alpha1Code
          alpha2Code
          alpha3Code
        }
        headquarters
        description
        ticker
        exchange
        foundedYear
        lastFundingDate
        numberOfEmployees
      }
    }
  }
}

Variables:

{
  "topMarkets": [{ "values": ["United States", "Canada"], "comparison": "IS_ANY_OF" }],
  "officeLocation": [{ "values": ["China"], "comparison": "IS_NOT_ANY_OF" }],
  "searchFilters": {
    "keywords": [{ "values": ["software development"], "comparison": "IS_ANY_OF" }],
    "revenue": [{ "values": [1000000000, 5000000000], "comparison": "BETWEEN" }],
    "employeeCount": [{ "values": [100, 1000], "comparison": "BETWEEN" }],
    "industry": [{ "values": ["AI___Machine_Learning_Services"], "comparison": "IS_ANY_OF" }],
    "country": [{ "values": ["United States"], "comparison": "IS_ANY_OF" }]
  }
}

industry values are Industry enum members (not free text). keywords is a filter list, not a bare string. The searchFilters portion above is confirmed working against staging (a query filtering industry: AI___Machine_Learning_Services returned live company data, e.g. Amazon).

Unverified: topMarkets / officeLocation with region names returned userCompanyId is required from the locale service for the API-key principal on staging, so region-name → region-ID resolution could not be confirmed end-to-end in this session. The arguments themselves are valid schema (InputTopMarketsFilter / InputOfficeLocationFilter, comparison of type InclusionComparisonType = IS_ANY_OF / IS_NOT_ANY_OF).

Deal Search

query Deals($searchFilters: InputDealSearchFilters, $sorters: [JSONObject!]) {
  dealsConnection(searchFilters: $searchFilters, sorters: $sorters) {
    edges {
      node {
        id
        title
        description
        type
        sponsorType
        announcedDate
        announcedDateSource
        startDate
        startDateSource
        endDate
        isEstimate
        isExclusive
        renewalOption
        totalDigitalImpressions
        annualValue {
          value
          currency
          multiplier
          isVerified
          localCurrency
          localCurrencyValue
          localCurrencyValueMultiplier
        }
        totalValue {
          value
          currency
          multiplier
          isVerified
          localCurrency
          localCurrencyValue
          localCurrencyValueMultiplier
        }
        buyerCompanies {
          id
          name
        }
        buyerCompanyIds
        buyerCompanyNames
        sellerCompanies {
          id
          name
        }
        sellerCompanyIds
        sellerCompanyNames
        sellerPersonIds
        sponsoredPersons {
          id
          name
        }
        sports {
          id
          name
        }
      }
      cursor
    }
    totalCount
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

Variables:

{
  "searchFilters": {
    "type": [{ "values": ["SPONSORSHIP", "MEDIA"], "comparison": "IS_ANY_OF" }],
    "status": [{ "values": ["ACTIVE"], "comparison": "IS_ANY_OF" }],
    "annualValue": [{ "values": [1000000, 10000000], "comparison": "BETWEEN" }],
    "isExclusive": [{ "values": [true], "comparison": "IS_ANY_OF" }],
    "buyerCompanyKeywords": [{ "values": ["Nike", "Adidas"], "comparison": "IS_ANY_OF" }]
  },
  "sorters": [{ "field": "announcedDate", "direction": "DESC" }]
}

Note: type and status values are enum members — DealType is SPONSORSHIP / MEDIA / FULL_DEAL / RELATIONSHIP (there is no ENDORSEMENT), and DealStatus is ACTIVE / PAST / FUTURE.

Unverified: The full combined payload above (multiple searchFilters plus sorters) returned a transient 502 Bad Gateway from the deals upstream on staging during testing and could not be confirmed end-to-end. The variable form itself is confirmed working for dealsConnection — a searchFilters variable filtering on type: SPONSORSHIP returned live data (totalCount 478,881). The sorters argument is typed [JSONObject!] in the schema (confirmed via introspection), but its runtime behavior and the date format/range fields (announcedDate etc.) were not verifiable in this session.

Contact Search

contactsConnection is also available. It uses a different argument shape from the other connections:

  • filters: InputGetContactFilters
  • personSearchFilters: JSONObject
  • sortBy: ContactSortBy, personSortBy: PersonOrderBy, sortOrder: SortOrder
  • after: String (pagination)

personSearchFilters typing note: Unlike personsConnection which exposes InputPersonsSearchFilters, the contactsConnection argument personSearchFilters has no dedicated typed input schema and is typed as a bare JSONObject scalar (confirmed via introspection). The gateway does not apply the same searchFilters variable-name transformation here. Because it is an untyped JSONObject passthrough, its accepted shape is not enforced by the schema and has not been verified end-to-end; for person-style filtering prefer the typed filters: InputGetContactFilters argument.

The filters argument (InputGetContactFilters) exposes ID/email/query-style fields rather than the nested { values, comparison } filter objects used elsewhere. Confirmed fields include:

  • contactIds, personIds, companyIds, noCompanyIds, opportunityIds, userId, importId, collectionId — lists of Int
  • emailString
  • queryString (free-text search)
  • filterTypeContactFilterType enum
  • matchingStatus — list of EntityMatchingStatus enum
  • syncSourceType — list of SyncSourceType enum
  • syncSourceNameWithSyncIssues — list of ImportSourceTypeEnum
  • fromCreatedAt, toCreatedAt, fromUpdatedAt, toUpdatedAtTimestamp
  • updatedInLastHoursFloat
  • isContact, isCrm, hasSyncIssues, onlyInCollections, isDeleted, includeBlacklistedBoolean

7. GraphQL Playground

Creating API Keys

{
  "Authorization": "Bearer <CRED_JWT_TOKEN>"
}

Running Queries

{
  "Authorization": "Bearer cred_<YOUR_API_KEY>"
}

8. API Schema Reference

8.1 Company Object

FieldDescription
idUnique company ID
nameName of the company
imageUrlLogo or brand image
websiteUrlPublic website
descriptionCorporate description
headquartersHQ location
tickerStock ticker symbol
exchangeExchange code
foundedYearFounding year
lastFundingDateDate of last funding round
isPublicPublic/private flag
hasSubsidiarySubsidiary flag
parentCompanyIdParent entity ID
numberOfEmployeesNumber of employees
industry.idIndustry identifier
industry.nameIndustry name
sector.idSector identifier
sector.nameSector name
country.idCountry identifier
country.nameCountry name
country.imageUrlCountry flag image URL
country.alpha1CodeISO 3166-1 alpha-1 code (e.g., "US")
country.alpha2CodeISO 3166-1 alpha-2 code
country.alpha3CodeISO 3166-1 alpha-3 code (e.g., "USA")
revenue.valueRevenue value
revenue.currencyCurrency code
revenue.multiplierValue multiplier (e.g., "MILLIONS")
revenue.isVerifiedWhether the value is verified
revenue.localCurrencyLocal currency code
revenue.localCurrencyValueValue in local currency
revenue.localCurrencyValueMultiplierLocal currency multiplier
marketCapMarket capitalization (same structure as revenue)
marketingBudgetMarketing budget (same structure as revenue)
fundingRaisedTotal funding raised (same structure as revenue)

8.2 Person Object

FieldDescription
idPerson ID
firstNameFirst name
lastNameLast name
nameFull name
genderGender
ageAge
skillsList of skills
categoryIdsCategory identifiers
languages.idLanguage identifier
languages.nameLanguage name
identifiers.nameIdentifier name (e.g., "LinkedIn", "Twitter")
identifiers.valueIdentifier value (URL or handle)
salary.grossSalary.valueGross salary value
salary.grossSalary.currencyCurrency code
salary.grossSalary.multiplierValue multiplier (e.g., "THOUSANDS")
salary.grossSalary.isVerifiedWhether the value is verified
salary.grossSalary.localCurrencyLocal currency code
salary.grossSalary.localCurrencyValueValue in local currency
salary.grossSalary.localCurrencyValueMultiplierLocal currency multiplier
salary.grossSalaryLowerRangeLower range of gross salary (same structure as grossSalary)
salary.grossSalaryUpperRangeUpper range of gross salary (same structure as grossSalary)

8.3 Deal Object

FieldDescription
idUnique deal ID (required)
titleDeal title
descriptionDeal description
typeDeal type (e.g., sponsorship, endorsement)
sponsorTypeType of sponsorship
announcedDateDate the deal was announced
announcedDateSourceSource of the announced date
startDateDeal start date
startDateSourceSource of the start date
endDateDeal end date
isEstimateWhether the value is an estimate
isExclusiveWhether the deal is exclusive
renewalOptionRenewal option type (e.g., AUTOMATIC, OPTIONAL)
totalDigitalImpressionsTotal digital impressions
annualValue.valueAnnual value amount
annualValue.currencyCurrency code
annualValue.multiplierValue multiplier (e.g., "MILLIONS")
annualValue.isVerifiedWhether the value is verified
annualValue.localCurrencyLocal currency code
annualValue.localCurrencyValueValue in local currency
annualValue.localCurrencyValueMultiplierLocal currency multiplier
totalValueTotal deal value (same structure as annualValue)
buyerCompaniesList of buyer companies
buyerCompanies.idBuyer company ID
buyerCompanies.nameBuyer company name
buyerCompanyIdsArray of buyer company IDs
buyerCompanyNamesArray of buyer company names
sellerCompaniesList of seller companies
sellerCompanies.idSeller company ID
sellerCompanies.nameSeller company name
sellerCompanyIdsArray of seller company IDs
sellerCompanyNamesArray of seller company names
sellerPersonIdsArray of seller person IDs
sponsoredPersonsList of sponsored persons
sponsoredPersons.idSponsored person ID
sponsoredPersons.nameSponsored person name
sportsList of sports associated with the deal
sports.idSport ID
sports.nameSport name

9. Error Handling

Authentication and rate-limit errors are returned by the gateway as HTTP errors with this body shape:

{ "message": "Invalid API key", "error": "Unauthorized", "statusCode": 401 }

Query-validation errors are returned in the standard GraphQL shape with an extensions.code:

{ "errors": [ { "message": "...", "extensions": { "code": "GRAPHQL_VALIDATION_FAILED" } } ] }
ScenarioHTTP statuserror / codeResolution
Missing Authorization header401UnauthorizedSend Authorization: Bearer <key>
Invalid/expired API key401Unauthorized (Invalid API key)Supply a valid API key
Invalid/expired JWT401Unauthorized (Invalid token: ...)Re-authenticate via authenticateUser
Invalid GraphQL query400GRAPHQL_VALIDATION_FAILEDFix the query/syntax
Rate limit exceeded429Too Many RequestsLower request frequency

10. Rate Limiting & Governance

API Key Validity

Limit TypePolicy
Default key validity1 year / 365 days (if expiresInDays is not specified when creating the API key)
Custom validityCan be set via expiresInDays when creating the API key, up to a maximum of 365 days (1 year)

Unverified: The external API exposes no query for listing or inspecting created API keys, and the schema does not surface a default value for the optional expiresInDays field (CreateApiKeyInput.expiresInDays is a plain optional Int). The 365-day default could therefore not be confirmed via the external API in this session.

Rate Limits by Environment

EnvironmentPolicy
Production• Non-data queries & mutations: 100 requests per 60 seconds (per IP and per user)
• Data connection queries (personsConnection, companiesConnection, dealsConnection, contactsConnection): 10 calls per day
• Results returned per data query: 1 result per call (use pageInfo.endCursor as the after variable in successive calls to page through additional results)
Staging• Non-data calls (queries and mutations): 100 requests per 60 seconds
• Data query results per call: 1 search result per call
• Data query daily limit: 10 calls per day

Exceeding a limit returns HTTP 429.

11. Security & Compliance

  • Keys have prefix cred_ and are user-scoped
  • JWTs use strict expiration
  • API keys must be stored in secret vaults
  • Production requires TLS
  • Full audit logs for key activity