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/onclarity-com:onclarity-com-next-steps-sync-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: Fast Next Steps Sync API
version: 0.1.0
tags:
- name: next_steps_sync
paths:
/api/v1/next-steps/sync/projects:
get:
tags:
- next_steps_sync
summary: List Projects
description: 'Live projects whose active config has ``nextStepsEnabled: true``, by id.'
operationId: list_projects_api_v1_next_steps_sync_projects_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SyncProjectsResponse'
'401':
description: Missing or invalid NEXT_STEPS_SYNC_PSK
'404':
description: Sync API off here (no key set), or no such flagged project
security:
- HTTPBearer: []
/api/v1/next-steps/sync/projects/{project_id}/inputs:
get:
tags:
- next_steps_sync
summary: Get Inputs
description: 'Everything the rules need for one project, minimal fields, no message text.
Members are the people who can get steps (never staff, blocked, deleted or pending users).
Apps and routines are the members'' own (plus whatever an open step points at), conversations
the members'' copilot conversations of the last 30 days, steps the project''s steps in every
state. Each list is capped at 5000 rows (``truncated`` names a list that was cut).
Raises:
HTTPException: 404 when the project does not exist or its flag is off.'
operationId: get_inputs_api_v1_next_steps_sync_projects__project_id__inputs_get
security:
- HTTPBearer: []
parameters:
- name: project_id
in: path
required: true
schema:
type: integer
maximum: 9223372036854775807
minimum: 1
description: A Clarity project id
title: Project Id
description: A Clarity project id
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SyncInputsResponse'
'401':
description: Missing or invalid NEXT_STEPS_SYNC_PSK
'404':
description: Sync API off here (no key set), or no such flagged project
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/next-steps/sync/projects/{project_id}/steps:
post:
tags:
- next_steps_sync
summary: Write Steps
description: 'Upsert steps, mark steps done, withdraw (expire) steps — one transaction per call.
Every upsert row is validated on its own: its person must be a non-staff member of THIS
project; its subject must be in this project (and the person''s own for a draft, a routine,
or their conversations); its kind a short slug; its wording within the caps. A refused row is
reported in ``errors`` (list, index, reason — never the values sent) and the rest are
written. A new step gets its group (``grp``) from Clarity; an open step only gets new
wording; a done, dismissed or expired step is never reopened (``status: final``).
Example:
```json
{"upsert": [{"user_id": 42, "kind": "routine_failed", "subject": {"routine_id": 7},
"wording": {"title": "Your routine “Weekly churn” failed",
"detail": "Open it to see what went wrong.",
"action_label": "Open the routine", "href": "/routines/7"}}],
"done": [311], "expire": []}
```
Raises:
HTTPException: 404 when the project does not exist or its flag is off; 400 when the body
is not of this shape (more than 500 upsert rows, 1000 done/expire ids, unknown keys).'
operationId: write_steps_api_v1_next_steps_sync_projects__project_id__steps_post
security:
- HTTPBearer: []
parameters:
- name: project_id
in: path
required: true
schema:
type: integer
maximum: 9223372036854775807
minimum: 1
description: A Clarity project id
title: Project Id
description: A Clarity project id
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/StepsSyncRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/StepsSyncResponse'
'401':
description: Missing or invalid NEXT_STEPS_SYNC_PSK
'404':
description: Sync API off here (no key set), or no such flagged project
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/v1/next-steps/sync/results:
get:
tags:
- next_steps_sync
summary: Get Results
description: 'What happened to the steps: one page of events, oldest first, and the current state of
every step those events are about (with the person''s email). Give ``since`` for the first
page, then ``cursor`` (or keep the last ``next_cursor`` and resume from it the next day).
Raises:
HTTPException: 400 when neither ``since`` nor ``cursor`` is given.'
operationId: get_results_api_v1_next_steps_sync_results_get
security:
- HTTPBearer: []
parameters:
- name: since
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
description: Events at or after this instant (ISO 8601 with offset)
title: Since
description: Events at or after this instant (ISO 8601 with offset)
- name: cursor
in: query
required: false
schema:
anyOf:
- type: string
pattern: ^\d{1,19}$
- type: 'null'
description: '`next_cursor` of the previous page'
title: Cursor
description: '`next_cursor` of the previous page'
- name: project_id
in: query
required: false
schema:
anyOf:
- type: integer
maximum: 9223372036854775807
minimum: 1
- type: 'null'
description: Only this project
title: Project Id
description: Only this project
- name: limit
in: query
required: false
schema:
type: integer
maximum: 1000
minimum: 1
default: 500
title: Limit
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SyncResultsResponse'
'401':
description: Missing or invalid NEXT_STEPS_SYNC_PSK
'404':
description: Sync API off here (no key set), or no such flagged project
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
components:
schemas:
SyncInputsResponse:
properties:
project:
$ref: '#/components/schemas/SyncProject'
generated_at:
type: string
format: date-time
title: Generated At
conversation_window_days:
type: integer
title: Conversation Window Days
members:
items:
$ref: '#/components/schemas/InputMember'
type: array
title: Members
description: Non-staff members who can get steps (never admins, blocked, deleted or pending users)
apps:
items:
$ref: '#/components/schemas/InputApp'
type: array
title: Apps
description: The members' live apps, and every app an open step points at
routines:
items:
$ref: '#/components/schemas/InputRoutine'
type: array
title: Routines
description: The members' routines, and every routine an open step points at
conversations:
items:
$ref: '#/components/schemas/InputConversation'
type: array
title: Conversations
description: The members' copilot conversations in the window
steps:
items:
$ref: '#/components/schemas/InputStep'
type: array
title: Steps
description: The project's steps in every state, newest first
truncated:
items:
type: string
type: array
title: Truncated
description: 'Lists that hit their cap (5000 rows) and were cut: their newest/first rows'
type: object
required:
- project
- generated_at
- conversation_window_days
- members
- apps
- routines
- conversations
- steps
title: SyncInputsResponse
InputConversation:
properties:
id:
type: integer
title: Id
owner_user_id:
type: integer
title: Owner User Id
title:
anyOf:
- type: string
- type: 'null'
title: Title
description: The conversation's title (a short topic); never message text
status:
type: string
title: Status
created_at:
type: string
format: date-time
title: Created At
type: object
required:
- id
- owner_user_id
- status
- created_at
title: InputConversation
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
input:
title: Input
ctx:
type: object
title: Context
type: object
required:
- loc
- msg
- type
title: ValidationError
InputApp:
properties:
id:
type: integer
title: Id
slug:
type: string
title: Slug
description: The app page is /app/{slug} (the step's href)
name:
anyOf:
- type: string
- type: 'null'
title: Name
created_by:
anyOf:
- type: integer
- type: 'null'
title: Created By
updated_at:
type: string
format: date-time
title: Updated At
is_deleted:
type: boolean
title: Is Deleted
type: object
required:
- id
- slug
- updated_at
- is_deleted
title: InputApp
SyncProjectsResponse:
properties:
projects:
items:
$ref: '#/components/schemas/SyncProject'
type: array
title: Projects
description: Live projects with nextStepsEnabled on, by id
type: object
required:
- projects
title: SyncProjectsResponse
InputStep:
properties:
id:
type: integer
title: Id
user_id:
type: integer
title: User Id
kind:
type: string
title: Kind
app_id:
anyOf:
- type: integer
- type: 'null'
title: App Id
routine_id:
anyOf:
- type: integer
- type: 'null'
title: Routine Id
signal_item_id:
anyOf:
- type: integer
- type: 'null'
title: Signal Item Id
question_group_id:
anyOf:
- type: integer
- type: 'null'
title: Question Group Id
question_key:
anyOf:
- type: string
- type: 'null'
title: Question Key
grp:
type: string
title: Grp
state:
type: string
title: State
created_at:
type: string
format: date-time
title: Created At
done_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Done At
type: object
required:
- id
- user_id
- kind
- grp
- state
- created_at
title: InputStep
ResultStep:
properties:
id:
type: integer
title: Id
project_id:
type: integer
title: Project Id
user_id:
type: integer
title: User Id
user_email:
anyOf:
- type: string
- type: 'null'
title: User Email
kind:
type: string
title: Kind
grp:
type: string
title: Grp
state:
type: string
title: State
created_at:
type: string
format: date-time
title: Created At
first_shown_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: First Shown At
clicked_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Clicked At
done_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Done At
type: object
required:
- id
- project_id
- user_id
- kind
- grp
- state
- created_at
title: ResultStep
RowError:
properties:
list:
type: string
enum:
- upsert
- done
- expire
title: List
index:
type: integer
title: Index
reason:
type: string
title: Reason
description: Why the row was refused; never echoes the values sent
type: object
required:
- list
- index
- reason
title: RowError
StepsSyncResponse:
properties:
created:
type: integer
title: Created
updated:
type: integer
title: Updated
final:
type: integer
title: Final
done:
type: integer
title: Done
description: Steps moved to done
expired:
type: integer
title: Expired
description: Steps moved to expired
already_closed:
type: integer
title: Already Closed
description: done/expire ids whose step was already done, dismissed or expired
upserted:
items:
$ref: '#/components/schemas/UpsertOutcome'
type: array
title: Upserted
errors:
items:
$ref: '#/components/schemas/RowError'
type: array
title: Errors
type: object
required:
- created
- updated
- final
- done
- expired
- already_closed
- upserted
- errors
title: StepsSyncResponse
InputRun:
properties:
status:
type: string
title: Status
description: success, failed or needs_input
finished_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Finished At
type: object
required:
- status
title: InputRun
StepsSyncRequest:
properties:
upsert:
items: {}
type: array
maxItems: 500
title: Upsert
description: StepUpsertRow objects
done:
items: {}
type: array
maxItems: 1000
title: Done
description: Step ids the person has done
expire:
items: {}
type: array
maxItems: 1000
title: Expire
description: 'Step ids withdrawn: no longer fit, not done'
additionalProperties: false
type: object
title: StepsSyncRequest
description: 'Rows are validated one by one: a bad row is reported (``errors``), the others are written.'
SyncProject:
properties:
id:
type: integer
title: Id
name:
type: string
title: Name
type: object
required:
- id
- name
title: SyncProject
UpsertOutcome:
properties:
index:
type: integer
title: Index
description: The row's index in `upsert`
step_id:
type: integer
title: Step Id
status:
type: string
enum:
- created
- updated
- final
title: Status
description: created; updated (an open step's wording refreshed); final (the step is done, dismissed or expired and was left as it is — a step is never reopened)
grp:
type: string
title: Grp
description: shown or held_back — decided by Clarity when the step was created
state:
type: string
title: State
type: object
required:
- index
- step_id
- status
- grp
- state
title: UpsertOutcome
ResultEvent:
properties:
id:
type: integer
title: Id
step_id:
type: integer
title: Step Id
project_id:
type: integer
title: Project Id
action:
type: string
title: Action
description: eligible, shown, clicked, dismissed, snoozed, done, expired
surface:
anyOf:
- type: string
- type: 'null'
title: Surface
description: overview (the browser) or sync (this API)
created_at:
type: string
format: date-time
title: Created At
type: object
required:
- id
- step_id
- project_id
- action
- created_at
title: ResultEvent
InputMember:
properties:
user_id:
type: integer
title: User Id
email:
type: string
title: Email
name:
anyOf:
- type: string
- type: 'null'
title: Name
type: object
required:
- user_id
- email
title: InputMember
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
SyncResultsResponse:
properties:
events:
items:
$ref: '#/components/schemas/ResultEvent'
type: array
title: Events
description: One page of events, oldest first (by id)
steps:
items:
$ref: '#/components/schemas/ResultStep'
type: array
title: Steps
description: The current state of every step those events are about
next_cursor:
anyOf:
- type: string
- type: 'null'
title: Next Cursor
description: Pass as `cursor` for the next page; store it to resume tomorrow. Null only when nothing was ever read
has_more:
type: boolean
title: Has More
type: object
required:
- events
- steps
- has_more
title: SyncResultsResponse
InputRoutine:
properties:
id:
type: integer
title: Id
name:
type: string
title: Name
created_by:
type: integer
title: Created By
status:
type: string
title: Status
description: draft, active or paused
admin_only:
type: boolean
title: Admin Only
description: 'Never a customer''s step: a write pointing at one is refused'
destination_emails:
items:
type: string
type: array
title: Destination Emails
has_slack:
type: boolean
title: Has Slack
created_at:
type: string
format: date-time
title: Created At
description: When the routine was made — a routine made by the person after a repeated_question step was created closes that step as done
last_finished_run:
anyOf:
- $ref: '#/components/schemas/InputRun'
- type: 'null'
description: Its latest run that is not running any more; null when none has finished
type: object
required:
- id
- name
- created_by
- status
- admin_only
- destination_emails
- has_slack
- created_at
title: InputRoutine
securitySchemes:
HTTPBearer:
type: http
scheme: bearer
HTTPBasic:
type: http
scheme: basic