n0t1fy-dev Verifications API

The verifications API from n0t1fy-dev — 2 operation(s) for verifications.

Operations 2

POST /v1/verifications Start a verification: NOTIFY makes a code and sends it by SMS #
POST /v1/verifications/{verification_id}/check Check the code a user typed #

Work with this as data

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-verifications-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 Specification

n0t1fy-dev-verifications-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: N0t1fy Dev Verifications API
  version: 0.2.0
  description: 'Operations tagged verifications 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: verifications
paths:
  /v1/verifications:
    post:
      tags:
      - verifications
      summary: 'Start a verification: NOTIFY makes a code and sends it by SMS'
      description: 'NOTIFY makes a random six-digit code, sends it to `to` with one of the code templates, and answers with the verification. The code is never in any answer, log or table: only a keyed hash of it is kept, until the verification ends (at most about an hour after the code expires). It works for 10 minutes and 5 checks, once. A new start for the same number replaces the previous code.


        With a test key, only the test numbers +995512345670 to +995512345679 are accepted, and their code is always `000000`; nothing is sent or charged. A live key sends a real SMS and spends one credit.


        `201` with `status: "pending"`: the code was sent (or may have been: read `message.status`); show the code-entry field at once. `201` with `status: "failed"`: the provider refused the SMS; `error` says why. Rarely, `201` with `status: "canceled"`: a newer start for the same number, or a claim, ended this code while the start was in flight, and a replayed start can even show `approved`: act only on a check''s `200`. Requires an `Idempotency-Key`: replaying it with the identical body returns the original verification with `200` (it may have been approved since, which is not a check result), and reusing it with a different body returns `409`. Then check the code the user types with POST /v1/verifications/{id}/check.'
      operationId: start_verification_route_v1_verifications_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/StartVerificationRequest'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponse'
        '200':
          description: 'Idempotent replay: the original verification, as it is now.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponse'
        '400':
          description: 'Invalid body, recipient or template, or a missing Idempotency-Key. `test_number_required`: a test key with a number that is not a test number.'
          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: The project is suspended.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '402':
          description: '`insufficient_credits`: a live key''s project has no credit left for the SMS, or its subscription has ended. Nothing was sent.'
          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: '`too_many_verifications`: this number had 5 verifications in the last hour or 10 in the last 24 hours from this project; the message says when the next is allowed. `rate_limited`: a per-minute limit is used up (5 sends a minute to one number, 60 sends a minute per project); the message names it. `daily_limit_reached`: the free tier''s daily limit. Nothing was sent. 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: '`provider_unavailable`: the provider was unreachable; nothing was sent, and it is safe to retry with the same Idempotency-Key. `verifications_disabled`: the operator switched verifications off; nobody is let in until they are back.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
      security:
      - bearerAuth: []
  /v1/verifications/{verification_id}/check:
    post:
      tags:
      - verifications
      summary: Check the code a user typed
      description: 'Answers `200` with the verification, `status: "approved"`, only when the code is right, for the number the code was sent to, within 10 minutes, with fewer than 5 wrong attempts before it, and never approved before. Every other answer is an error. Let the user in only when a check answers `200` with status `approved`; treat every other answer, a timeout and a network error as not approved. Branch on `error.code`, never on the HTTP status alone.


        `to` must be the number your application is about to mark as verified. Every check spends one attempt, including a wrong number; a malformed `code` (not six digits as a string) or `to` spends none. A check is not idempotent: if its answer is lost, the attempt may have approved the code, which then cannot be used again, so ask the user for a new code. Do not retry a check by itself.'
      operationId: check_verification_route_v1_verifications__verification_id__check_post
      parameters:
      - name: verification_id
        in: path
        required: true
        schema:
          type: string
          title: Verification Id
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckVerificationRequest'
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApprovedVerificationResponse'
        '400':
          description: '`invalid_request`: a malformed body, or a `code` that is not six digits written as a string. `invalid_recipient`: `to` is not +9955 and eight digits. No attempt was spent.'
          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: The project is suspended.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '404':
          description: '`verification_not_found`: no such verification in this project.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '409':
          description: '`verification_closed`: already approved, replaced by a newer code, or its SMS was never sent. Offer a new code.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '410':
          description: '`verification_expired`: more than 10 minutes since the start.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '422':
          description: '`incorrect_code`: a wrong code; the message says how many attempts are left. `too_many_attempts`: a wrong code that was the fifth, or any check after it: offer a new code. `recipient_mismatch`: `to` is not the number the code was sent to; the attempt is spent and the code was not compared.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
        '429':
          description: '`rate_limited`: more than 120 checks a minute in this project (test and live keys counted apart). No attempt was spent. 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: '`verifications_disabled`: the operator switched verifications off; nobody is let in until they are back.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorResponse'
      security:
      - bearerAuth: []
