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/spruce-health-conversations-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: Spruce Health Conversations API
version: 1.0.0
description: The Conversations operations of the Spruce Health API, split by tag from the OpenAPI Spruce Health publishes for developer.sprucehealth.com (ReadMe registry @spruce/v1.0#13needamst2v4m6). Base https://api.sprucehealth.com/v1, Bearer organization token.
contact:
name: Spruce Health
url: https://developer.sprucehealth.com
servers:
- url: https://api.sprucehealth.com/v1
variables:
domain:
default: api.sprucehealth.com
security:
- spruceAPIToken: []
tags:
- name: Conversations
paths:
/conversations:
get:
description: 'This operation lists all conversations available to the organization. This is an eventually consistent view and may take a short time before new conversations appear in results.
To iterate through all conversations in the organization, list the first page of conversations (without specifying `paginationToken` or `startFrom`). If `hasMore=true`, the provide the `paginationToken` to the API to list subsequent pages of conversations until `hasMore=false`.
## Detecting conversations with new messages
Note that the conversations are ordered by created date by default. You can also order them by the time of last activity in the conversation by specifying `orderBy=last_message`. This is particularly helpful when trying to determine conversations with new activity in them. In this particular case, you can query the list of conversations with `orderBy=last_message` and capture the `lastMessageAt` time for the last conversation in the list. On the next query, you can then `startFrom=<lastMessageAt time you saved>` and `orderBy=last_message` to return any conversations with new activity since your last query.
While you can determine the conversations with new activity, it is also important to know if the latest messages in each conversation were from your teammates or from an external contact (like a patient). To determine this, you can use the [listing of conversation items API](/reference/conversationitems) to query for the latest items since a particular time with the `startFrom` field. If any message in the list returned has `direction=inbound` then it indicates a message received since the last query for message items.
'
operationId: ListConversations
parameters:
- description: How many conversations to return at one time (max 200)
in: query
name: pageSize
required: false
schema:
format: int32
maximum: 200
minimum: 1
type: integer
- description: 'After fetching a set of conversations, use the returned `paginationToken` to fetch the next page of conversations. Only one of `startFrom` or `paginationToken` can be provided.
'
in: query
name: paginationToken
required: false
schema:
$ref: '#/components/schemas/paginationToken'
- description: 'Determines the order of the results. When optionally combined with `startFrom`, you can get conversationswhere the time that you''re ordering by is greater than or equal to the specified start from date. For example, `"orderBy": "last_message"` and `"startFrom": "2025-01-01T00:00:00.000Z"` will return conversations with a last message time greater than or equal to January 1, 2025 midnight UTC (useful for fetching delta updates from the last time you fetched).
'
in: query
name: orderBy
required: true
schema:
$ref: '#/components/schemas/conversations_orderBy'
- description: 'Only return conversations whose ordering field value is greater than or equal to this timestamp.
**Format** — RFC 3339 “date-time” (`YYYY-MM-DDTHH:mm:ss.SSS±hh:mm`). Use **Z** for UTC or an explicit offset such as **-07:00**.
- When `orderBy=created`, you will receive conversations created greater than or equal to the provided startFrom time.
- When `orderBy=last_message`, you will receive conversations with a last message time greater than or equal to the provided startFrom time.
- Only one of `startFrom` or `paginationToken` can be provided.
'
examples:
laPDT:
summary: Same instant in Los Angeles (PDT)
value: '2020-03-31T17:00:00-07:00'
utcMidnight:
summary: UTC start of 1 Apr 2020
value: '2020-04-01T00:00:00Z'
in: query
name: startFrom
required: false
schema:
format: date-time
type: string
responses:
'200':
content:
application/json:
schema:
properties:
conversations:
items:
$ref: '#/components/schemas/conversation'
type: array
hasMore:
$ref: '#/components/schemas/hasMore'
paginationToken:
$ref: '#/components/schemas/paginationToken'
totalCount:
$ref: '#/components/schemas/totalCount'
description: Total count represents the total number of conversations available. This is a best effort calculation at the time of the initial query. This count will not be recalculated more than once every 60 seconds while iterating a set of results.
required:
- totalCount
- conversations
- hasMore
type: object
description: Expected response to a valid request
headers:
s-ratelimit-limit:
$ref: '#/components/headers/s-ratelimit-limit'
s-ratelimit-remaining:
$ref: '#/components/headers/s-ratelimit-remaining'
s-request-id:
$ref: '#/components/headers/s-request-id'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: bad request
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: unexpected error
summary: List and filter all conversations available to the organization
tags:
- Conversations
post:
description: 'This operation creates a new conversation within an organization. The following conversation types are supported:
### Secure Conversations (`type: "secure"`)
A secure conversation can be started with a single contact or a group of contacts. All contacts must be patients and either have a Spruce account or a pending secure invite.
### Note Conversations (`type: "note"`)
A note conversation is an internal-only conversation for documenting information. Notes can optionally include organization members/groups and can be associated with contacts for organizational purposes (via `associatedContactIds`). Associated contacts will not have access to the note.
### Asynchronous Message Processing
If a message is included in the conversation creation request, the message will be posted asynchronously after the conversation is created. The API will immediately return the conversation details along with a `postMessageRequestId` that can be used to track when the message is actually sent.
The `postMessageRequestId` returned in the response can be matched against the `requestID` field of the `conversationItem.created` webhook event to identify when the message has been successfully posted to the conversation.
'
operationId: CreateConversation
parameters:
- $ref: '#/components/parameters/s-idempotency-key'
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/createConversation'
description: Conversation json object. The internal secure endpoint and destinations are required.
required: true
responses:
'201':
content:
application/json:
schema:
properties:
conversation:
$ref: '#/components/schemas/conversation'
postMessageRequestId:
$ref: '#/components/schemas/asyncRequest_id'
required:
- conversation
type: object
description: created
headers:
s-ratelimit-limit:
$ref: '#/components/headers/s-ratelimit-limit'
s-ratelimit-remaining:
$ref: '#/components/headers/s-ratelimit-remaining'
s-request-id:
$ref: '#/components/headers/s-request-id'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: bad request
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: unexpected error
summary: Create a new conversation
tags:
- Conversations
/conversations/{conversationId}:
get:
description: This operation fetches a specific conversation for the provided id.
operationId: Conversation
parameters:
- description: The id of the conversation to retrieve
in: path
name: conversationId
required: true
schema:
type: string
responses:
'200':
content:
application/json:
schema:
properties:
conversation:
$ref: '#/components/schemas/conversation'
required:
- conversation
type: object
description: Expected response to a valid request
headers:
s-ratelimit-limit:
$ref: '#/components/headers/s-ratelimit-limit'
s-ratelimit-remaining:
$ref: '#/components/headers/s-ratelimit-remaining'
s-request-id:
$ref: '#/components/headers/s-request-id'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: bad request
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: not found
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: unexpected error
summary: Get a conversation for a given id
tags:
- Conversations
patch:
description: 'This operation updates a specific conversation by id.
Fields provided in the input object will be updated, omitted fields *(null)* will be unchanged.'
operationId: UpdateConversation
parameters:
- $ref: '#/components/parameters/s-idempotency-key'
- description: The id of the conversation to update
in: path
name: conversationId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/updateConversation'
description: Conversation json object. Omitted fields are not updated.
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/conversation'
description: ok response
headers:
s-ratelimit-limit:
$ref: '#/components/headers/s-ratelimit-limit'
s-ratelimit-remaining:
$ref: '#/components/headers/s-ratelimit-remaining'
s-request-id:
$ref: '#/components/headers/s-request-id'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: bad request
'404':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: not found
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: duplicate request
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: unexpected error
summary: Update a conversation
tags:
- Conversations
/conversations/{conversationId}/items:
get:
description: This operation lists all conversations items available in a conversation. This is an eventually consistent view and may take a short time before new conversation items appear in results.
operationId: ConversationItems
parameters:
- description: The id of the conversation to list items for
in: path
name: conversationId
required: true
schema:
type: string
- description: How many conversation items to return at one time (max 200)
in: query
name: pageSize
required: false
schema:
format: int32
maximum: 200
minimum: 1
type: integer
- description: The order in which conversation items are returned.
in: query
name: order
required: false
schema:
$ref: '#/components/schemas/conversationItems_Order'
- in: query
name: paginationToken
required: false
schema:
$ref: '#/components/schemas/paginationToken'
- description: The created time after which to query for new items in a conversation.
in: query
name: startFrom
required: false
schema:
example: '2020-04-01T00:00:00Z'
format: date-time
type: string
responses:
'200':
content:
application/json:
schema:
properties:
conversationItems:
items:
$ref: '#/components/schemas/conversationItem'
type: array
hasMore:
$ref: '#/components/schemas/hasMore'
paginationToken:
$ref: '#/components/schemas/paginationToken'
totalCount:
$ref: '#/components/schemas/totalCount'
description: Total count represents the total number of conversation items available. This is a best effort calculation at the time of the initial query. This count will not be recalculated more than once every 60 seconds while iterating a set of results.
required:
- totalCount
- conversationItems
- hasMore
type: object
description: Expected response to a valid request
headers:
s-ratelimit-limit:
$ref: '#/components/headers/s-ratelimit-limit'
s-ratelimit-remaining:
$ref: '#/components/headers/s-ratelimit-remaining'
s-request-id:
$ref: '#/components/headers/s-request-id'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: bad request
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: unexpected error
summary: List and filter all conversation items in a conversation
tags:
- Conversations
/conversations/{conversationId}/messages:
post:
description: 'This operation posts a message in a conversation as specified by the conversationId. You can retrieve the conversationId by [listing the conversations for a contact](/reference/contactconversations) or by [listing all conversations in the organization](/reference/conversations). You can also [send messages to a phone number, an email address, fax number, or securely message a contact](/reference/postmessagefromendpoint) using a [specific internal endpoint](/reference/internalendpoints). The `requestID` returned by this API may be used to match against the `requestID` field of the `conversationItem.created` webhook event to identify when the message is posted.
## Posting an internal message containing a page for an organization member
To post a message with a page for an organization member, you''ll first need to know the member''s id. You can find the id of the organization member by [listing all organization members](/reference/organizationmembers). Once the member id is known, you can post a message to the conversation with `internal=true` and an element of `type=page` and `value=<member-id>` in the list of `body` elements being posted.
The `body` parameter is a list of message elements. Each element can be of type `text` or `page`. The request can contain combinations of `text` and `page` elements to create internal messages with useful content while also notifying a set of members.
## Posting to a Team or Note conversation
You can also use this API to post messages into a Team or Note conversations. For Note conversations, you will have to specify `internal=true` since only internal messages can be posted in Note conversations.'
operationId: PostConversationMessage
parameters:
- $ref: '#/components/parameters/s-idempotency-key'
- description: The id of the conversation to post to
in: path
name: conversationId
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/conversation_messagePost'
required: true
responses:
'200':
content:
application/json:
schema:
properties:
requestId:
$ref: '#/components/schemas/asyncRequest_id'
required:
- requestId
type: object
description: ok
headers:
s-ratelimit-limit:
$ref: '#/components/headers/s-ratelimit-limit'
s-ratelimit-remaining:
$ref: '#/components/headers/s-ratelimit-remaining'
s-request-id:
$ref: '#/components/headers/s-request-id'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: bad request
'422':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: duplicate request
'500':
content:
application/json:
schema:
$ref: '#/components/schemas/error'
description: unexpected error
summary: Post a message to a specific conversation
tags:
- Conversations
components:
schemas:
conversation_id:
description: Spruce's conversation ID
example: t_0E5QDGJC03000
type: string
conversationItem_ImageAttachment:
properties:
mimetype:
description: The mimetype of the image attachment.
example: image/png
type: string
signedUrl:
$ref: '#/components/schemas/signedUrl'
description: The URL used to fetch the image attachment.
required:
- mimetype
- signedUrl
type: object
conversationItem_Transcription:
properties:
id:
description: The id of the transcription job. Pass this to the [Transcription endpoint](/reference/transcription) to fetch the full transcription text.
type: string
status:
description: The current status of the transcription. When `pending`, the transcription is still being processed.
enum:
- completed
- pending
- failed
- noSpeech
type: string
summarizationStatus:
description: The current status of the summarization, if the transcription is being summarized. Null when no summarization was requested.
enum:
- completed
- pending
- failed
type: string
required:
- id
- status
type: object
conversationItems_Order:
description: The order of the conversation items returned
enum:
- newest_first
- oldest_first
example: newest_first
type: string
teammate_id:
description: The id of the teammate
example: entity_0E5QDGJC03000
type: string
conversation_tagId:
description: Spruce's conversation tag ID
example: tag_0E5QDGJC03000
type: string
deviceInformation:
properties:
accessID:
description: The access ID of API credentials used to make the request.
type: string
appVersion:
description: The version of the app.
type: string
device:
description: The type of the device.
type: string
deviceId:
description: The id of the device.
type: string
deviceModel:
description: The model of the device.
type: string
platform:
description: The platform of the device.
type: string
type: object
objectType:
description: String representing the object's type
type: string
conversation:
properties:
apiURL:
description: An absolute URL for fetching this conversation from the API
example: https://api.sprucehealth.com/conversations/t_0E5QDJJC03000
format: url
type: string
appURL:
description: An absolute URL to view the conversation in the Spruce app
example: https://app.sprucehealth.com/org/entity_0D4QABCC06000/thread/t_0E5QDJJC03000
format: url
type: string
archived:
description: Whether or not the conversation is archived
example: false
type: boolean
assignedToMemberId:
description: The id of the teammate the conversation is assigned to
example: entity_0D4QABCC06000
type: string
associatedContactIds:
description: The ids of the contacts associated with the conversation. This may include contacts that are not a part of the conversation. For example, the conversation may be with parents, but associated with a contact representing their child.
example:
- entity_0D4QABCC06000
items:
type: string
type: array
createdAt:
description: The date the conversation was created
example: '2020-04-01T00:00:00Z'
format: date-time
type: string
externalParticipants:
description: The external participants in the conversation.
items:
properties:
contact:
description: The id of the contact associated with the participant. This will be omitted if the participant is not a saved contact.
example: entity_0D4QABCC06000
type: string
displayName:
description: The display name of the participant
example:
- 555-555-5555
- John Doe
- patient@example.com
type: string
endpoint:
$ref: '#/components/schemas/endpoint'
description: The endpoint of the participant, such as their phone number or email address. For secure conversations, there will not be an endpoint.
required:
- displayName
type: object
type: array
id:
$ref: '#/components/schemas/conversation_id'
internalEndpoint:
$ref: '#/components/schemas/endpoint'
description: 'The internal endpoint of the conversation. For secure conversations, this will be a Spruce Link.
Note: for secure endpoints, the `id` returned here is a derived value that will not equal the `endpoint.id` returned for the same Spruce Link by the list internal endpoints API. Use `rawValue` to match a conversation''s secure internal endpoint to the corresponding Spruce Link. Endpoint ids for phone, fax, and email channels use the same format across responses and can be compared directly.
'
internalMemberIds:
description: The ids of the teammates, teams and/or your organization that are members of the conversation.
example:
- entity_0D4QABCC06000
items:
type: string
type: array
isReadOnly:
description: If the conversation is read-only, messages cannot be sent to it.
example: false
type: boolean
lastMessageAt:
description: The time of the conversations latest message
example: '2020-04-01T00:00:00Z'
format: date-time
type: string
object:
$ref: '#/components/schemas/objectType'
subtitle:
description: The subtitle of the conversation
example: Billing
type: string
tags:
$ref: '#/components/schemas/conversation_tags'
title:
description: The title of the conversation
example: John Doe
type: string
type:
description: The type of the conversation (e.g. 'email', 'phone', 'secure', etc.). Note that SMS will be in a 'phone' conversation, and video calls will be in a 'secure' conversation. More conversation types may be added in the future, so ensure while parsing this that you gracefully handle any new/unexpected values.
enum:
- email
- phone
- secure
- fax
- team
- note
- other
type: string
required:
- appURL
- apiURL
- archived
- createdAt
- id
- isReadOnly
- tags
- type
- title
- object
type: object
conversations_orderBy:
description: The order of the conversations returned
enum:
- created
- last_message
example: created
type: string
create_conversation_note:
properties:
associatedContactIds:
description: The ids of contacts that this note is regarding. These contacts will not have access to the note but will be associated with it for organizational purposes.
example:
- entity_0D4QABCC06000
items:
type: string
type: array
memberIds:
description: The ids of organization members or groups to include in the note conversation. If not provided, the note will be private to the creator.
example:
- entity_0D4QABCC06000
items:
type: string
type: array
message:
$ref: '#/components/schemas/conversation_messagePost'
title:
description: The title of the note conversation. If not provided, a default title will be generated.
example: Patient Follow-up Notes
type: string
type: object
conversationItem_Page:
properties:
id:
description: The id of the page.
type: string
memberId:
description: The id of the teammate being paged.
example: entity_0D4QABCC06000
type: string
resolved:
description: If the page has been resolved.
type: boolean
resolvedAt:
description: The date time the page was resolved at.
example: '2020-04-01T00:00:00Z'
format: date-time
type: string
resolvedByMemberId:
description: The id of the teammate that resolved the page.
example: entity_0D4QABCC06000
type: string
required:
- id
- memberId
- resolved
type: object
error:
properties:
message:
example: Invalid Contact ID
type: string
statusCode:
example: 400
type: integer
type:
example: BAD_PARAMETER
type: string
required:
- message
- statusCode
- type
type: object
conversation_messageBodyElement:
description: An element of a message body. This can be either a `text` or `page` type element. A `text` element is a string of text to be placed in the message. A `page` element is a reference to an organization member. For a `page` element, the value field should be the Spruce id of the organization member being referenced.
properties:
type:
enum:
- text
- page
example: text
type: string
value:
description: The value of the message body element
example: Hello, how are you?
type: string
required:
- type
- value
type: object
paginationToken:
description: Token given in a previous response to allow requesting the next page
example: abcdefghijklmnop
type: string
conversation_messagePost_attachment:
properties:
attachmentId:
description: The id of the attachment. In most cases, this will be a media id returned from posting a file to the [media endpoint](/reference/uploadmedia).
example: d7b25969-86ec-7e37-3776-3577-c0637a0c
type: string
title:
description: The title of the attachment
example: My Image
type: string
required:
- attachmentId
- title
type: object
conversationItem_id:
description: The id of a conversation item.
example: ti_0D4QABCC06000
type: string
totalCount:
example: 750
format: int32
type: integer
create_conversation_secure:
properties:
destinationContactIds:
description: The ids of the destination contacts.
example:
- entity_0D4QABCC06000
items:
type: string
type: array
internalEndpointId:
description: Organization's internal endpoint ID that will be used as the internal endpoint for the conversation.
example: organizationCode_2ER39ETHBQ800
type: string
message:
$ref: '#/components/schemas/conversation_messagePost'
subject:
description: The conversation's subject.
example: Annual Physical Exam
type: string
required:
- destinationContactIds
- internalEndpointId
type: object
endpoint:
properties:
channel:
description: The channel of the endpoint (e.g. 'email', 'phone', 'fax', etc.). More endpoint channels may be added in the future, so ensure while parsing this that you gracefully handle any new/unexpected values.
enum:
- email
- phone
- fax
- secure
type: string
displayValue:
description: The display value of the endpoint. This is the value that should be displayed to the user when showing the endpoint, along with the label if it's populated.
example:
email:
value: patient@example.com
phone:
value: (555) 555-5555
secure:
value: spruce.care/123456
type: string
id:
$ref: '#/components/schemas/endpoint_id'
isInternal:
description: Internal endpoints are endpoints that are owned by your organization, such as your organization's Spruce Phone Numbers or Spruce Links.
example: false
type: boolean
label:
description: The optional label of the endpoint
example:
- Home
- Work
type: string
object:
$ref: '#/components/schemas/objectType'
rawValue:
description: The raw value
# --- truncated at 32 KB (48 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/spruce-health/refs/heads/main/openapi/spruce-health-conversations-api-openapi.yml