Primitive Templates API

Public Function template registry reads used to browse installable agent templates.

OpenAPI Specification

primitive-templates-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Primitive Account Templates API
  version: 1.0.0
  description: "Primitive is email infrastructure for AI agents. The Primitive API lets you manage domains, emails, webhook endpoints,\nfilters, and account settings programmatically.\n\n## Authentication\n\nMost endpoints require a Bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer prim_<your_api_key>\nAuthorization: Bearer prim_oat_<oauth_access_token>\n```\n\nAPI keys and OAuth access tokens are org-scoped. Create and manage them in your dashboard\nunder Settings > API Keys. CLI login plus CLI/agent signup endpoints\nexplicitly declare `security: []`; they do not require an API key because\nthey are used to create OAuth CLI sessions.\n\n## Rate Limiting\n\nThe API enforces a sliding window rate limit of **120 requests per\n60 seconds** per organization. When exceeded, the API returns `429`\nwith a `Retry-After` header indicating how many seconds to wait.\n\n## Pagination\n\nList endpoints use cursor-based pagination. Responses include a\n`meta` object with `total`, `limit`, and `cursor` fields. Pass the\n`cursor` value as a query parameter to fetch the next page. When\n`cursor` is `null`, there are no more results.\n\n## Response Format\n\nAll responses use a consistent envelope:\n\n```json\n{\n  \"success\": true,\n  \"data\": { ... },\n  \"meta\": { \"total\": 42, \"limit\": 50, \"cursor\": \"...\" }\n}\n```\n\nErrors follow the same pattern:\n\n```json\n{\n  \"success\": false,\n  \"error\": { \"code\": \"not_found\", \"message\": \"Email not found\" }\n}\n```\n\n## Webhook signing\n\nOutbound webhook deliveries (configured via the `endpoints` API)\nare signed so receivers can verify they came from Primitive and\nhave not been tampered with in transit. The signing scheme is\ndeliberately simple so it can be reimplemented in any language\nin a few lines. The Node SDK's `verifyWebhookSignature` helper\nis the reference implementation; the wire details below let you\nwrite a verifier in Python, Go, Ruby, etc. without reading our\nsource.\n\n**Header**: `Primitive-Signature: t=<unix-seconds>,v1=<hex>`\n\nA legacy `MyMX-Signature` header is also sent on every delivery\nwith the same value, retained for back-compatibility with\nintegrations written before the rename. New code should read\n`Primitive-Signature`.\n\n**Signed string**: `${timestamp}.${rawBody}` where `timestamp`\nis the Unix-seconds integer from the `t=` parameter and\n`rawBody` is the exact bytes of the HTTP request body BEFORE\nany JSON decoding. Verify against the raw body, not a\nre-serialized parse, or you will silently mismatch on\ninsignificant whitespace.\n\n**Signature**: HMAC-SHA256 of the signed string, hex-encoded\n(lowercase). Use the account's webhook secret as the HMAC key,\nas a UTF-8 byte sequence.\n\n**Secret**: returned by `GET /account/webhook-secret`. The\nstring looks base64-shaped (e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`)\nbut is NOT base64; use it AS-IS as a UTF-8 string for the HMAC\nkey. Base64-decoding before HMAC will silently produce\nmismatched signatures.\n\n**Tolerance**: by convention, reject deliveries whose `t=`\ntimestamp is more than 5 minutes off your wall-clock to defend\nagainst replay attacks. The Node SDK's helper enforces this by\ndefault.\n\n**Verification recipe** (any language):\n\n```\n1. Read the raw HTTP body (do not parse).\n2. Read `Primitive-Signature: t=<ts>,v1=<sig>`.\n3. Reject if abs(now - ts) > 300 seconds.\n4. expected = HMAC_SHA256_hex(secret_utf8, f\"{ts}.{rawBody}\")\n5. Constant-time compare expected to sig. Reject if not equal.\n```\n\nFor Node, use `verifyWebhookSignature` from\n`@primitivedotdev/sdk/webhook` (or the higher-level\n`handleWebhook` helper if you want a one-liner). For other\nlanguages, the recipe above is everything you need.\n\nTest deliveries: `POST /endpoints/{id}/test` triggers a fake\ndelivery to your endpoint URL, signed with your real account\nsecret, so you can confirm verification end-to-end without\nneeding real inbound mail. The test response carries the exact\n`signature` header value sent on the wire so you can compare\nstrings directly.\n\n\n## Errors\n\nEvery error response is the same JSON envelope (`{ \"success\": false, \"error\": { \"code\", \"message\" } }`), served as `application/json` with HTTP status codes, following the RFC 7807 problem-details shape. The `error.code` is a stable machine-readable string and `error.message` is human-readable.\n\n## Authorization and roles\n\nAccess is governed by organization role-based access control. Every organization member holds one of three roles — `owner`, `admin`, or `member` — and a credential inherits a role. **API keys** always act at `member` level, regardless of the role of the user who created them, so an API key can never perform owner- or admin-only actions. **OAuth access tokens** act with the authorizing user's current organization role, resolved on each request. Every operation in this spec is part of the member-level surface, so any valid credential can call it. Organization administration that is not part of this API — billing and organization settings — requires an `owner` or `admin` and is performed in the dashboard. Fine-grained per-key scopes (e.g. a send-only or read-only key) are on the roadmap; today the role model is the unit of access control.\n\n## Versioning\n\nThe current stable API is **v1**. All endpoints are served under `/v1/` and are covered by a backward-compatibility guarantee: existing fields and status codes will not change without a deprecation notice.\n\nBreaking changes are announced at least 6 months in advance via changelog and email. Deprecated operations and fields are marked `x-deprecated: true` in the spec and carry a plain-English description of the replacement. The `v1` path prefix is guaranteed stable indefinitely; backward-compatible additions (new optional fields, new endpoints) may be made at any time without a version bump."
  contact:
    name: Primitive
    url: https://primitive.dev
  license:
    name: Proprietary
    url: https://primitive.dev/terms
  x-stability-level: stable
  x-deprecation-policy: 'Breaking changes are announced at least 6 months in advance. Deprecated fields carry x-deprecated: true. The current stable version is v1.'
