samva-dev Topic forms API

Hosted and embedded double opt-in signup forms for topics

Operations 5

GET /v1/topics/{id}/forms List topic forms #
POST /v1/topics/{id}/forms Create a topic form #
GET /v1/topics/{id}/forms/{formId} Get a topic form #
PATCH /v1/topics/{id}/forms/{formId} Update a topic form #
DELETE /v1/topics/{id}/forms/{formId} Delete a topic form #

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/samva-dev:samva-dev-topic-forms-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

samva-dev-topic-forms-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Samva Topic forms API
  version: 1.0.0
  description: Samva is the email API for your app. Send transactional email in one typed call. Delivery events and customer replies come back as signed webhooks, and replies thread to the email they answer.
servers:
- url: https://api.samva.dev
security: []
tags:
- name: Topic forms
  description: Hosted and embedded double opt-in signup forms for topics
paths:
  /v1/topics/{id}/forms:
    get:
      tags:
      - Topic forms
      operationId: topicForms.list
      parameters:
      - name: id
        in: path
        schema:
          $ref: '#/components/schemas/TopicId'
        required: true
      security:
      - apiKey: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      $ref: '#/components/schemas/TopicForm'
                required:
                - items
                additionalProperties: false
        '401':
          description: UnauthorizedError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedError'
        '403':
          description: ForbiddenError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
        '404':
          description: ResourceNotFoundError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResourceNotFoundError'
        '422':
          description: ValidationError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '500':
          description: InternalError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalError'
        '504':
          description: GatewayTimeoutError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayTimeoutError'
      description: Lists the signup forms belonging to the visible topic. Forms contain exact HTTPS allowed origins, bounded confirmation and success copy, an optional HTTPS redirect, and a public key for hosted or embedded signup.
      summary: List topic forms
      x-samva-scope: contacts:read
    post:
      tags:
      - Topic forms
      operationId: topicForms.create
      parameters:
      - name: id
        in: path
        schema:
          $ref: '#/components/schemas/TopicId'
        required: true
      security:
      - apiKey: []
      responses:
        '201':
          description: TopicForm
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopicForm'
        '401':
          description: UnauthorizedError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedError'
        '403':
          description: ForbiddenError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
        '404':
          description: ResourceNotFoundError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResourceNotFoundError'
        '422':
          description: ValidationError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '500':
          description: InternalError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalError'
        '504':
          description: GatewayTimeoutError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayTimeoutError'
      description: Creates a signup form for the visible topic and returns 201. The server generates its opaque public key. allowedOrigins contains exact HTTPS origins; the canonical web origin and current topic link origin are also accepted. Copy is plain text and redirectUrl is HTTPS or null.
      summary: Create a topic form
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TopicFormCreatePayload'
        required: true
      x-samva-scope: contacts:create
  /v1/topics/{id}/forms/{formId}:
    get:
      tags:
      - Topic forms
      operationId: topicForms.get
      parameters:
      - name: id
        in: path
        schema:
          $ref: '#/components/schemas/TopicId'
        required: true
      - name: formId
        in: path
        schema:
          type: string
          pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$
          format: uuid
        required: true
      security:
      - apiKey: []
      responses:
        '200':
          description: TopicForm
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopicForm'
        '401':
          description: UnauthorizedError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedError'
        '403':
          description: ForbiddenError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
        '404':
          description: ResourceNotFoundError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResourceNotFoundError'
        '422':
          description: ValidationError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '500':
          description: InternalError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalError'
        '504':
          description: GatewayTimeoutError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayTimeoutError'
      description: Returns a signup form belonging to the visible topic, including its public key and current link origin. Forms outside the caller namespace or organization return 404.
      summary: Get a topic form
      x-samva-scope: contacts:read
    patch:
      tags:
      - Topic forms
      operationId: topicForms.update
      parameters:
      - name: id
        in: path
        schema:
          $ref: '#/components/schemas/TopicId'
        required: true
      - name: formId
        in: path
        schema:
          type: string
          pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$
          format: uuid
        required: true
      security:
      - apiKey: []
      responses:
        '200':
          description: TopicForm
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TopicForm'
        '401':
          description: UnauthorizedError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedError'
        '403':
          description: ForbiddenError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
        '404':
          description: ResourceNotFoundError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResourceNotFoundError'
        '422':
          description: ValidationError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '500':
          description: InternalError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalError'
        '504':
          description: GatewayTimeoutError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayTimeoutError'
      description: Updates only the supplied form fields. allowedOrigins replaces the complete exact-origin allowlist; redirectUrl null clears the success redirect. The public key remains stable.
      summary: Update a topic form
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TopicFormUpdatePayload'
        required: true
      x-samva-scope: contacts:update
    delete:
      tags:
      - Topic forms
      operationId: topicForms.remove
      parameters:
      - name: id
        in: path
        schema:
          $ref: '#/components/schemas/TopicId'
        required: true
      - name: formId
        in: path
        schema:
          type: string
          pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$
          format: uuid
        required: true
      security:
      - apiKey: []
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                required:
                - success
                additionalProperties: false
        '401':
          description: UnauthorizedError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedError'
        '403':
          description: ForbiddenError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ForbiddenError'
        '404':
          description: ResourceNotFoundError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ResourceNotFoundError'
        '422':
          description: ValidationError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
        '500':
          description: InternalError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalError'
        '504':
          description: GatewayTimeoutError
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayTimeoutError'
      description: Deletes a form belonging to the visible topic. Its public key immediately stops accepting signups. Existing email confirmation links keep their snapshotted copy and remain valid until expiry.
      summary: Delete a topic form
      x-samva-scope: contacts:delete