components:
  schemas:
    CheckVerificationRequest:
      properties:
        to:
          type: string
          title: To
          description: 'The number your application is about to mark as verified, in E.164 format. It must be the number the verification was started for: otherwise the answer is `recipient_mismatch`, and the attempt is spent.'
          examples:
          - '+995591234567'
        code:
          type: string
          title: Code
          description: 'The code the user typed: six digits, as a JSON string, so a leading zero is never lost. Surrounding spaces are trimmed. Anything else is refused with `400` and spends no attempt.'
          examples:
          - '482913'
      additionalProperties: false
      type: object
      required:
      - to
      - code
      title: CheckVerificationRequest
      examples:
      - code: '482913'
        to: '+995591234567'
    VerificationResponse:
      properties:
        id:
          type: string
          title: Id
          description: 'Opaque verification identifier: the check needs it.'
        object:
          type: string
          const: verification
          title: Object
          description: Always `verification`.
        to:
          type: string
          title: To
          description: 'Masked number: country code and first digit, then the last two digits.'
          examples:
          - +9955••••••67
        status:
          type: string
          enum:
          - pending
          - approved
          - failed
          - expired
          - canceled
          title: Status
          description: '`pending` until a check approves it or it ends. Only `pending` changes; a `pending` verification past `expires_at` is shown as `expired`. Let a user in only on a check that answers `200` with `approved`, never on this field read elsewhere: a replayed start can show `approved` too.'
        template:
          type: string
          title: Template
          description: The template of the SMS that carried the code.
        locale:
          type: string
          enum:
          - ka
          - en
          title: Locale
          description: The language of that SMS.
        attempts_remaining:
          type: integer
          title: Attempts Remaining
          description: 'Checks left before the code stops working: 5 at the start, one fewer for each wrong code, and 0 once the verification is no longer `pending` (approved, expired, canceled, or ended by wrong codes).'
          examples:
          - 5
        expires_at:
          type: string
          title: Expires At
          description: 'ISO 8601 UTC: 10 minutes after the start request. No check works after it.'
        approved_at:
          anyOf:
          - type: string
          - type: 'null'
          title: Approved At
          description: When a check approved it, or `null`.
        error:
          anyOf:
          - $ref: '#/components/schemas/VerificationError'
          - type: 'null'
          description: '`null` unless it ended without an approval (not for `expired`).'
        message:
          $ref: '#/components/schemas/MessageResponse'
          description: The SMS that carried the code. Read its delivery with GET /v1/messages/{id}; show the code-entry field at once, without waiting for `delivered`.
        created_at:
          type: string
          title: Created At
          description: ISO 8601 UTC, second precision, `Z` suffix.
        updated_at:
          type: string
          title: Updated At
          description: ISO 8601 UTC time of the most recent change.
      type: object
      required:
      - id
      - object
      - to
      - status
      - template
      - locale
      - attempts_remaining
      - expires_at
      - approved_at
      - message
      - created_at
      - updated_at
      title: VerificationResponse
      description: One verification. The code, its hash and the full number are never included.
      examples:
      - attempts_remaining: 5
        created_at: '2026-10-20T09:15:30Z'
        expires_at: '2026-10-20T09:25:30Z'
        id: ver_01J8XW7K2N9P4Q6R8S0T2V4W6X
        locale: ka
        message:
          created_at: '2026-10-20T09:15:30Z'
          id: msg_01J8XW7K3B5D7F9H1K3M5P7R9T
          object: message
          segments: 1
          status: submitted
          to: +9955••••••67
          updated_at: '2026-10-20T09:15:31Z'
        object: verification
        status: pending
        template: verification_code
        to: +9955••••••67
        updated_at: '2026-10-20T09:15:31Z'
    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.
    StartVerificationRequest:
      properties:
        to:
          type: string
          title: To
          description: 'The phone number to verify, in E.164 format: `+9955` followed by eight digits. With a test key (`sk_test_`), only the test numbers +995512345670 to +995512345679 are accepted, and their code is always `000000`.'
          examples:
          - '+995591234567'
        template:
          type: string
          enum:
          - verification_code
          - login_code
          - password_reset_code
          title: Template
          description: Which message carries the code. NOTIFY fills in the code, and the minutes where the template names them (10).
          default: verification_code
          examples:
          - verification_code
        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
      title: StartVerificationRequest
      examples:
      - locale: ka
        template: verification_code
        to: '+995591234567'
    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'
    ApprovedVerificationResponse:
      properties:
        id:
          type: string
          title: Id
          description: 'Opaque verification identifier: the check needs it.'
        object:
          type: string
          const: verification
          title: Object
          description: Always `verification`.
        to:
          type: string
          title: To
          description: 'Masked number: country code and first digit, then the last two digits.'
          examples:
          - +9955••••••67
        status:
          type: string
          const: approved
          title: Status
          description: 'Always `approved`: every other outcome of a check is an error.'
        template:
          type: string
          title: Template
          description: The template of the SMS that carried the code.
        locale:
          type: string
          enum:
          - ka
          - en
          title: Locale
          description: The language of that SMS.
        attempts_remaining:
          type: integer
          title: Attempts Remaining
          description: 'Checks left before the code stops working: 5 at the start, one fewer for each wrong code, and 0 once the verification is no longer `pending` (approved, expired, canceled, or ended by wrong codes).'
          examples:
          - 5
        expires_at:
          type: string
          title: Expires At
          description: 'ISO 8601 UTC: 10 minutes after the start request. No check works after it.'
        approved_at:
          type: string
          title: Approved At
          description: 'ISO 8601 UTC: when this check approved it.'
        error:
          anyOf:
          - $ref: '#/components/schemas/VerificationError'
          - type: 'null'
          description: '`null` unless it ended without an approval (not for `expired`).'
        message:
          $ref: '#/components/schemas/MessageResponse'
          description: The SMS that carried the code. Read its delivery with GET /v1/messages/{id}; show the code-entry field at once, without waiting for `delivered`.
        created_at:
          type: string
          title: Created At
          description: ISO 8601 UTC, second precision, `Z` suffix.
        updated_at:
          type: string
          title: Updated At
          description: ISO 8601 UTC time of the most recent change.
      type: object
      required:
      - id
      - object
      - to
      - status
      - template
      - locale
      - attempts_remaining
      - expires_at
      - approved_at
      - message
      - created_at
      - updated_at
      title: ApprovedVerificationResponse
      description: 'The only success a check has. As the check''s response model it makes the rule

        "a 2xx is only an approval" the code''s own: anything else answers 500, not 200

        (the 2026-10-15 checkpoint, item 4). The MCP check tool validates through it too.'
      examples:
      - attempts_remaining: 5
        created_at: '2026-10-20T09:15:30Z'
        expires_at: '2026-10-20T09:25:30Z'
        id: ver_01J8XW7K2N9P4Q6R8S0T2V4W6X
        locale: ka
        message:
          created_at: '2026-10-20T09:15:30Z'
          id: msg_01J8XW7K3B5D7F9H1K3M5P7R9T
          object: message
          segments: 1
          status: submitted
          to: +9955••••••67
          updated_at: '2026-10-20T09:15:31Z'
        object: verification
        status: pending
        template: verification_code
        to: +9955••••••67
        updated_at: '2026-10-20T09:15:31Z'
    VerificationError:
      properties:
        code:
          type: string
          title: Code
          description: '`too_many_attempts`, `replaced` (a newer code was sent to the number), `project_claimed`, or the error of the SMS that carried the code when it was never sent (`provider_rejected`, `provider_unavailable`, …).'
          examples:
          - replaced
        message:
          type: string
          title: Message
          description: Human-readable explanation. Wording may change.
      type: object
      required:
      - code
      - message
      title: VerificationError
      description: Why a verification ended without an approval.
  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