servers:
- url: https://api.primitive.dev/v1
  description: Canonical API host (PRIMITIVE_API_BASE_URL). Carries every public API operation.
tags:
- name: Templates
  description: Public Function template registry reads used to browse installable agent templates.
paths:
  /templates:
    get:
      operationId: listTemplates
      summary: List function templates
      description: List approved Function templates available for browsing and installation. Results are cacheable and paginated with `data.next_cursor`.
      tags:
      - Templates
      security: []
      parameters:
      - name: q
        in: query
        required: false
        description: Search templates by title, summary, or slug.
        schema:
          type: string
          minLength: 1
      - name: tag
        in: query
        required: false
        description: Filter templates by an exact tag.
        schema:
          type: string
          minLength: 1
      - name: cursor
        in: query
        required: false
        description: Cursor from a previous response `data.next_cursor` value.
        schema:
          type: string
      - name: limit
        in: query
        required: false
        description: Maximum number of templates to return. The server caps this at 100.
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 50
      responses:
        '200':
          description: Paginated template registry summaries.
          content:
            application/json:
              schema:
                allOf:
                - type: object
                  properties:
                    success:
                      type: boolean
                      const: true
                  required:
                  - success
                  - data
                - type: object
                  properties:
                    data:
                      type: object
                      properties:
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                                format: uuid
                              slug:
                                type: string
                                pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
                                description: Stable template slug used in template URLs and install commands.
                              title:
                                type: string
                              summary:
                                type: string
                              author:
                                type: object
                                additionalProperties: false
                                properties:
                                  id:
                                    type: string
                                    minLength: 1
                                  name:
                                    type: string
                                    minLength: 1
                                  url:
                                    type: string
                                    format: uri
                                required:
                                - id
                                - name
                              tags:
                                type: array
                                items:
                                  type: string
                              verified:
                                type: boolean
                              install_count:
                                type: integer
                                minimum: 0
                              github_repo:
                                type: string
                                pattern: ^[A-Za-z0-9-]+/[A-Za-z0-9_.-]+$
                                description: GitHub repository in owner/repo form.
                              created_at:
                                type: string
                                format: date-time
                              updated_at:
                                type: string
                                format: date-time
                            required:
                            - id
                            - slug
                            - title
                            - summary
                            - author
                            - tags
                            - verified
                            - install_count
                            - github_repo
                            - created_at
                            - updated_at
                        next_cursor:
                          type:
                          - string
                          - 'null'
                          description: Cursor to pass as the next `cursor` query value, or null when there are no more templates.
                      required:
                      - items
                      - next_cursor
        '400':
          $ref: '#/components/responses/ValidationError'
          description: Invalid request parameters
        '429':
          $ref: '#/components/responses/RateLimited'
          description: Rate limit exceeded
  /templates/{id}:
    get:
      operationId: getTemplate
      summary: Get a function template
      description: Fetch one approved Function template by slug, including its manifest snapshot and README. The stored source files used for install are not returned.
      tags:
      - Templates
      security: []
      parameters:
      - name: id
        in: path
        required: true
        description: Template slug from the template manifest.
        schema:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
          description: Template slug.
      responses:
        '200':
          description: Template registry detail.
          content:
            application/json:
              schema:
                allOf:
                - type: object
                  properties:
                    success:
                      type: boolean
                      const: true
                  required:
                  - success
                  - data
                - type: object
                  properties:
                    data:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        slug:
                          type: string
                          pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
                          description: Stable template slug used in template URLs and install commands.
                        title:
                          type: string
                        summary:
                          type: string
                        author:
                          type: object
                          additionalProperties: false
                          properties:
                            id:
                              type: string
                              minLength: 1
                            name:
                              type: string
                              minLength: 1
                            url:
                              type: string
                              format: uri
                          required:
                          - id
                          - name
                        tags:
                          type: array
                          items:
                            type: string
                        verified:
                          type: boolean
                        install_count:
                          type: integer
                          minimum: 0
                        github_repo:
                          type: string
                          pattern: ^[A-Za-z0-9-]+/[A-Za-z0-9_.-]+$
                          description: GitHub repository in owner/repo form.
                        created_at:
                          type: string
                          format: date-time
                        updated_at:
                          type: string
                          format: date-time
                        description:
                          type:
                          - string
                          - 'null'
                        github_sha:
                          type: string
                        github_path:
                          type:
                          - string
                          - 'null'
                        manifest:
                          type: object
                          additionalProperties: false
                          properties:
                            schemaVersion:
                              type: integer
                              const: 1
                            id:
                              type: string
                              pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
                              description: Stable template slug from the manifest.
                            title:
                              type: string
                              minLength: 1
                            summary:
                              type: string
                              minLength: 1
                            description:
                              type: string
                            author:
                              type: object
                              additionalProperties: false
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                name:
                                  type: string
                                  minLength: 1
                                url:
                                  type: string
                                  format: uri
                              required:
                              - id
                              - name
                            tags:
                              type: array
                              items:
                                type: string
                                minLength: 1
                              default: []
                            source:
                              oneOf:
                              - type: object
                                additionalProperties: false
                                properties:
                                  mode:
                                    type: string
                                    const: managed-build
                                  dir:
                                    type: string
                                    minLength: 1
                                    default: .
                                required:
                                - mode
                                - dir
                              - type: object
                                additionalProperties: false
                                properties:
                                  mode:
                                    type: string
                                    const: bundle
                                  file:
                                    type: string
                                    minLength: 1
                                required:
                                - mode
                                - file
                            install:
                              type: object
                              additionalProperties: false
                              properties:
                                mode:
                                  type: string
                                  enum:
                                  - deploy
                                  - scaffold
                                editFiles:
                                  type: array
                                  items:
                                    type: string
                                    minLength: 1
                                  default: []
                                reason:
                                  type: string
                                  default: ''
                              required:
                              - mode
                              - editFiles
                              - reason
                            secrets:
                              type: array
                              items:
                                type: object
                                additionalProperties: false
                                properties:
                                  key:
                                    type: string
                                    pattern: ^[A-Z_][A-Z0-9_]*$
                                  required:
                                    type: boolean
                                    default: true
                                  description:
                                    type: string
                                required:
                                - key
                                - required
                              default: []
                            secretGroups:
                              type: array
                              items:
                                type: object
                                additionalProperties: false
                                properties:
                                  keys:
                                    type: array
                                    minItems: 2
                                    items:
                                      type: string
                                      pattern: ^[A-Z_][A-Z0-9_]*$
                                  min:
                                    type: integer
                                    minimum: 1
                                    default: 1
                                  description:
                                    type: string
                                required:
                                - keys
                                - min
                              default: []
                            variables:
                              type: array
                              items:
                                type: object
                                additionalProperties: false
                                properties:
                                  key:
                                    type: string
                                    minLength: 1
                                  prompt:
                                    type: string
                                    minLength: 1
                                  default:
                                    type: string
                                  file:
                                    type: string
                                    minLength: 1
                                  type:
                                    type: string
                                    enum:
                                    - string
                                    - select
                                    - url
                                    - email
                                    default: string
                                  options:
                                    type: array
                                    items:
                                      type: string
                                      minLength: 1
                                  validation:
                                    type: object
                                    additionalProperties: false
                                    properties:
                                      pattern:
                                        type: string
                                        minLength: 1
                                      maxLength:
                                        type: integer
                                        minimum: 1
                                required:
                                - key
                                - prompt
                                - type
                              default: []
                            consumesVendors:
                              type: array
                              items:
                                type: object
                                additionalProperties: false
                                properties:
                                  slug:
                                    type: string
                                    minLength: 1
                                  required:
                                    type: boolean
                                    default: true
                                required:
                                - slug
                              default: []
                            setup:
                              type: object
                              additionalProperties: false
                              properties:
                                agent:
                                  type: string
                                  minLength: 1
                                prompt:
                                  type: string
                                  minLength: 1
                                produces:
                                  type: array
                                  items:
                                    type: string
                                    minLength: 1
                                  default: []
                              required:
                              - agent
                              - prompt
                              - produces
                            postInstall:
                              type: string
                          required:
                          - schemaVersion
                          - id
                          - title
                          - summary
                          - author
                          - tags
                          - source
                          - install
                          - secrets
                          - secretGroups
                          - variables
                        readme:
                          type:
                          - string
                          - 'null'
                        status:
                          type: string
                          enum:
                          - pending
                          - approved
                          - rejected
                      required:
                      - id
                      - slug
                      - title
                      - summary
                      - author
                      - tags
                      - verified
                      - install_count
                      - github_repo
                      - created_at
                      - updated_at
                      - description
                      - github_sha
                      - github_path
                      - manifest
                      - readme
                      - status
        '400':
          $ref: '#/components/responses/ValidationError'
          description: Invalid request parameters
        '404':
          $ref: '#/components/responses/NotFound'
          description: Resource not found
        '429':
          $ref: '#/components/responses/RateLimited'
          description: Rate limit exceeded
  /templates/{id}/install:
    post:
      operationId: installTemplate
      summary: Install a function template
      description: Start a one-shot deploy of an approved deploy-mode Function template. The response returns an install record immediately; poll `GET /templates/installs/{id}` for progress.
      tags:
      - Templates
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        description: Template slug from the template manifest.
        schema:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
          description: Template slug.
      - name: Idempotency-Key
        in: header
        required: false
        description: Optional client-supplied idempotency key. Retrying a request with the same key returns the original result instead of performing the action a second time; if omitted the server derives one from the canonical payload hash. Safe to retry network failures without duplicating side effects.
        schema:
          type: string
          minLength: 1
          maxLength: 255
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                address:
                  type: string
                  pattern: ^[a-z0-9][a-z0-9._-]{0,63}$
                  description: Localpart to claim on the selected inbound domain. Defaults to the template slug.
                domain:
                  type: string
                  minLength: 3
                  description: Org domain name to claim the address on. Defaults to the org's newest active domain.
                variables:
                  type: object
                  additionalProperties:
                    type: string
                  description: Template variable values keyed by manifest variable key.
                secrets:
                  type: object
                  additionalProperties:
                    type: string
                  description: Secret values keyed by manifest secret key.
      responses:
        '201':
          description: Template install started.
          content:
            application/json:
              schema:
                allOf:
                - type: object
                  properties:
                    success:
                      type: boolean
                      const: true
                  required:
                  - success
                  - data
                - type: object
                  properties:
                    data:
                      type: object
                      properties:
                        id:
                          type: string
                          format: uuid
                        template_slug:
                          type: string
                          pattern: ^[a-z0-9][a-z0-9_-]{0,62}$
                          description: Template slug for this install.
                        state:
                          type: string
                          enum:
                          - deploying
                          - connecting
                          - bound
                          - tested
                          - deploy_failed
                          - bind_failed
                          - test_failed
                        address:
                          type:
                          - string
                          - 'null'
                        function_id:
                          type:
                          - string
                          - 'null'
                          format: uuid
                        error:
                          type:
                          - string
                          - 'null'
                        created_at:
                          type: string
                          format: date-time
                        updated_at:
                          type: string
                          format: date-time
                      required:
                      - id
                      - template_slug
                      - state
                      - address
                      - function_id
                      - error
                      - created_at
                      - updated_at
        '400':
          $ref: '#/components/responses/ValidationError'
          description: Invalid request parameters
        '401':
          $ref: '#/components/responses/Unauthorized'
          description: Invalid or missing API key
        '403':
          $ref: '#/components/responses/Forbidden'
          description: Authenticated caller lacks permission for the operation
        '404':
          $ref: '#/components/responses/NotFound'
          description: Resource not found
        '409':
          $ref: '#/components/responses/Conflict'
          description: The request conflicts with the current state of the resource
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
          description: 'The request was well-formed but could not be processed. For Payments

            this covers a missing payout address, a failed payment verification, a

            spend-policy decline, or an expired challenge; `error.code` distinguishes

            them.

            '
        '429':
          $ref: '#/components/responses/RateLimited'
          description: Rate limit exceeded
  /templates/installs/{id}:
    get:
      operationId: getTemplateInstall
      summary: Get template install status
      description: Fetch the current state of a template install. Reads may advance the self-test phase when a reply effect has been observed.
      tags:
      - Templates
      security:
      - BearerAuth: []
      parameters:
      - name: id
        in: path
        required: true
        description: Template install UUID.
        schema:
          type: string
          format: uuid
          pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
      responses:
        '200':
          description: Current template install status.
          content:
            application/json:
              schema:
                allOf:
                - type: object
                  properties:
                    success:
                      type: boolean
                      const: true
                  re

# --- truncated at 32 KB (44 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/primitive/refs/heads/main/openapi/primitive-templates-api-openapi.yml