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/n0t1fy-dev:n0t1fy-dev-messages-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: N0t1fy Dev Messages API
version: 0.2.0
description: 'Operations tagged messages across 2 of this provider''s published API definitions: n0t1fy-dev-api-openapi.json, n0t1fy-dev-openapi.json. Each path carries the servers of the definition it was published in.'
tags:
- name: Messages
paths:
/v1/messages:
post:
tags:
- Messages
summary: Send one transactional SMS
description: 'Validates, records, and submits one message.
`201` means the message resource was created — including when the provider rejected it, in which case the body carries `status: "failed"` and an `error`. Requires an `Idempotency-Key`: replaying it with the identical body returns the original message with `200`, while reusing it with a different body returns `409`.'
operationId: create_message_route_v1_messages_post
parameters:
- name: Idempotency-Key
in: header
required: true
schema:
type: string
minLength: 1
maxLength: 200
title: Idempotency-Key
description: One unique value per logical message or verification start, such as a UUID. Reuse it only to retry the identical request.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateMessageRequest'
responses:
'201':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/MessageResponse'
'200':
description: 'Idempotent replay: the original message, unchanged.'
content:
application/json:
schema:
$ref: '#/components/schemas/MessageResponse'
'400':
description: Invalid request body, recipient, template, or variables, or a missing Idempotency-Key. The error message names what to change.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'401':
description: Missing, malformed, unknown, or revoked API key.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: '`project_suspended`: the project is suspended. `recipient_not_on_team`: a team template (`audience` team on /templates) to a number not confirmed on the project''s team, or, with a test key, to a number other than the test numbers. Nothing was sent or charged; the project''s owner adds team numbers on the dashboard. Do not retry as it is.'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'402':
description: '`insufficient_credits`: a live key''s project has too few credits for this message, or its subscription has ended and the credits left in its last month expired. Nothing was sent. The message says when sending resumes. Test keys never spend credits.'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'409':
description: The Idempotency-Key was reused with a different body.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'429':
description: '`rate_limited`: a per-minute limit is used up (5 sends a minute to one number, 60 sends a minute per project), or the 30 team alerts an hour to one number; the message names it, and when it frees. `daily_limit_reached`: the free tier''s daily segment limit is used up; do not retry before the reset time named in the message (midnight UTC). Nothing was sent in either case. A retry with the same Idempotency-Key and body never gets `rate_limited`: it is answered with the original. Every `429` carries a `Retry-After` header (whole seconds, rounded up) and `error.retry_at` (ISO 8601 UTC): the same moment, when the limit frees.'
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
headers:
Retry-After:
description: Whole seconds until the limit frees, rounded up and at least 1.
schema:
type: integer
minimum: 1
'503':
description: The provider was unreachable or busy, and nothing was sent. Safe to retry, including with the same Idempotency-Key.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearerAuth: []
/v1/messages/{message_id}:
get:
tags:
- Messages
summary: Read one message
description: 'Returns the current normalized state of a message owned by the authenticated project. Delivery confirmations arrive asynchronously, so poll this rather than assuming a fixed delay. Poll only while `status` is `queued` or `submitted`: no other status ever changes. Always set a time limit (a few minutes for a code); when it passes, record the message as unconfirmed and do not send it again.'
operationId: get_message_route_v1_messages__message_id__get
parameters:
- name: message_id
in: path
required: true
schema:
type: string
title: Message Id
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/MessageResponse'
'401':
description: Missing, malformed, unknown, or revoked API key.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'403':
description: The project is suspended.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
'404':
description: No such message in this project.
content:
application/json:
schema:
$ref: '#/components/schemas/ApiErrorResponse'
security:
- bearerAuth: []
components:
schemas:
MessageError:
properties:
code:
type: string
title: Code
description: Stable machine-readable code, safe to branch on.
examples:
- provider_rejected
message:
type: string
title: Message
description: Human-readable explanation. Wording may change; the code will not.
examples:
- The delivery provider rejected the message.
type: object
required:
- code
- message
title: MessageError
description: A safe, provider-neutral explanation attached to a message.
ApiErrorResponse:
properties:
error:
$ref: '#/components/schemas/ApiErrorBody'
type: object
required:
- error
title: ApiErrorResponse
description: Every error response in this API has this shape.
ApiErrorBody:
properties:
code:
type: string
title: Code
description: Stable machine-readable error code.
examples:
- invalid_recipient
message:
type: string
title: Message
description: Human-readable explanation, written to be actionable.
examples:
- 'The recipient must be a Georgian mobile number in E.164 format: +9955XXXXXXXX.'
request_id:
anyOf:
- type: string
- type: 'null'
title: Request Id
description: Echoes the `X-Request-Id` response header; quote it when reporting a problem.
examples:
- req_01J8XW7K2N9P4Q6R8S0T2V4W6X
retry_at:
anyOf:
- type: string
- type: 'null'
title: Retry At
description: 'Only on a `429` (`rate_limited`, `daily_limit_reached`, `too_many_verifications`): when the limit frees, ISO 8601 UTC with a `Z` suffix, the same moment the `Retry-After` header counts down to. Show a countdown to it; do not retry before it. Absent from every other error.'
examples:
- '2026-10-16T12:35:00Z'
type: object
required:
- code
- message
title: ApiErrorBody
MessageResponse:
properties:
id:
type: string
title: Id
description: Opaque message identifier. Store it to read the status later.
object:
type: string
const: message
title: Object
description: Always `message`.
to:
type: string
title: To
description: 'Masked recipient: country code and first digit, then the last two digits.'
examples:
- +9955••••••67
status:
type: string
enum:
- queued
- submitted
- delivered
- undeliverable
- failed
- unknown
title: Status
description: Normalized delivery state. `submitted` means the provider accepted the request, not that a handset received it.
segments:
anyOf:
- type: integer
- type: 'null'
title: Segments
description: SMS segments this message occupies — the unit the provider bills. `null` only for messages created before segment counting existed.
examples:
- 1
error:
anyOf:
- $ref: '#/components/schemas/MessageError'
- type: 'null'
description: '`null` unless the message failed or was undeliverable.'
created_at:
type: string
title: Created At
description: ISO 8601 UTC, second precision, `Z` suffix.
examples:
- '2026-09-14T09:15:30Z'
updated_at:
type: string
title: Updated At
description: ISO 8601 UTC time of the most recent change.
examples:
- '2026-09-14T09:15:31Z'
type: object
required:
- id
- object
- to
- status
- segments
- created_at
- updated_at
title: MessageResponse
description: One message resource. Text, full recipient, and provider internals are never included.
examples:
- created_at: '2026-09-14T09:15:30Z'
id: msg_01J8XW7K2N9P4Q6R8S0T2V4W6X
object: message
segments: 1
status: submitted
to: +9955••••••67
updated_at: '2026-09-14T09:15:31Z'
CreateMessageRequest:
properties:
to:
type: string
title: To
description: 'Recipient in E.164 format: `+9955` followed by eight digits. No other country or format is accepted, and numbers are never normalized on your behalf.'
examples:
- '+995591234567'
template:
type: string
title: Template
description: 'Which message to send. Message text is never free-form: every message is rendered from one of these templates.
- `verification_code` (`code`): Your verification code is {code}. Do not share it with anyone.
- `login_code` (`code`): Your sign-in code is {code}. If you did not request it, ignore this message.
- `password_reset_code` (`code`, `minutes`): Your password reset code is {code}. It expires in {minutes} minutes.
- `service_down` (`service`): Alert: {service} is down. Team only.
- `service_up` (`service`): Resolved: {service} is up again. Team only.
- `incident_opened` (`incident`): Urgent: incident {incident} needs attention. Team only.
- `support_ticket_urgent` (`ticket`): Urgent: support ticket {ticket} is waiting for a reply. Team only.
- `job_failed` (`job`): Failed: scheduled job {job} did not finish. Team only.
- `agent_alert` (`agent`, `count`): {agent}: {count} new updates. Check your app. Team only.
Team templates go only to numbers confirmed on the project''s team on the dashboard (a test key: the test numbers only); any other number answers `403 recipient_not_on_team`. Every template, its blanks and who it may go to: /templates.'
examples:
- verification_code
variables:
additionalProperties: true
type: object
title: Variables
description: Values for the template's placeholders, all as JSON strings. A `code` is 4 to 8 digits; `minutes` is 1 to 999; an `incident` or `ticket` 1 to 8 digits; a `count` 1 to 99; an `agent` `your_agent` or `ai_assistant`; a `service` or `job` a name on the project's team page (a live key). Values that look like a link, a web address, or a phone number are refused.
examples:
- code: '482913'
locale:
type: string
enum:
- ka
- en
title: Locale
description: 'Language of the message: `ka` (Georgian, the default) or `en`.'
default: ka
examples:
- ka
additionalProperties: false
type: object
required:
- to
- template
- variables
title: CreateMessageRequest
examples:
- template: verification_code
to: '+995591234567'
variables:
code: '482913'
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'An API key: `sk_test_…` (fake provider, never sends) or `sk_live_…`. Get a test key from `POST /v1/test-keys`.'
x-refined-from:
- n0t1fy-dev-api-openapi.json
- n0t1fy-dev-openapi.json