Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Instasent product Readiness API
description: '### Overview
The Instasent Product API provides a comprehensive set of tools for managing **organizations** and **projects** within the Instasent platform. This API is designed to help businesses organize customer data, manage team permissions, and set up projects for targeted marketing and customer engagement. ### What is the Product API? The Product API is Instasent''s primary management API for high-level entities and operations. It provides comprehensive tools for managing your organization''s customer data platform, from initial setup to ongoing operations. > **NOTE**:
> - To access the Product API you need a Product Token and your Project UID, you can get them in your project settings. **Core Purpose**: The Product API enables you to:
- **Manage Organizations & Projects**: View organization information, create and configure projects, and manage project-level settings
- **Configure Data Sources**: Create and manage API data sources that serve as entry points for customer data
- **Access Unified Audience Data**: Query, search, and retrieve contacts from your project''s unified audience, where data from multiple sources is automatically merged
- **Track Customer Events**: Search and analyze customer interaction events to understand behavior patterns
- **Manage Segments**: View and work with audience segments for targeted marketing
- **Monitor Campaigns & Automations**: Access campaign and automation details, configurations, and status
- **Send Direct Messages**: Create and send direct SMS messages to audience contacts, and manage SMS senders
- **Ingest Data**: Push contacts and events to data sources via the Ingest API (integrated into the Product API)
**Key Entities**:
- **Organizations**: Represent companies using Instasent. Each organization has its own settings, billing information, user accounts, and API tokens. Organizations can contain multiple projects. - **Projects**: Isolated environments within an organization where customer data, contacts, events, segments, campaigns, and automations are managed. Projects allow you to organize different brands, customer segments, or marketing initiatives separately. - **Data Sources**: Collections of contacts and events that feed into a project. Multiple data sources can contribute to a single project''s unified audience. - **Contacts**: Individual records representing customers, leads, or audience members. Contacts from different data sources are automatically merged into a unified `Audience Contact` when they share matching unique identifiers. - **Events**: Immutable records of customer interactions, such as purchases, page views, email opens, or any custom activity. Events enrich contact profiles and can trigger automations. ### Key Features and Benefits
The Product API empowers organizations by providing comprehensive tools for customer data management and marketing automation:
1. **Data Ingestion & Management**:
- Create and manage API data sources for ingesting contacts and events
- Push contacts and events to data sources via the Ingest API
- View datasource statistics and stream specifications
- Delete contacts from data sources when needed
2. **Unified Audience Management**:
- Access a project''s unified audience where contacts from multiple data sources are automatically merged
- Search and filter contacts using powerful QueryFilter syntax
- Scroll through large contact lists with cursor-based pagination
- Retrieve contacts by ID, user identifier, phone number, or email address
- View contact events and interaction history
3. **Event Tracking & Analysis**:
- Search and filter audience events using the Event Filtering system
- Scroll through event history with pagination support
- Access event data to understand customer behavior and interactions
4. **Segmentation & Targeting**:
- View and manage audience segments (static and dynamic)
- Scroll contacts within specific segments
- Use segments for targeted marketing campaigns
5.'
version: 2.0.0
contact:
email: dev@instasent.com
url: https://instasent.com
name: Instasent
license:
name: Instasent
url: https://www.instasent.com/aviso-legal
servers:
- url: https://api.instasent.com/v1
description: Instasent product API
security:
- BearerAuth: []
- OAuth2: []
tags:
- name: Readiness
description: 'Setup readiness endpoints — "what''s left to configure" and "what needs
attention" for a project or one of its channels, plus the real per-country
send capability. Always recomputed from current data (no cached "done"
flag); steps carry stable keys only (copy/i18n is the client''s).'
paths:
/project/{project}/readiness:
get:
summary: Project setup readiness
description: '"What''s left to configure" for a project home, as a live report of
onboarding steps. Always recomputed from current data — a completed
step re-opens if its condition regresses; there is no cached "done"
flag. The step set depends on the project type (`standard` vs
`api_sms`). Steps carry only stable keys (no copy); blockers are the
steps that gate operation, and the home scope never returns warnings.
**Rate Limit**: [m] moderate - varies by subscription tier'
tags:
- Readiness
parameters:
- $ref: '#/components/parameters/ProjectPath'
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
entity:
$ref: '#/components/schemas/ReadinessReport'
required:
- entity
examples:
standard:
summary: Standard project, partially configured
value:
entity:
scope: project
projectType: standard
channel: null
percent: 29
operational: false
steps:
- key: import
completed: true
isBlocker: true
disabled: false
skipped: false
skippable: true
- key: channels
completed: true
isBlocker: true
disabled: false
skipped: false
skippable: true
- key: legal-profile
completed: false
isBlocker: true
disabled: false
skipped: false
skippable: true
- key: funds
completed: false
isBlocker: true
disabled: false
skipped: false
skippable: true
- key: campaign
completed: false
isBlocker: false
disabled: false
skipped: false
skippable: true
- key: automation
completed: false
isBlocker: false
disabled: false
skipped: true
skippable: true
- key: brand
completed: false
isBlocker: false
disabled: false
skipped: false
skippable: true
warnings: []
reach: null
computedAt: '2026-09-05T09:41:12Z'
'401':
$ref: '#/components/responses/UnauthorizedError'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitError'
operationId: getProjectByProjectReadiness
x-operation-id-source: derived
/project/{project}/readiness/channel/{channel}:
get:
summary: Channel setup readiness
description: '"What''s left to configure" for one channel of a project. Returns
onboarding `steps` plus the `recommended-registrations` warning:
countries a sender should be registered for and is not.
What a carrier or regulator DID to a register (`pending-review`,
`rejected-registration`) is no longer here: it moved to
`GET /project/{project}/attention` on 2026-09-05, keeping those key
names. One fact has one owner.
Warnings only appear once the channel has an active sender. SMS has
no per-country onboarding step (auto-accepted); RCS keeps
`register-country`. The report also carries `reach` — the countries
you can send to right now on this channel (union plus a per-sender
breakdown); it is null only on the project home scope.
**Rate Limit**: [m] moderate - varies by subscription tier'
tags:
- Readiness
parameters:
- $ref: '#/components/parameters/ProjectPath'
- name: channel
in: path
required: true
description: Channel to report on.
schema:
type: string
enum:
- sms
- rcs
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
properties:
entity:
$ref: '#/components/schemas/ReadinessReport'
required:
- entity
examples:
sms:
summary: SMS channel with a sender and registers in review / rejected
value:
entity:
scope: channel
projectType: standard
channel: sms
percent: 50
operational: true
steps:
- key: add-sender
completed: true
isBlocker: true
disabled: false
skipped: false
skippable: true
- key: send-first-sms-campaign
completed: false
isBlocker: false
disabled: false
skipped: false
skippable: true
warnings:
- key: recommended-registrations
severity: error
count: 2
rows:
- channel: sms
senderId: 5f3a9b2c4d1e0f00112233ab
senderName: MYBRAND
country: ES
source: regulation
urgency: urgent
audienceCount: null
audienceShare: null
reason: null
- channel: sms
senderId: 5f3a9b2c4d1e0f00112233ab
senderName: MYBRAND
country: FR
source: audience
urgency: null
audienceCount: 412
audienceShare: 0.0824
reason: null
reach:
reachableCountries:
- PT
senders:
MYBRAND:
- PT
senderCount: 1
defaultSender: MYBRAND
computedAt: '2026-09-05T09:41:12Z'
'401':
$ref: '#/components/responses/UnauthorizedError'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimitError'
operationId: getProjectByProjectReadinessChannelByChannel
x-operation-id-source: derived
components:
schemas:
ReadinessReach:
type: object
description: 'The countries the channel can send to right now ("countries you
can send to"): the union plus the per-sender breakdown. Regulation-
aware (register effective status): a country is reachable unless a
registration is required/pending, an enforced regulation gates it,
or the register is rejected/revoked. SMS is default-allow over the
operator catalog (same set as the SMS sender `acceptedCountries`);
RCS is register-driven and may be stricter than the RCS sender
`acceptedCountries`, which is carrier-only.
'
properties:
reachableCountries:
type: array
description: 'Union of reachable countries across the channel''s active
senders (ISO 3166-1 alpha-2), deduplicated and sorted.
'
items:
type: string
example:
- ES
- FR
- PT
senders:
type: object
description: 'Per-sender breakdown keyed by sender alias (SMS `from`,
RCS agent name). Senders that reach no country are omitted.
Normalize on read:
treat `[]` and `{}` as the same empty map, and never call
map-only or list-only operations on it unguarded.
'
additionalProperties:
type: array
items:
type: string
example:
ACME:
- ES
- PT
INFO:
- FR
senderCount:
type: integer
description: 'How many ACTIVE senders the channel has, including those
that reach no country. NOT the size of `senders`: an RCS
agent with no accepted register counts here and is absent
there, which is exactly the case worth telling apart.
'
defaultSender:
type:
- string
- 'null'
description: 'The project default sender''s alias, when it is one of the
active senders. It matters because a send that names no
sender uses it, so the union above can promise more than a
single send would actually reach.
Always null on `api_sms` projects even when the field is
set: nothing there picks it, so naming it would promise
the reach of a sender no request uses.
'
required:
- reachableCountries
- senders
- senderCount
- defaultSender
additionalProperties: false
ResponseErrorDetail:
type: object
properties:
title:
type: string
status:
type: integer
detail:
type: string
required:
- title
- status
- detail
x-stoplight:
id: v3njemo17ya0e
ReadinessWarning:
description: 'A signal the user cannot simply complete. ONE warning exists:
`recommended-registrations`.
`pending-review` and `rejected-registration` used to be the other
two and MOVED to `GET /project/{project}/attention` on 2026-09-05,
keeping their key names: a carrier or regulator acting on a
register that was submitted is an event, not a configuration gap.
It stays a union discriminated by `key`, with one member. Narrow
on the key and `rows` narrows with it; the next warning to arrive
inherits that instead of adding nullable fields to this one.
'
oneOf:
- $ref: '#/components/schemas/ReadinessRecommendationWarning'
discriminator:
propertyName: key
mapping:
recommended-registrations: '#/components/schemas/ReadinessRecommendationWarning'
ResponseErrorMessage:
type: object
properties:
message:
type: string
code:
type: integer
required:
- message
x-stoplight:
id: nzjbrnkttcnxo
ReadinessRecommendationRow:
type: object
description: 'A register that does NOT exist and should. Rows of
`recommended-registrations`.
The mirror image of the register rows that moved to the attention
endpoint: there is no
`effectiveStatus` because there is no register. The informative
field is `source`, which says why the country is recommended.
A country already covered by a non-archived register on that
sender never appears here, whatever its status.
'
properties:
channel:
type: string
enum:
- sms
- rcs
senderId:
type: string
senderName:
type: string
country:
type: string
description: ISO 3166-1 alpha-2 country code.
source:
type: string
enum:
- regulation
- audience
- org
description: 'Why it is recommended. `regulation` rows are emitted per
active sender (regulators register senders, not projects);
`audience` and `org` rows are emitted once, against the
sender a send would actually use.
'
urgency:
type:
- string
- 'null'
enum:
- urgent
- upcoming
- far
- null
description: How close the regulator's deadline is. Null unless `source` is `regulation`.
audienceCount:
type:
- integer
- 'null'
description: Reachable contacts in that country. Null unless `source` is `audience`.
audienceShare:
type:
- number
- 'null'
format: float
minimum: 0
maximum: 1
description: '`audienceCount` over the project''s contacts with a mobile phone,
between 0 and 1 and unrounded. The same base the audience
threshold is measured against. Null unless `source` is `audience`.
'
reason:
type:
- string
- 'null'
enum:
- sender-substituted
- null
description: '`sender-substituted` when the country IS reachable for this
sender, but only with a sender substituted on delivery, so the
recipient may see a different sender. The row stays, and stays
urgent: that delivery is a last resort, to be fixed by
registering. Null otherwise.
'
required:
- channel
- senderId
- senderName
- country
- source
- urgency
- audienceCount
- audienceShare
- reason
additionalProperties: false
ReadinessStep:
type: object
description: A single onboarding milestone ("what's left").
properties:
key:
type: string
description: Stable identifier of the step (no copy; the client owns i18n).
example: add-sender
completed:
type: boolean
isBlocker:
type: boolean
description: When true, the project/channel cannot operate until this step is completed.
disabled:
type: boolean
description: When true, a prerequisite is not yet met, so the user cannot act on it yet.
skipped:
type: boolean
description: 'Whether the user hid this step from the dashboard checklist.
A PREFERENCE, not a fact: the backend reports it and honors
none of it, so `completed`, `isBlocker`, `disabled`, `percent`
and `operational` are all computed as if it were false. Each
client decides what to do with it.
'
skippable:
type: boolean
description: 'Whether a user may hide this step at all. True for every step
today; it exists so the day one becomes mandatory, the decision is
declared once here and every surface obeys it.
⚠ It outranks a stored skip: on a step that is not skippable,
`skipped` is always false even if a preference was saved before it
stopped being skippable. Nothing ever says "you hid this" about
something that can no longer be hidden, and nobody has to clean up
the old attributes.
'
required:
- key
- completed
- isBlocker
- disabled
- skipped
- skippable
additionalProperties: false
ReadinessRecommendationWarning:
type: object
description: 'Countries a sender should be registered for and is not. The only
warning the user can act on directly, so it comes first in the
array.
Audience-sourced rows are omitted when the audience''s country
distribution is unavailable: the project has no audience, or it
could not be obtained at that moment. The distribution is refreshed
at most every six hours, so a recent import can take that long to
show here. Regulation and org rows are always present when they
apply, so an empty audience contribution is silent, never an error.
'
properties:
key:
type: string
enum:
- recommended-registrations
severity:
type: string
enum:
- error
count:
type: integer
description: Total recommendations. May exceed `rows` length, which is capped at 8.
rows:
type: array
items:
$ref: '#/components/schemas/ReadinessRecommendationRow'
required:
- key
- severity
- count
- rows
additionalProperties: false
ReadinessReport:
type: object
description: 'Live readiness report for a project (home) or a channel. Always
recomputed; never cached as "done".
'
properties:
scope:
type: string
enum:
- project
- channel
projectType:
type: string
enum:
- standard
- api_sms
channel:
type:
- string
- 'null'
description: The channel for a channel-scoped report; null for the project home.
percent:
type: integer
description: Completion percentage (0-100); 100 when there are no steps.
operational:
type: boolean
description: True when no incomplete blocker steps remain.
steps:
type: array
items:
$ref: '#/components/schemas/ReadinessStep'
warnings:
type: array
description: Always empty for the project (home) scope.
items:
$ref: '#/components/schemas/ReadinessWarning'
reach:
description: 'Channel send reach — the countries you can send to right
now, with a per-sender breakdown. Present on channel-scoped
reports; null for the project (home) scope.
'
allOf:
- $ref: '#/components/schemas/ReadinessReach'
computedAt:
type: string
format: date-time
description: 'When the backend computed this report (UTC ISO-8601).
There is no cache behind it, so at the moment of the
response it is always "now". It travels because the CLIENT
may hold it: anything that fetches once and reuses the
answer later needs to know how old what it holds is.
'
example: '2026-09-04T16:20:31Z'
required:
- scope
- projectType
- channel
- percent
- operational
- steps
- warnings
- reach
- computedAt
additionalProperties: false
responses:
NotFound:
description: Resource can't be found
content:
application/json:
schema:
$ref: '#/components/schemas/ResponseErrorDetail'
UnauthorizedError:
description: You are missing or using bad credentials
content:
application/json:
schema:
$ref: '#/components/schemas/ResponseErrorMessage'
RateLimitError:
description: You reached your endpoint rate limit
content:
application/json:
schema:
$ref: '#/components/schemas/ResponseErrorMessage'
parameters:
ProjectPath:
name: project
in: path
description: Project UID (e.g., 'my-project-123')
required: true
schema:
type: string
securitySchemes:
BearerAuth:
description: Token with permissions to access the endpoint
type: http
scheme: bearer
OAuth2:
description: 'OAuth 2.1 Authorization Code flow with PKCE, for applications that act in a
user''s name instead of using a token the user pasted. The resulting access
token is an ordinary Product API bearer token (`isoa_` prefix) with a
24-hour lifetime, refreshed through `POST /oauth/token`.
Register the client first with `POST /oauth/register`, or use a `client_id`
issued by Instasent. PKCE is mandatory and only `S256` is accepted; there is
no client secret. Discover these URLs at runtime from
`/.well-known/oauth-authorization-server` rather than hard-coding them. All
three are on this API host; the authorization URL is a browser redirect that
hands the user to the dashboard''s consent screen.
The scopes below are the same product permissions the API returns in
`GET /` and the dashboard shows when creating a token. Which of them a
client may be granted depends on its lane: MCP clients are limited to a
curated, agent-safe subset, while API clients may be offered the full set.
The final grant is always intersected with the authorizing user''s roles and
the organization''s plan.
'
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://api.instasent.com/oauth/authorize
tokenUrl: https://api.instasent.com/oauth/token
refreshUrl: https://api.instasent.com/oauth/token
scopes:
ACCOUNT_READ: Read access to organization account details and funds
PROJECT_DATASOURCE_READ: Read-only access to datasources
PROJECT_DATASOURCE_WRITE: Create and modify datasources
PROJECT_AUDIENCE_READ: Read access to audience contacts
PROJECT_AUDIENCE_WRITE: Write access to audience contacts
PROJECT_AUDIENCE_LIST: List and scroll audience contacts
PROJECT_AUDIENCE_DATA_BASIC: Access to basic contact data
PROJECT_AUDIENCE_DATA_FULL: Access to full contact data
PROJECT_AUDIENCE_DATA_EVENTS: Access to audience events
PROJECT_AGGREGATIONS: Access to audience and event aggregations
PROJECT_SEGMENT_WRITE: Save an audience filter as a segment
PROJECT_CAMPAIGN_READ: Read access to campaigns
PROJECT_CAMPAIGN_WRITE: Create a campaign draft
PROJECT_AUTOMATION_READ: Read access to automations
PROJECT_DIRECT_READ: Messaging read access
PROJECT_DIRECT_WRITE: Messaging write access
x-stoplight:
id: xl7ao4m61duhz