pricklymails-com Auth API

Registration, login, token refresh, password reset, and 2FA.

Operations 11

POST /api/auth/2fa/verify Completes a sign-in that requires two-factor authentication #
POST /api/auth/confirm Confirms an account with the six-digit code mailed at signup, and signs it in #
POST /api/auth/forgot-password Requests a password reset email #
POST /api/auth/login Signs in with an email and a password #
POST /api/auth/logout Signs out by revoking the refresh token in the `prickly_refresh` cookie #
POST /api/auth/refresh Exchanges the refresh token for a new access token #
POST /api/auth/register Starts account creation with an email and a password #
POST /api/auth/resend-confirmation Sends a fresh confirmation code for a signup whose code expired, was burned by… #
POST /api/auth/reset-password Sets a new password using the token from the password reset email #
POST /api/auth/signup-preview Checks the address a visitor is about to sign up with, through the pipeline… #
POST /api/auth/verify-email-change Applies a pending email change with the token from the confirmation email sent… #

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/pricklymails-com:pricklymails-com-auth-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

pricklymails-com-auth-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Pricklymails Com Auth API
  version: 0.9.0
  contact:
    email: support@pricklymails.com
  license:
    name: Proprietary
  description: 'Operations tagged auth across 2 of this provider''s published API definitions: pricklymails-com-openapi.json, pricklymails-com-openapi.yaml. Each path carries the servers of the definition it was published in.'
tags:
- name: Auth
  description: Registration, login, token refresh, password reset, and 2FA.