components:
  schemas:
    ValidationError:
      type: object
      properties:
        _tag:
          type: string
          enum:
          - ValidationError
        message:
          type: string
        fields:
          anyOf:
          - type: object
            additionalProperties:
              type: array
              items:
                type: string
          - type: 'null'
      required:
      - _tag
      - message
      additionalProperties: false
      x-category:
      - validation
      x-retryable: false
    TopicForm:
      type: object
      properties:
        id:
          type: string
          pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$
          format: uuid
        publicKey:
          type: string
          pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|[fF]{8}-[fF]{4}-[fF]{4}-[fF]{4}-[fF]{12})$
          format: uuid
        topicId:
          $ref: '#/components/schemas/TopicId'
        allowedOrigins:
          type: array
          items:
            type: string
            pattern: ^https:\/\/
            maxLength: 2048
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2048
          maxItems: 20
        confirmationTitle:
          type: string
          minLength: 1
          maxLength: 120
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 120
        confirmationMessage:
          type: string
          minLength: 1
          maxLength: 2000
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 2000
        successTitle:
          type: string
          minLength: 1
          maxLength: 120
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 120
        successMessage:
          type: string
          minLength: 1
          maxLength: 2000
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 2000
        redirectUrl:
          anyOf:
          - type: string
            pattern: ^https:\/\/
            maxLength: 2048
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2048
          - type: 'null'
        linkOrigin:
          type: string
        createdAt:
          type: string
        updatedAt:
          type: string
      required:
      - id
      - publicKey
      - topicId
      - allowedOrigins
      - confirmationTitle
      - confirmationMessage
      - successTitle
      - successMessage
      - redirectUrl
      - linkOrigin
      - createdAt
      - updatedAt
      additionalProperties: false
    TopicFormUpdatePayload:
      type: object
      properties:
        allowedOrigins:
          anyOf:
          - type: array
            items:
              type: string
              pattern: ^https:\/\/
              maxLength: 2048
              x-samva-string-checks:
              - id: effect/schema/isMaxLength
                payload:
                  maxLength: 2048
            maxItems: 20
          - type: 'null'
        confirmationTitle:
          anyOf:
          - type: string
            minLength: 1
            maxLength: 120
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 120
          - type: 'null'
        confirmationMessage:
          anyOf:
          - type: string
            minLength: 1
            maxLength: 2000
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2000
          - type: 'null'
        successTitle:
          anyOf:
          - type: string
            minLength: 1
            maxLength: 120
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 120
          - type: 'null'
        successMessage:
          anyOf:
          - type: string
            minLength: 1
            maxLength: 2000
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2000
          - type: 'null'
        redirectUrl:
          anyOf:
          - type: string
            pattern: ^https:\/\/
            maxLength: 2048
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2048
          - type: 'null'
          - type: 'null'
      additionalProperties: false
    GatewayTimeoutError:
      type: object
      properties:
        _tag:
          type: string
          enum:
          - GatewayTimeoutError
        message:
          type: string
        retryAfterSeconds:
          type: number
      required:
      - _tag
      - message
      - retryAfterSeconds
      additionalProperties: false
      x-category:
      - transient
      x-retryable: true
    TopicFormCreatePayload:
      type: object
      properties:
        allowedOrigins:
          type: array
          items:
            type: string
            pattern: ^https:\/\/
            maxLength: 2048
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2048
          maxItems: 20
        confirmationTitle:
          type: string
          minLength: 1
          maxLength: 120
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 120
        confirmationMessage:
          type: string
          minLength: 1
          maxLength: 2000
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 2000
        successTitle:
          type: string
          minLength: 1
          maxLength: 120
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 120
        successMessage:
          type: string
          minLength: 1
          maxLength: 2000
          x-samva-string-checks:
          - id: effect/schema/isMaxLength
            payload:
              maxLength: 2000
        redirectUrl:
          anyOf:
          - type: string
            pattern: ^https:\/\/
            maxLength: 2048
            x-samva-string-checks:
            - id: effect/schema/isMaxLength
              payload:
                maxLength: 2048
          - type: 'null'
      required:
      - allowedOrigins
      - confirmationTitle
      - confirmationMessage
      - successTitle
      - successMessage
      - redirectUrl
      additionalProperties: false
    UnauthorizedError:
      type: object
      properties:
        _tag:
          type: string
          enum:
          - UnauthorizedError
        message:
          type: string
      required:
      - _tag
      - message
      additionalProperties: false
      x-category:
      - auth
      x-retryable: false
    TopicId:
      type: string
      pattern: ^unsub_[0-9a-hjkmnp-tv-z]{16,24}$
      x-samva-brand: TopicId
    ForbiddenError:
      type: object
      properties:
        _tag:
          type: string
          enum:
          - ForbiddenError
        message:
          type: string
      required:
      - _tag
      - message
      additionalProperties: false
      x-category:
      - auth
      x-retryable: false
    InternalError:
      type: object
      properties:
        _tag:
          type: string
          enum:
          - InternalError
        message:
          type: string
      required:
      - _tag
      - message
      additionalProperties: false
      x-category:
      - transient
      x-retryable: true
    ResourceNotFoundError:
      type: object
      properties:
        _tag:
          type: string
          enum:
          - ResourceNotFoundError
        resource:
          type: string
        id:
          type: string
        message:
          type: string
      required:
      - _tag
      - resource
      - id
      - message
      additionalProperties: false
      x-category:
      - notFound
      x-retryable: false
  securitySchemes:
    apiKey:
      type: apiKey
      name: x-api-key
      in: header