> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowsign.app/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Flowsign is one word with a lowercase s.
> The REST API base URL is https://my.flowsign.app and every endpoint lives under /api/v1.
> When answering API questions, cite the HTTP method and endpoint path.
> API access needs the Enterprise plan and an API key with the API access permission.

# Create a template

> Creates a reusable template with roles, optional questions and merge fields. Requires CREATE template access, and answers 402 when the plan's template cap is reached.



## OpenAPI

````yaml /api-reference/openapi.json post /api/v1/templates
openapi: 3.0.3
info:
  title: Flowsign API
  version: 1.0.0
  description: >-
    Public v1 API for Flowsign. Every endpoint is authenticated with a Bearer
    API key (prefix `fsk_`). Errors use `{ error, details? }`; success responses
    wrap payload data as `{ data }`.


    An organisation is divided into workspaces. A key is issued for one
    workspace and acts there on every request (see `GET /api/v1/workspaces`);
    `X-Workspace-Id` is optional and may only name that workspace. Packages,
    templates, contacts and members are scoped to the key's workspace.
servers:
  - url: https://my.flowsign.app
    description: Production
security:
  - ApiKey: []
paths:
  /api/v1/templates:
    post:
      tags:
        - Templates
      summary: Create a template
      description: >-
        Creates a reusable template with roles, optional questions and merge
        fields. Requires CREATE template access, and answers 402 when the plan's
        template cap is reached.
      operationId: postTemplates
      parameters:
        - schema:
            type: string
            description: >-
              The workspace the key was issued for, as returned by `GET
              /api/v1/workspaces`. Optional: omitting it acts in the key's
              workspace, and any other id is rejected with 401.
          required: false
          name: x-workspace-id
          in: header
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  minLength: 1
                  description: The template's name.
                  example: Employment agreement
                description:
                  type: string
                  description: Free-text description of what the template is for.
                  example: Standard individual employment agreement for new hires.
                status:
                  allOf:
                    - $ref: '#/components/schemas/TemplateStatus'
                    - description: >-
                        Initial lifecycle state. Defaults to DRAFT. ACTIVE also
                        stamps the publish time; ARCHIVED stamps the archive
                        time. ACTIVE is refused with 400 when `signingMode` is
                        WORKFLOW and the questions break a workflow rule; save
                        as DRAFT to keep them and read the problems from
                        `warnings`.
                      example: DRAFT
                tags:
                  type: array
                  items:
                    type: string
                  description: >-
                    Organisation tags to put on the template. A tag that does
                    not exist yet is created.
                  example:
                    - HR
                    - Onboarding
                reminderIntervalDays:
                  type: integer
                  minimum: 1
                  description: >-
                    Days between automatic reminders to each recipient who
                    hasn't finished, counted from their invitation. Null or
                    absent sends none.
                  example: 3
                expirationDays:
                  type: integer
                  minimum: 1
                  description: >-
                    Days the package stays open for signing, counted from when
                    it is sent. Null or absent means it never expires.
                  example: 30
                expiryWarningDays:
                  type: integer
                  minimum: 1
                  description: >-
                    Days before expiry at which recipients who haven't finished
                    are warned. MUST be fewer than `expirationDays`.
                  example: 5
                emailSubject:
                  type: string
                  description: >-
                    Subject of the invitation email. {{key}} placeholders are
                    filled from the package's merge field values.
                  example: Your employment agreement with Studio Phoenix Limited
                emailMessage:
                  type: string
                  description: >-
                    Body of the invitation email. {{key}} placeholders are
                    filled from the package's merge field values.
                  example: >-
                    Kia ora {{employee_name}}, please review and sign your
                    agreement.
                signingMode:
                  allOf:
                    - $ref: '#/components/schemas/SigningMode'
                    - description: >-
                        How recipients are walked through signing. PARALLEL (the
                        default) invites every role at once; SEQUENTIAL invites
                        one role at a time in `order`; WORKFLOW follows the
                        template's workflow, asking recipients its questions as
                        they open the package.
                brandColor:
                  type: string
                  nullable: true
                  pattern: ^#[0-9a-fA-F]{6}$
                  description: >-
                    Accent colour for the signing experience and emails, as a
                    six-digit hex code. Needs a plan with custom branding,
                    otherwise 402. Null clears it.
                  example: '#1a2b3c'
                roles:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                        minLength: 1
                        description: >-
                          The role's id. Carry the id from `GET
                          /api/v1/templates/:templateId` to keep a role and the
                          fields placed for it; a role left out of `roles` is
                          removed with its fields. A new role may take an id of
                          your own choosing, which a merge field's
                          `binding.roleId` in the same request can name; the
                          saved role gets a server id.
                        example: cmg3k2v8a0001s7p4d9x1qz2h
                      name:
                        type: string
                        minLength: 1
                        description: >-
                          The role's name, unique within the template. A role is
                          a named slot a person fills when a package is
                          launched: each recipient in `POST
                          /api/v1/packages/from-template` is matched onto a role
                          by this exact name.
                        example: Employee
                      actionType:
                        allOf:
                          - $ref: '#/components/schemas/ActionType'
                          - description: >-
                              What the person filling this role does with the
                              package. SIGNER completes fields and signs; VIEWER
                              can open and read the package while it is out but
                              has no fields; CC only receives the finished copy
                              by email and never gets a signing session.
                              Defaults to SIGNER.
                      order:
                        type: integer
                        minimum: 0
                        description: >-
                          Zero-based position of the role. In SEQUENTIAL signing
                          mode roles are invited one at a time in this order; in
                          PARALLEL mode it only orders the list.
                        example: 0
                      deliveryDefault:
                        allOf:
                          - $ref: '#/components/schemas/RecipientDelivery'
                          - description: >-
                              How the recipient filling this role receives the
                              package by default. EMAIL (the default) sends an
                              invitation; IN_PERSON is hosted on someone's
                              device.
                      hostRole:
                        $ref: '#/components/schemas/RecipientHostRole'
                      hostUserIds:
                        type: array
                        items:
                          type: string
                          minLength: 1
                        maxItems: 5
                        description: >-
                          The members who may host an IN_PERSON recipient when
                          `hostRole` is SPECIFIC_USER. Up to 5.
                        example:
                          - 8f1c2a4e-6b3d-4c9a-9e7f-2d5b1a3c4e6f
                      hostGroupIds:
                        type: array
                        items:
                          type: string
                          minLength: 1
                        maxItems: 3
                        description: >-
                          The member groups whose members may host when
                          `hostRole` is MEMBER_GROUP. Up to 3.
                        example:
                          - cmg1hd3x10002v8p9f6r8bt4n
                    required:
                      - name
                      - order
                  minItems: 1
                  maxItems: 100
                  description: >-
                    The named slots recipients fill at launch. At least one, at
                    most 100.
                metadata:
                  nullable: true
                  description: >-
                    Not accepted. A template's default custom field values are
                    set in the app; sending this is refused with 400 and nothing
                    is saved.
                questions:
                  type: array
                  items:
                    type: object
                    properties:
                      question:
                        type: string
                        minLength: 1
                        description: The question as it is asked.
                        example: Does the role include a company vehicle?
                      type:
                        $ref: '#/components/schemas/QuestionType'
                      order:
                        type: integer
                        minimum: 0
                        description: >-
                          Zero-based position of the question among the
                          template's questions.
                        example: 0
                      dependsOnQuestionIndex:
                        type: integer
                        minimum: 0
                        description: >-
                          Zero-based index into `questions` of the question
                          whose answer reveals this one. Give it together with
                          `dependsOnOptionIndex`; a pair that names nothing is
                          ignored.
                        example: 0
                      dependsOnOptionIndex:
                        type: integer
                        minimum: 0
                        description: >-
                          Zero-based index into that question's `options` of the
                          answer that reveals this question.
                        example: 0
                      options:
                        type: array
                        items:
                          type: object
                          properties:
                            label:
                              type: string
                              minLength: 1
                              description: >-
                                The answer as it is shown to the person
                                answering.
                              example: 'Yes'
                            order:
                              type: integer
                              minimum: 0
                              description: >-
                                Zero-based position of the option among the
                                question's options.
                              example: 0
                            isDefault:
                              type: boolean
                              description: >-
                                Whether this option is preselected. When no
                                option sets it, the last option is the default.
                              example: true
                            actions:
                              type: array
                              items:
                                type: object
                                properties:
                                  type:
                                    $ref: '#/components/schemas/QuestionActionType'
                                  targetDocumentId:
                                    type: string
                                    nullable: true
                                    description: >-
                                      The template document the action applies
                                      to, by document id. A reference the
                                      template does not recognise is dropped and
                                      reported in `warnings`.
                                    example: cmg3k5r1c0003s7p4h2m8tb7k
                                  targetFieldId:
                                    type: string
                                    nullable: true
                                    description: >-
                                      Reserved for SHOW_FIELD and HIDE_FIELD,
                                      which this endpoint does not currently
                                      apply.
                                    example: cmg3k7q9e0004s7p4b1z6lc3n
                                required:
                                  - type
                              description: >-
                                What happens to the package's documents when
                                this option is picked.
                          required:
                            - label
                            - order
                          additionalProperties: false
                        description: >-
                          The answers on offer, each with the actions it
                          triggers.
                    required:
                      - question
                      - order
                  description: >-
                    Conditional questions the sender answers at launch. Each
                    answer's actions decide which documents the package
                    includes. Questions reference each other by position in this
                    array.
                mergeFields:
                  type: array
                  items:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        description: >-
                          Placeholder name, written as {{key}} in the email
                          subject and message and in document text, and used as
                          the key in `fields` when launching a package. Trimmed
                          and unique within the template: a repeated or blank
                          key is skipped.
                        example: start_date
                      label:
                        type: string
                        minLength: 1
                        description: >-
                          Human-readable name shown to the sender when the value
                          is asked for.
                        example: Start date
                      description:
                        type: string
                        description: Help text shown to the sender alongside the field.
                        example: The employee's first day of work.
                      source:
                        $ref: '#/components/schemas/MergeFieldSource'
                      binding:
                        $ref: '#/components/schemas/MergeFieldBinding'
                      type:
                        $ref: '#/components/schemas/VariableType'
                      options:
                        type: array
                        items:
                          type: string
                        description: >-
                          Allowed values for a list field. Entries are trimmed
                          and blanks dropped. When set, the default and any
                          launch value must be one of them.
                        example:
                          - Full time
                          - Part time
                      defaultValue:
                        type: string
                        description: >-
                          The value the package uses when the sender leaves the
                          field blank at launch. Checked against `type` and
                          `options`; a bad default is rejected with 422 under
                          `mergeFields.<key>.defaultValue`.
                        example: '2026-10-01'
                      isRequired:
                        type: boolean
                        description: >-
                          Whether a value must exist at launch, from the sender
                          or from `defaultValue`. Defaults to false.
                        example: true
                      order:
                        type: integer
                        minimum: 0
                        description: >-
                          Zero-based display position among the template's merge
                          fields.
                        example: 0
                    required:
                      - key
                      - label
                      - order
                  description: >-
                    Values the template collects and merges into its documents
                    and emails. Blank at launch means the field's default.
              required:
                - name
                - roles
      responses:
        '201':
          description: Success
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        description: >-
                          The id of the new template. Add documents with `POST
                          /api/v1/templates/:templateId/documents` and place
                          fields with `PUT
                          /api/v1/templates/:templateId/fields`.
                        example: kX9dQ2mB7pLw
                      warnings:
                        type: array
                        items:
                          type: string
                        description: >-
                          Present only when a question dependency or document
                          reference could not be applied, which the template is
                          saved without, or when the questions break a workflow
                          rule a DRAFT is allowed to hold.
                        example:
                          - >-
                            Question 2 depends on an answer that does not exist
                            and was left unconditional
                    required:
                      - id
                required:
                  - data
        '400':
          description: >-
            The body is not valid JSON, or `status` is ACTIVE and the questions
            break a workflow rule
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Caller's plan does not include this feature (publicApi / webhooks)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: API key present but caller lacks the required permission
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Request failed schema validation; details keyed by field
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: Rate limit exceeded; see `Retry-After`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    TemplateStatus:
      type: string
      enum:
        - DRAFT
        - ACTIVE
        - ARCHIVED
      description: >-
        Lifecycle state. DRAFT is still being built, ACTIVE is published and
        ready to launch packages from, ARCHIVED is retired but kept for
        reference.
      example: ACTIVE
    SigningMode:
      type: string
      enum:
        - PARALLEL
        - SEQUENTIAL
        - WORKFLOW
      description: >-
        PARALLEL (the default) invites everyone at once; SEQUENTIAL invites one
        recipient at a time in the order given. WORKFLOW is refused here, since
        a workflow is drawn in the app or comes from a template.
      example: SEQUENTIAL
    ActionType:
      type: string
      enum:
        - SIGNER
        - VIEWER
        - CC
      description: >-
        What the recipient does with the package. SIGNER completes fields and
        signs; VIEWER can open and read the package while it is out but has no
        fields; CC only receives the finished copy by email and never gets a
        signing session.
      example: SIGNER
    RecipientDelivery:
      type: string
      enum:
        - EMAIL
        - IN_PERSON
      description: >-
        How the recipient receives the package. EMAIL sends them an invitation;
        IN_PERSON sends no email, and a host opens the session and hands the
        device over.
      example: EMAIL
    RecipientHostRole:
      type: string
      enum:
        - SENDER
        - SPECIFIC_USER
        - MEMBER_GROUP
      description: >-
        Who may host an IN_PERSON recipient's session. SENDER is whoever sent
        the package; SPECIFIC_USER is one of `hostUserIds`; MEMBER_GROUP is any
        member of `hostGroupIds`.
      example: SENDER
    QuestionType:
      type: string
      enum:
        - TOGGLE
        - CHOICE
      description: >-
        How the answers are offered. TOGGLE is a yes/no pair; CHOICE is a named
        list. Presentational only: the options are stored as given either way.
      example: TOGGLE
    QuestionActionType:
      type: string
      enum:
        - INCLUDE_DOCUMENT
        - EXCLUDE_DOCUMENT
        - SHOW_FIELD
        - HIDE_FIELD
      description: >-
        What picking this option does. INCLUDE_DOCUMENT attaches the document in
        `targetDocumentId` to the package and EXCLUDE_DOCUMENT drops it.
        SHOW_FIELD and HIDE_FIELD are accepted but not applied by this endpoint.
      example: INCLUDE_DOCUMENT
    MergeFieldSource:
      type: string
      enum:
        - SENDER
        - AUTHOR
        - MAPPED
        - WORKFLOW
      description: >-
        Who supplies a merge field's value. SENDER asks the sender at launch;
        AUTHOR fixes it to `defaultValue`; MAPPED reads it from a recipient's
        details through `binding`; WORKFLOW lets a workflow answer set it.
      example: SENDER
    MergeFieldBinding:
      type: object
      properties:
        kind:
          type: string
          enum:
            - recipient
          description: >-
            Where the value is read from. `recipient` reads one of a role's
            recipient details.
          example: recipient
        roleId:
          type: string
          minLength: 1
          description: The template role whose recipient the value is read from.
          example: cmg3k2v8a0001s7p4d9x1qz2h
        attribute:
          type: string
          enum:
            - name
            - email
          description: Which of the recipient's details fills the value.
          example: name
      required:
        - kind
        - roleId
        - attribute
      description: Where a MAPPED merge field reads its value from.
    VariableType:
      type: string
      enum:
        - TEXT
        - NUMBER
        - DATE
        - CURRENCY
      description: >-
        Value type, which decides how the default and launch values are
        validated: TEXT (free text), NUMBER, DATE (ISO 8601 date) or CURRENCY.
        Defaults to TEXT.
      example: DATE
    Error:
      type: object
      properties:
        error:
          type: string
          description: What went wrong, in plain words.
          example: 'Missing permission: canSendPackages'
        details:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          description: >-
            Validation problems keyed by field path. Present only on 422
            responses.
          example:
            recipients.0.email:
              - Invalid email
      required:
        - error
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      bearerFormat: fsk_*

````