paths:
  /api/auth/2fa/verify:
    post:
      tags:
      - Auth
      summary: Completes a sign-in that requires two-factor authentication
      description: Send the `temp_token` from the login response together with a TOTP code or an unused backup code. On success the body carries an access token, the refresh token is set in an httpOnly `prickly_refresh` cookie, and a non-httpOnly `pm_session` cookie holds the session expiry as a hint (it is never a credential). Like the password login, it recognizes the browser by its `pm_device` cookie and sets one when the request carried none; spending a backup code emails the account owner.
      operationId: verify_2fa
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Verify2FARequest'
        required: true
      responses:
        '200':
          description: 2FA verified; authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '401':
          description: Temp token invalid, or the TOTP/backup code is wrong.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '429':
          description: Too many failed 2FA attempts; temporarily locked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/confirm:
    post:
      tags:
      - Auth
      summary: Confirms an account with the six-digit code mailed at signup, and signs it in
      description: 'One code takes four guesses: a wrong code, an expired one, a burned one and an address with no account waiting for a code all answer the same `confirm_account.invalid_code`, after which a new code comes from `POST /api/auth/resend-confirmation`. With the `preview_token` of the check the visitor ran on this address before signing up, that check becomes the account''s first job, never billed, and `first_job_uuid` names it.'
      operationId: confirm
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConfirmAccountRequest'
        required: true
      responses:
        '200':
          description: Email address confirmed; authenticated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConfirmAccountResponse'
        '401':
          description: The code does not confirm an account (`confirm_account.invalid_code`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/forgot-password:
    post:
      tags:
      - Auth
      summary: Requests a password reset email
      description: The response is `204` whether or not the address has an account, so it cannot be used to discover registered addresses.
      operationId: forgot_password
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ForgotPasswordRequest'
        required: true
      responses:
        '204':
          description: Reset email sent if the address is registered. Same response whether or not the account exists.
        '400':
          description: Malformed email address.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/login:
    post:
      tags:
      - Auth
      summary: Signs in with an email and a password
      description: 'On success the body carries an access token, the refresh token is set in an httpOnly `prickly_refresh` cookie scoped to `/api/auth`, and a non-httpOnly `pm_session` cookie holds the session expiry as a hint for browser clients (it is never a credential). A browser the account has not signed in from before is recognized by an httpOnly `pm_device` cookie (scoped to `/api/auth`, valid 364 days) that this response sets when the request carried none; a sign-in from a device that is new to the account raises a security notice on the notifications page and by email, and never blocks the sign-in. When the account has two-factor authentication enabled, the response is instead a `{ requires_2fa, temp_token }` body with no cookie; complete the sign-in with `POST /api/auth/2fa/verify`.


        A correct password on an account whose email is not confirmed yet returns `403` with the `authenticate_user.email_not_confirmed` code. Confirming the account (`POST /api/auth/confirm`) signs the user in directly.'
      operationId: login
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
        required: true
      responses:
        '200':
          description: Authenticated, or a 2FA challenge requiring a follow-up call to `/api/auth/2fa/verify`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
        '401':
          description: Invalid credentials, banned account, or deleted account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '403':
          description: Correct password, but the account's email is not confirmed yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '429':
          description: Account temporarily locked after repeated failed attempts.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/logout:
    post:
      tags:
      - Auth
      summary: Signs out by revoking the refresh token in the `prickly_refresh` cookie
      description: The response clears the `prickly_refresh` and `pm_session` cookies.
      operationId: logout
      responses:
        '204':
          description: Refresh token revoked (or none present); browser cookies cleared. Idempotent.
  /api/auth/refresh:
    post:
      tags:
      - Auth
      summary: Exchanges the refresh token for a new access token
      description: 'Reads the refresh token from the `prickly_refresh` httpOnly cookie and replies with a new access token in the body plus fresh `prickly_refresh` and `pm_session` cookies. Each refresh token is single-use: send back the cookie from the latest response.


        A request without the `prickly_refresh` cookie means there is no session to restore and returns `200` with a `null` body. A cookie that is present but invalid, expired, or already used returns `401`.'
      operationId: refresh
      responses:
        '200':
          description: Rotated access token, with fresh refresh and session cookies. A `null` body means no `prickly_refresh` cookie was present; nothing to restore.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
        '401':
          description: Refresh token invalid, expired, or its user no longer exists.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/register:
    post:
      tags:
      - Auth
      summary: Starts account creation with an email and a password
      description: 'The optional `locale` (`"en"` or `"fr"`, English when absent) sets the language of every email sent to the account, starting with the confirmation code. The response is `204` whether the address is new or already registered, so it cannot be used to discover registered addresses: a new address receives a six-digit confirmation code, an already-registered one receives an "account already exists" notice instead. Neither outcome signs the caller in: `POST /api/auth/confirm` with the code does.


        The address is also checked for deliverability before the account is created: an undeliverable address is rejected with `register_user.undeliverable_email` and a disposable address with `register_user.disposable_email`. A `preview_token` from `POST /api/auth/signup-preview` for the same address stands in for that check.'
      operationId: register
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
        required: true
      responses:
        '204':
          description: Registration accepted. Same response whether the email was new or already registered.
        '400':
          description: Invalid email, invalid password, an unsupported locale (`register_user.invalid_locale`), a disposable email (`register_user.disposable_email`), or an undeliverable email (`register_user.undeliverable_email`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/resend-confirmation:
    post:
      tags:
      - Auth
      summary: Sends a fresh confirmation code for a signup whose code expired, was burned by…
      description: The response is `204` whether or not the address has an account or is already confirmed, so it cannot be used to discover registered addresses. A request inside the cooldown that follows a code, or past the account's daily allowance of codes, sends nothing.
      operationId: resend_confirmation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ResendConfirmationRequest'
        required: true
      responses:
        '204':
          description: A new code sent if the address is registered, not yet confirmed, its last code is older than the resend cooldown, and it has not reached its daily allowance of codes. Same response in every other case.
        '400':
          description: Malformed email address.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/reset-password:
    post:
      tags:
      - Auth
      summary: Sets a new password using the token from the password reset email
      description: Returns `204` on success.
      operationId: reset_password
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ResetPasswordRequest'
        required: true
      responses:
        '204':
          description: Password changed.
        '400':
          description: New password fails the password policy.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '401':
          description: Reset token invalid, expired, or already used.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '404':
          description: No account matches the reset token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/signup-preview:
    post:
      tags:
      - Auth
      summary: Checks the address a visitor is about to sign up with, through the pipeline…
      description: 'The response says which checks passed, never the score, the verdict or the reasons: those wait on the server under `preview_token` until the account is confirmed, when `POST /api/auth/confirm` records them as its first job. `POST /api/auth/register` with the same token reuses the result rather than checking the address again. Previews and registrations share one per-IP budget.'
      operationId: signup_preview
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SignupPreviewRequest'
        required: true
      responses:
        '200':
          description: Which checks passed, and whether the address may sign up.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignupPreviewResponse'
        '400':
          description: Malformed email address (`signup_preview.invalid_email`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '429':
          description: Too many previews and registrations from this address.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
  /api/auth/verify-email-change:
    post:
      tags:
      - Auth
      summary: Applies a pending email change with the token from the confirmation email sent…
      description: Returns `204` on success.
      operationId: verify_email_change
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerifyEmailChangeRequest'
        required: true
      responses:
        '204':
          description: Email address change applied.
        '401':
          description: Email-change token invalid or expired.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
        '409':
          description: The new email address was taken by another account in the meantime.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiErrorBody'
components:
  schemas:
    UserResponse:
      type: object
      description: Public representation of a user.
      required:
      - uuid
      - email
      - role
      - email_verified
      - locale
      - created_at
      properties:
        created_at:
          type: string
          description: Account creation timestamp (ISO 8601).
        email:
          type: string
          description: Email address.
        email_verified:
          type: boolean
          description: Whether the email has been verified.
        locale:
          type: string
          description: Language of the account's emails (`"en"` or `"fr"`).
        role:
          type: string
          description: User role (`"user"` or `"admin"`).
        uuid:
          type: string
          description: Public UUID.
    ApiErrorBody:
      type: object
      description: 'Error envelope returned with every non-success status: `{ "error": { "code", "message" } }`.'
      required:
      - error
      properties:
        error:
          $ref: '#/components/schemas/ApiErrorDetail'
          description: Error detail.
    SmtpStatusDto:
      type: string
      description: Outcome of the SMTP probe.
      enum:
      - deliverable
      - undeliverable
      - unknown
      - skipped
    LoginResponse:
      oneOf:
      - $ref: '#/components/schemas/AuthResponse'
        description: Standard authentication response (no 2FA required).
      - type: object
        description: 2FA is required; the client must call `/api/auth/2fa/verify` with the temp token.
        required:
        - requires_2fa
        - temp_token
        properties:
          requires_2fa:
            type: boolean
            description: Always `true` when this variant is returned.
          temp_token:
            type: string
            description: A short-lived token to send to `POST /api/auth/2fa/verify` with the code.
      description: 'Response returned by the login endpoint.


        The body is either a full authentication response or, when two-factor authentication is required, a

        `{ requires_2fa, temp_token }` object.'
    ResendConfirmationRequest:
      type: object
      description: Request body for `POST /api/auth/resend-confirmation`.
      required:
      - email
      properties:
        email:
          type: string
          description: The email address of the account requesting a fresh confirmation code.
    ConfirmAccountRequest:
      type: object
      description: Request body for `POST /api/auth/confirm`.
      required:
      - email
      - code
      properties:
        code:
          type: string
          description: The six-digit code from the confirmation email.
        email:
          type: string
          description: The address the account was registered under.
        preview_token:
          type:
          - string
          - 'null'
          description: 'The `preview_token` of the check the visitor ran on this address before signing up: that check becomes the

            account''s first job.'
    Verify2FARequest:
      type: object
      description: Request body for `POST /api/auth/2fa/verify`.
      required:
      - temp_token
      - code
      properties:
        code:
          type: string
          description: The TOTP code or backup code.
        temp_token:
          type: string
          description: The `temp_token` returned by login when 2FA is required.
    AuthResponse:
      type: object
      description: 'Response body for authentication endpoints.


        The refresh token is delivered in an httpOnly cookie, never in the JSON body.'
      required:
      - access_token
      - expires_in
      - user
      properties:
        access_token:
          type: string
          description: Access token (JWT), sent as a Bearer credential.
        expires_in:
          type: integer
          format: int64
          description: Access token lifetime in seconds.
          minimum: 0
        user:
          $ref: '#/components/schemas/UserResponse'
          description: Authenticated user details.
    ResetPasswordRequest:
      type: object
      description: Request body for `POST /api/auth/reset-password`.
      required:
      - token
      - new_password
      properties:
        new_password:
          type: string
          description: The new password, subject to the same rules as at registration.
        token:
          type: string
          description: The reset token from the password reset email.
    ForgotPasswordRequest:
      type: object
      description: Request body for `POST /api/auth/forgot-password`.
      required:
      - email
      properties:
        email:
          type: string
          description: The email address of the account requesting a password reset.
    PreviewChecksDto:
      type: object
      description: 'Which checks passed for an address a visitor previews before signing up: the shape of the per-check result object,

        without the mail exchanger hostnames.'
      required:
      - syntax
      - mx
      - disposable
      - role
      - free
      - typo
      - smtp
      - catchall
      properties:
        catchall:
          $ref: '#/components/schemas/ProviderFlagDto'
          description: Whether the domain is a catch-all server.
        disposable:
          $ref: '#/components/schemas/ProviderFlagDto'
          description: Whether the domain is from a known disposable provider.
        free:
          $ref: '#/components/schemas/ProviderFlagDto'
          description: Whether the domain is a known free webmail provider.
        mx:
          $ref: '#/components/schemas/MxPreviewDto'
          description: Whether the domain publishes a usable mail exchanger.
        role:
          $ref: '#/components/schemas/ProviderFlagDto'
          description: Whether the local-part is a known role-based address.
        smtp:
          $ref: '#/components/schemas/SmtpCheckDto'
          description: SMTP deliverability probe result.
        syntax:
          type: boolean
          description: Whether the email syntax is valid.
        typo:
          $ref: '#/components/schemas/TypoCheckDto'
          description: Typo detection result, with the corrected address when one was found.
    SignupPreviewResponse:
      type: object
      description: 'Response body for `POST /api/auth/signup-preview`.


        Says which checks passed and nothing more: the score, the verdict and the reasons stay on the server until the

        account the visitor creates is confirmed.'
      required:
      - signup
      properties:
        checks:
          oneOf:
          - type: 'null'
          - $ref: '#/components/schemas/PreviewChecksDto'
            description: Which checks passed, absent when no check ran.
        preview_token:
          type:
          - string
          - 'null'
          description: 'The handle on the stored result, to send back with `POST /api/auth/register` and `POST /api/auth/confirm`.

            Present only when `signup` is `allowed`.'
        signup:
          $ref: '#/components/schemas/SignupEligibilityDto'
          description: Whether the address may sign up.
    RegisterRequest:
      type: object
      description: Request body for `POST /api/auth/register`.
      required:
      - email
      - password
      properties:
        email:
          type: string
          description: The email address for the new account.
        locale:
          type:
          - string
          - 'null'
          description: 'The language of the page the user signs up on (`"en"` or `"fr"`), which every email to the account then uses.

            English when absent.'
        password:
          type: string
          description: 'The password for the new account: 12 to 128 characters with an uppercase letter, a digit, and a special

            character.'
        preview_token:
          type:
          - string
          - 'null'
          description: 'The `preview_token` that `POST /api/auth/signup-preview` returned for this same address: its result stands in

            for the check registration would otherwise run again. Ignored when unknown, expired, or issued for another

            address.'
    LoginRequest:
      type: object
      description: Request body for `POST /api/auth/login`.
      required:
      - email
      - password
      properties:
        email:
          type: string
          description: The email address of the account.
        password:
          type: string
          description: The account password.
    SignupPreviewRequest:
      type: object
      description: Request body for `POST /api/auth/signup-preview`.
      required:
      - email
      properties:
        email:
          type: string
          description: The address the visitor is about to sign up with.
    VerifyEmailChangeRequest:
      type: object
      description: Request body for `POST /api/auth/verify-email-change`.
      required:
      - token
      properties:
        token:
          type: string
          description: The confirmation token from the link in the email-change email.
    SmtpCheckDto:
      type: object
      description: SMTP deliverability probe result.
      required:
      - status
      properties:
        status:
          $ref: '#/components/schemas/SmtpStatusDto'
          description: 'SMTP probe outcome: `deliverable` (the server accepted the `RCPT TO` command), `undeliverable` (the server

            permanently rejected the recipient, 5xx), `unknown` (no definitive answer: a temporary refusal, a timeout, a

            connection failure, or a server that refused the probe itself), or `skipped` (not requested, or not

            needed because the answer was already known).'
    ApiErrorDetail:
      type: object
      description: Detail of an error response.
      required:
      - code
      properties:
        code:
          type: string
          description: Stable key identifying the error (for example `"verify.invalid_uuid"`). Clients localize by this key.
        message:
          type:
          - string
          - 'null'
          description: 'Present on most error kinds and equal to `code`; the API returns no localized text.

            Absent for error kinds that carry no extra detail.'
    ProviderFlagDto:
      oneOf:
      - type: boolean
        description: The check ran; carries the real boolean result.
      - type: object
        description: The check was not run.
        required:
        - status
        properties:
          status:
            type: string
            description: Always `"skipped"`.
      description: 'A boolean provider or risk-flag check result (`disposable`, `role`, `free`, `catchall`).


        Renders as a bare `true`/`false` when the check ran, or as `{ "status": "skipped" }` when it did not run (excluded

        from the caller''s check set), the same skipped shape the `mx` and `smtp` checks use, so an unrun check never reads

        as a definitive negative result.'
    ConfirmAccountResponse:
      allOf:
      - $ref: '#/components/schemas/AuthResponse'
        description: The session, as every sign-in returns it.
      - type: object
        properties:
          first_job_uuid:
            type:
            - string
            - 'null'
            format: uuid
            description: 'The job recording the check the visitor ran on their address before signing up, readable through

              `GET /api/jobs/{uuid}`. Present only when `preview_token` named one.'
      description: 'Response body for `POST /api/auth/confirm`: the session of the confirmed account.'
    SignupEligibilityDto:
      type: string
      description: Whether the previewed address may sign up.
      enum:
      - allowed
      - undeliverable
      - disposable
      - unchecked
    MxPreviewDto:
      oneOf:
      - type: object
        description: The check ran.
        required:
        - valid
        properties:
          valid:
            type: boolean
            description: Whether the domain publishes at least one usable mail exchanger.
      - type: object
        description: The check was not run.
        required:
        - status
        properties:
          status:
            type: string
            description: Always `"skipped"`.
      description: The MX check of a signup preview.
    TypoCheckDto:
      type: object
      description: Typo detection result.
      required:
      - detected
      properties:
        detected:
          type: boolean
          description: Whether a domain typo was detected.
        suggested_domain:
          type:
          - string
          - 'null'
          description: 'Corrected domain only (e.g. `"gmail.com"`), present on `GET /api/verify/{uuid}` when a typo was detected.

            Only the domain is returned (zero-retention policy); the caller already has the local part to combine it with.'
        suggestion:
          type:
          - string
          - 'null'
          description: 'Full corrected address (e.g. `"user@gmail.com"`), only ever present on the synchronous submit response where the

            raw email is available in-request.

            Always absent on `GET /api/verify/{uuid}`, because the submitted address is never stored (zero-retention

            policy); `suggested_domain` is that path''s equivalent.'
  securitySchemes:
    bearer_api_key:
      type: http
      scheme: bearer
      description: A `pm_live_*` or `pm_test_*` API key.
    jwt:
      type: http
      scheme: bearer
      description: A short-lived token from `/api/auth/login`, or `/oauth/token` for an agent.
x-refined-from:
- pricklymails-com-openapi.json
- pricklymails-com-openapi.yaml