Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/simple-ai:simple-ai-contacts-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Public API v1 Contacts API
description: 'Public API v1 requiring API keys.
**Timestamps:** All datetime fields in API responses are returned in UTC using ISO 8601 format (e.g., `2024-01-15T14:30:00Z`). When filtering by date parameters, provide timestamps in ISO 8601 format.'
version: 0.1.0
servers:
- url: https://api.usesimple.ai/api/v1
description: Production API Server
tags:
- name: Contacts
paths:
/contacts:
get:
tags:
- Contacts
summary: List Contacts
operationId: list_contacts
security:
- APIKeyHeader: []
responses:
'200':
description: List Contacts
content:
application/json:
schema:
$ref: '#/components/schemas/ListContactsResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The request or an attribute value is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
description: List active contacts in the authenticated organization, ordered by UUID. Supplied filters are combined. externalId requires sourceKey. Continue with after=nextCursor while hasMore is true.
parameters:
- name: sourceKey
in: query
required: false
schema:
type: string
minLength: 1
maxLength: 63
pattern: ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$
description: Stable lowercase snake_case identifier for the source.
- name: externalId
in: query
required: false
schema:
type: string
minLength: 1
maxLength: 1000
- name: phoneNumber
in: query
required: false
schema:
type: string
pattern: ^\+[1-9]\d{1,14}$
- name: email
in: query
required: false
schema:
type: string
format: email
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 50
- name: after
in: query
required: false
schema:
type: string
format: uuid
/contacts/{contactId}:
get:
tags:
- Contacts
summary: Get Contact
operationId: get_contact_by_uuid
security:
- APIKeyHeader: []
responses:
'200':
description: Get Contact
content:
application/json:
schema:
$ref: '#/components/schemas/SyncedContact'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The request or an attribute value is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'404':
description: Contact missing, deleted, or outside the authenticated organization.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
description: Read an active contact by UUID within the authenticated organization, including attributes, external identities, and consent records.
parameters:
- name: contactId
in: path
required: true
schema:
type: string
format: uuid
delete:
tags:
- Contacts
summary: Delete Contact
description: Delete an active contact by UUID within the authenticated organization. The contact no longer appears in reads, and a sync source can send the contact's external IDs and event IDs again to create a new contact. Opt-outs recorded for its phone number are kept.
operationId: delete_contact_by_uuid
security:
- APIKeyHeader: []
parameters:
- name: contactId
in: path
required: true
schema:
type: string
format: uuid
responses:
'200':
description: The contact was deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteContactResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'404':
description: Contact missing, already deleted, or outside the authenticated organization.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The contact ID is not a valid UUID.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
/contacts/upsert:
post:
tags:
- Contacts
summary: Upsert Synced Contact
description: Create or update a contact, define its source and fields, and record number-specific consent in one transaction. Accepts source strings and optional event ordering.
operationId: upsert_synced_contact_contacts_upsert_post
security:
- APIKeyHeader: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertSyncedContactRequest'
example:
source:
key: salesforce
name: Salesforce
provider: salesforce
fields:
name:
label: Name
type: text
email:
label: Email
type: email
phone_number:
label: Phone number
type: phone
lifecycle_stage:
label: Lifecycle stage
description: Current Salesforce lifecycle stage
type: enum
enumOptions:
- lead
- customer
externalId: lead-42
name: Ada Lovelace
email: ada@example.com
phoneNumber: '+14155550100'
attributes:
lifecycle_stage: lead
responses:
'200':
description: Contact updated or linked, or an event skipped with the current contact returned.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertSyncedContactResponse'
'201':
description: A new contact was created.
content:
application/json:
schema:
$ref: '#/components/schemas/UpsertSyncedContactResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'409':
description: Source, field, identity, event ID, or source timestamp conflict.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The request or an attribute value is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
/contacts/fields/{fieldKey}:
delete:
tags:
- Contacts
summary: Delete Synced Contact Field
description: Delete a contact field definition a sync source created, together with the values stored for it on every contact, so a source can define the same key again with a new type or enum options.
operationId: delete_synced_contact_field
security:
- APIKeyHeader: []
parameters:
- name: fieldKey
in: path
required: true
schema:
type: string
minLength: 1
maxLength: 63
pattern: ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$
description: Key of the field to delete.
responses:
'200':
description: The field was deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteSyncedContactFieldResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'404':
description: The organization has no field with this key.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'409':
description: The field was created in Simple, or a contact segment or the call params mapping uses it. Nothing is deleted.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The key is invalid or names the name, email, or phone_number field.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
/contacts/{phoneNumber}/data:
put:
tags:
- Contacts
summary: Replace Contact Data
description: Replace the complete JSON object stored for a phone number. The data is scoped to the authenticated organization, and an unknown phone number gets a contact automatically.
operationId: replace_contact_data_contacts__phoneNumber__data_put
security:
- APIKeyHeader: []
parameters:
- name: phoneNumber
in: path
required: true
schema:
type: string
description: The caller's phone number or other caller identifier. US numbers may be formatted or sent as digits; non-US numbers must include the + country code. Non-phone identifiers (for example chat or SIP identifiers) are accepted verbatim, up to 128 characters.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContactDataRequest'
responses:
'200':
description: Contact data replaced.
content:
application/json:
schema:
$ref: '#/components/schemas/ContactDataResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The phone number or request body is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
patch:
tags:
- Contacts
summary: Merge Contact Data
description: Shallow-merge top-level fields into the JSON object stored for a phone number. Set a field to null to delete it.
operationId: merge_contact_data_contacts__phoneNumber__data_patch
security:
- APIKeyHeader: []
parameters:
- name: phoneNumber
in: path
required: true
schema:
type: string
description: The caller's phone number or other caller identifier. US numbers may be formatted or sent as digits; non-US numbers must include the + country code. Non-phone identifiers (for example chat or SIP identifiers) are accepted verbatim, up to 128 characters.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContactDataRequest'
responses:
'200':
description: Contact data merged.
content:
application/json:
schema:
$ref: '#/components/schemas/ContactDataResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The phone number or request body is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
get:
tags:
- Contacts
summary: Read Contact Data
description: Read the current JSON object stored for a phone number in the authenticated organization. Stored keys are returned at the top level; if a stored key collides with a metadata field name, the metadata value wins.
operationId: read_contact_data_contacts__phoneNumber__data_get
security:
- APIKeyHeader: []
parameters:
- name: phoneNumber
in: path
required: true
schema:
type: string
description: The caller's phone number or other caller identifier. US numbers may be formatted or sent as digits; non-US numbers must include the + country code. Non-phone identifiers (for example chat or SIP identifiers) are accepted verbatim, up to 128 characters.
responses:
'200':
description: Current contact data.
content:
application/json:
schema:
$ref: '#/components/schemas/ContactDataGetResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'404':
description: No current data exists for this phone number.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The phone number is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
delete:
tags:
- Contacts
summary: Delete Contact Data
description: Delete the current JSON object stored for a phone number. Deletion is idempotent and preserves revision history.
operationId: delete_contact_data_contacts__phoneNumber__data_delete
security:
- APIKeyHeader: []
parameters:
- name: phoneNumber
in: path
required: true
schema:
type: string
description: The caller's phone number or other caller identifier. US numbers may be formatted or sent as digits; non-US numbers must include the + country code. Non-phone identifiers (for example chat or SIP identifiers) are accepted verbatim, up to 128 characters.
responses:
'200':
description: Contact data deletion result.
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteContactDataResponse'
'401':
description: Authentication failed.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
'422':
description: The phone number is invalid.
content:
application/json:
schema:
$ref: '#/components/schemas/PublicApiError'
components:
schemas:
DeleteContactDataResponse:
type: object
required:
- phoneNumber
- deleted
properties:
phoneNumber:
type: string
description: The normalized phone number in E.164 format, or the caller identifier as provided when it is not a phone number.
deleted:
type: boolean
description: Whether a current value was deleted.
title: Delete Contact Data Response
ContactDataGetResponse:
type: object
additionalProperties:
type: string
required:
- phoneNumber
description: Your stored fields at the top level, keyed alongside the caller identifier. Every value is a string, no value exceeds 250 characters, and the entire serialized body is kept within 250 characters as well — when the combined payload would overrun that, the longest field is shortened until it fits, longest first, so a prose field absorbs the loss. Values of 64 characters or fewer are never shortened, nor is the caller identifier, because truncating a routing value or status changes its meaning rather than degrading it; a body of only short values is returned over budget instead. IVR platforms consume this response as a flat key-value list and hold each value in a fixed-width string variable (Five9 caps script strings at 250 characters), so stored values longer than that are cut at the last sentence boundary that fits, or truncated at 250 characters when there is no usable boundary. Numbers and booleans are serialized as strings, null and absent values as an empty string, and nested objects and arrays as JSON text. Revision and expiry metadata is not returned here so it does not consume the IVR's character budget; the write endpoints return it.
properties:
phoneNumber:
type: string
description: The normalized phone number in E.164 format, or the caller identifier as provided when it is not a phone number.
title: Contact Data Get Response
DeleteContactResponse:
type: object
required:
- id
- deleted
properties:
id:
type: string
format: uuid
description: The UUID of the deleted contact.
deleted:
type: boolean
const: true
title: Delete Contact Response
ContactDataRequest:
type: object
additionalProperties: false
required:
- data
properties:
data:
type: object
additionalProperties: true
description: The JSON object to store. Its serialized UTF-8 size may not exceed 64 KiB.
ttlSeconds:
type: integer
minimum: 60
maximum: 7776000
description: Optional expiration in seconds. Omit for no expiry; allowed values range from 60 seconds through 90 days.
title: Contact Data Request
UpsertSyncedContactResponse:
type: object
required:
- contact
- created
- linked
- applied
- reason
properties:
contact:
$ref: '#/components/schemas/SyncedContact'
created:
type: boolean
description: True when this request created the Simple contact.
linked:
type: boolean
description: True when a new external identity was linked to an existing Simple contact.
applied:
type: boolean
description: False when the request was skipped as a duplicate or stale event.
reason:
anyOf:
- type: string
enum:
- duplicate
- stale
- type: 'null'
title: Upsert Synced Contact Response
DeleteSyncedContactFieldResponse:
type: object
required:
- key
- deleted
properties:
key:
type: string
description: The key of the deleted field.
deleted:
type: boolean
const: true
title: Delete Synced Contact Field Response
ContactSyncSource:
type: object
additionalProperties: false
required:
- key
- name
- provider
properties:
key:
type: string
minLength: 1
maxLength: 63
pattern: ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$
description: Stable lowercase snake_case identifier for the source.
name:
type: string
minLength: 1
maxLength: 255
description: Display name for the source.
provider:
type: string
enum:
- salesforce
- shopify
- custom
description: The system that owns the synced contact data.
title: Contact Sync Source
ContactExternalIdentity:
type: object
required:
- sourceKey
- externalId
properties:
sourceKey:
type: string
externalId:
type: string
title: Contact External Identity
ListContactsResponse:
type: object
required:
- data
- hasMore
- nextCursor
properties:
data:
type: array
items:
$ref: '#/components/schemas/SyncedContact'
hasMore:
type: boolean
nextCursor:
anyOf:
- type: string
format: uuid
- type: 'null'
SyncedContact:
type: object
required:
- id
- name
- email
- phoneNumber
- attributes
- derivedAttributes
- externalIdentities
- consents
- isTest
properties:
id:
type: string
format: uuid
name:
anyOf:
- type: string
- type: 'null'
email:
anyOf:
- type: string
format: email
- type: 'null'
phoneNumber:
anyOf:
- type: string
- type: 'null'
isTest:
type: boolean
description: True for contacts created as dashboard test identities. Test contacts never merge with production contacts.
attributes:
type: object
additionalProperties:
anyOf:
- type: string
- type: number
- type: boolean
- type: 'null'
derivedAttributes:
type: object
additionalProperties:
$ref: '#/components/schemas/DerivedContactAttribute'
externalIdentities:
type: array
items:
$ref: '#/components/schemas/ContactExternalIdentity'
consents:
type: array
items:
$ref: '#/components/schemas/ContactConsentRecord'
description: Consent records by source for the current phone number. Empty for contacts without a phone number.
title: Synced Contact
ContactDataResponse:
type: object
required:
- phoneNumber
- data
- revision
- ttlSeconds
- expiresAt
properties:
phoneNumber:
type: string
description: The normalized phone number in E.164 format, or the caller identifier as provided when it is not a phone number.
data:
type: object
additionalProperties: true
description: The stored JSON object.
revision:
type: integer
minimum: 1
description: The revision number of this value.
ttlSeconds:
anyOf:
- type: integer
- type: 'null'
description: Remaining TTL in seconds, or null when the record has no expiry.
expiresAt:
anyOf:
- type: string
format: date-time
- type: 'null'
description: Expiration timestamp in UTC, or null when the record has no expiry.
title: Contact Data Response
PublicApiError:
type: object
required:
- status
- success
- error
- errors
properties:
status:
type: string
const: error
success:
type: boolean
const: false
error:
type: string
errors:
type: array
items:
type: string
title: Public API Error
DerivedContactAttribute:
type: object
required:
- value
- status
- confidence
- evaluatedAt
properties:
value:
anyOf:
- type: string
- type: number
- type: boolean
- type: 'null'
status:
type: string
enum:
- ready
- pending
- stale
- failed
confidence:
anyOf:
- type: number
- type: 'null'
evaluatedAt:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Derived Contact Attribute
ContactConsentRecord:
type: object
required:
- phoneNumber
- sourceKey
- medium
- category
- status
- observedAt
properties:
phoneNumber:
type: string
sourceKey:
anyOf:
- type: string
- type: 'null'
description: Null identifies a decision recorded by Simple.
medium:
type: string
enum:
- voice
- text
category:
type: string
enum:
- all
- transactional
- marketing
status:
type: string
enum:
- opted_in
- opted_out
- not_opted_out
- unknown
description: Any opted_out record blocks the matching communication. not_opted_out does not grant affirmative consent.
observedAt:
type: string
format: date-time
UpsertSyncedContactRequest:
type: object
additionalProperties: false
required:
- source
- externalId
properties:
source:
oneOf:
- type: string
minLength: 1
maxLength: 63
pattern: ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$
description: Stable lowercase snake_case identifier for the source.
- $ref: '#/components/schemas/ContactSyncSource'
description: A source key reuses or creates a custom source. The object form supplies its display name and provider. Existing metadata is preserved when using a string.
fields:
type: object
propertyNames:
pattern: ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$
maxLength: 63
additionalProperties:
$ref: '#/components/schemas/ContactSyncFieldDefinition'
default: {}
description: Field definitions owned by this source. Include them when first used or when labels, descriptions, or enum options change. Define name, email, and phone_number before sending their corresponding top-level values.
externalId:
type: string
minLength: 1
maxLength: 1000
description: Stable contact identifier from the external source.
name:
anyOf:
- type: string
minLength: 1
maxLength: 255
- type: 'null'
description: Contact name. Omit to leave unchanged or send null to clear it.
email:
anyOf:
- type: string
format: email
- type: 'null'
description: Contact email. Omit to leave unchanged or send null to clear it.
phoneNumber:
anyOf:
- type: string
minLength: 1
maxLength: 255
- type: 'null'
description: Contact phone number. Omit to leave unchanged or send null to clear it.
match:
$ref: '#/components/schemas/ContactSyncMatch'
attributes:
type: object
propertyNames:
pattern: ^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$
maxLength: 63
additionalProperties: true
default: {}
description: Values for non-system fields defined by this source. Values must match their field type. Omit a key to leave it unchanged or send null to clear it.
eventId:
type: string
minLength: 1
maxLength: 255
description: Unique event ID within this source. Supply with sourceUpdatedAt; required for nonempty consents. Retry with the same request body.
sourceUpdatedAt:
type: string
format: date-time
description: Timestamp of the source change, including timezone. Older events for the external identity are skipped. Supply with eventId.
consents:
type: array
maxItems: 6
default: []
items:
$ref: '#/components/schemas/ContactConsentInput'
description: Preferences for the supplied primary phoneNumber. Omitted or empty leaves consent unchanged. Duplicate medium/category entries are rejected.
title: Upsert Synced Contact Request
dependentRequired:
eventId:
- sourceUpdatedAt
sourceUpdatedAt:
- eventId
allOf:
- if:
required:
- consents
properties:
consents:
minItems: 1
then:
required:
- phoneNumber
- eventId
- sourceUpdatedAt
properties:
phoneNumber:
type: string
pattern: ^\+[1-9]\d{1,14}$
ContactConsentInput:
type: object
additionalProperties: false
required:
- medium
- category
- optOut
properties:
medium:
type: string
enum:
- voice
- text
category:
type: string
enum:
- all
- transactional
- marketing
optOut:
anyOf:
- type: boolean
- type: 'null'
description: True reports an opt-out, false reports no opt-out from this source, and null reports unknown. False is not affirmative consent.
ContactSyncMatch:
type: object
additionalProperties: false
properties:
email:
type: string
format: email
description: Lookup-only email used to link this identity to one existing contact.
phoneNumber:
type: string
minLength: 1
maxLength: 255
description: Lookup-only phone number used to link this identity to one existing contact.
default: {}
title: Contact Sync Match
ContactSyncFieldDefinition:
type: object
additionalProperties: false
required:
- label
- type
properties:
label:
type: string
minLength: 1
maxLength: 255
description: Display label for the field.
description:
anyOf:
- type: string
maxLength: 2000
- type: 'null'
default: null
description: Optional explanation of the field.
type:
type: string
enum:
- text
- number
- boolean
- date
- enum
- url
- email
- phone
description: Value type enforced for this field. A field's type cannot be changed after creation.
enumOptions:
type: array
maxItems: 100
uniqueItems: true
items:
type: string
minLength: 1
maxLength: 255
default: []
description: Allowed values for an enum field. Required for enum fields and omitted for other types. Existing options cannot be removed.
title: Contact Sync Field Definition
securitySchemes:
APIKeyHeader:
type: http
scheme: bearer
description: 'Your API key, sent as `Authorization: Bearer YOUR_API_KEY`'