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

# Batch create passes

> Create multiple passes in a single request. Supports up to 1000 passes per call with automatic duplicate detection.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/passes/batch
openapi: 3.0.1
info:
  title: Stell API
  description: >-
    Create and manage passes for Apple Wallet and Google Wallet. One API for
    loyalty programs, membership cards, tickets, and more.


    ## Errors


    Errors returned by Stell use one JSON shape:


    ```json

    {
      "error": {
        "code": "NOT_FOUND",
        "message": "Pass not found",
        "details": { "passId": "3f1c2b8e-9a4d-4c5e-8f7a-1b2c3d4e5f60" }
      },
      "requestId": "01J9Z3K8QH5X2V7RMT4N6WBCDE"
    }

    ```


    `code` is one of `BAD_REQUEST`, `VALIDATION_ERROR`, `UNAUTHORIZED`,
    `FORBIDDEN`, `NOT_FOUND`, `CONFLICT`, `UNPROCESSABLE_ENTITY` or
    `INTERNAL_ERROR`. `details` is optional and its fields depend on the error:
    for example `missingFields` for required fields left out, `errors` for pass
    template validation, or the `passId` that was not found.


    API Gateway rejects some requests before they reach Stell: a missing or
    invalid API key, a throttled request (429), and a request body or required
    parameter that does not match the published schema (400, for example
    `{"message": "Invalid request body"}`). These get a short error body from
    API Gateway instead, with no `error` object and no `requestId`.


    ## Request IDs


    Responses from Stell carry a request ID in the `X-Request-Id` header, except
    `GET /v1/health` and `204 No Content` responses. Error bodies from Stell
    repeat it as `requestId`, and so do success bodies except `GET
    /v1/merchants/{merchantId}`, which returns the merchant without a wrapper.
    Include the request ID when you contact Stell support about a request.


    ## Pagination


    List endpoints that accept `limit` return one page at a time. `limit` sets
    the page size, from 1 to 100, and defaults to 100; a value outside that
    range returns 400. When more results exist, the response includes a
    `nextToken`. Send it back as the `nextToken` query parameter to get the next
    page, and stop when a response has no `nextToken`. A page can hold fewer
    items than `limit` and still have a `nextToken`. `GET /v1/companies` returns
    only your own company, so it ignores `limit` and never returns a
    `nextToken`.
  termsOfService: https://getstell.com/terms
  contact:
    name: Stell API Support
    url: https://getstell.com/about?topic=Technical%20Support#contact
    email: hello@getstell.com
  version: '2026-09-30T16:18:58Z'
servers:
  - url: https://api.platform.getstell.com
    description: Production API
security:
  - StellApiAuthorizer: []
tags:
  - name: Companies
    description: Manage companies at the top of your tenant hierarchy.
  - name: Merchants
    description: Manage brands and business units within companies.
  - name: Stores
    description: Manage store locations and customer touchpoints.
  - name: Programs
    description: Configure pass programs for loyalty, membership, tickets, and more.
  - name: Pass Templates
    description: Define pass design and field layouts.
  - name: Passes
    description: Issue and manage customer passes for Apple and Google Wallet.
  - name: Terminals
    description: Configure terminals for tap-to-scan functionality.
  - name: Transactions
    description: Track pass usage, purchases, and redemptions.
  - name: Engagement
    description: Geofences, notifications, and location-based engagement features.
  - name: System
    description: Health checks and service monitoring.
paths:
  /v1/passes/batch:
    post:
      tags:
        - Passes
      summary: Batch create passes
      description: >-
        Create multiple passes in a single request. Supports up to 1000 passes
        per call with automatic duplicate detection.
      operationId: batchCreatePasses
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BatchCreatePassesModel'
        required: true
      responses:
        '201':
          description: 201 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchCreatePassesResponseModel'
        '400':
          description: 400 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error400Model'
        '401':
          description: 401 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error401Model'
        '403':
          description: 403 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error403Model'
        '404':
          description: 404 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error404Model'
        '500':
          description: 500 response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error500Model'
      security:
        - StellApiAuthorizer: []
components:
  schemas:
    BatchCreatePassesModel:
      title: BatchCreatePassesModel
      required:
        - passes
        - programId
      type: object
      properties:
        passes:
          maxItems: 1000
          minItems: 1
          type: array
          description: Array of passes to create (1-1000 items)
          items:
            required:
              - walletType
            type: object
            properties:
              templateOverrides:
                type: object
                additionalProperties: true
                description: >-
                  Template overrides for this pass. Same shape as single pass
                  creation: images.{slot} accepts { "sourceUrl": "https://..." }
                  or { "uploadId": "..." }, and null clears the slot.
              payload:
                maxLength: 64
                type: string
                description: NFC/QR payload string (max 64 chars)
              walletType:
                type: string
                description: Target wallet platform for the pass
                enum:
                  - APPLE_WALLET
                  - GOOGLE_WALLET
              loyaltyState:
                type: object
                additionalProperties: true
                description: Loyalty program state data
              notificationMessage:
                type: string
                description: >-
                  Message shown when the pass is updated (wallet push / pass
                  refresh)
              attribution:
                type: object
                properties:
                  referrerHost:
                    maxLength: 253
                    type: string
                    description: Referrer host only, never a full URL
                  reference:
                    maxLength: 200
                    type: string
                    description: 'Opaque correlation id: request id, endpoint id, session id'
                  origin:
                    type: string
                    description: >-
                      STELL = a Stell-hosted surface, MERCHANT = the merchant's
                      own code calling the API (default), PARTNER = a
                      third-party connector acting for the merchant
                    enum:
                      - STELL
                      - MERCHANT
                      - PARTNER
                  channel:
                    type: string
                    description: >-
                      Where the person came from. When omitted it is DECLARED
                      from campaign.medium (email, sms, qr, print, terminal,
                      social, paid, push, web) or otherwise INFERRED from the
                      mechanism.
                    enum:
                      - EMAIL
                      - SMS
                      - QR
                      - PRINT
                      - TERMINAL
                      - SOCIAL
                      - PAID
                      - PUSH
                      - WEB
                      - DIRECT
                      - UNKNOWN
                  campaign:
                    type: object
                    properties:
                      campaign:
                        maxLength: 200
                        type: string
                      term:
                        maxLength: 200
                        type: string
                      source:
                        maxLength: 200
                        type: string
                      medium:
                        maxLength: 200
                        type: string
                      content:
                        maxLength: 200
                        type: string
                    additionalProperties: false
                    description: utm_* parameters as received
                  mechanism:
                    type: string
                    description: >-
                      How the pass was created. Named for what happened, never
                      for which system did it.
                    enum:
                      - API
                      - VAS_PERSONALIZATION
                      - VAS_MEMBER_LINK
                      - ADMIN_FORM
                      - PORTAL_ISSUE
                      - ONBOARDING_FORM
                      - ONBOARDING_FORM_OTP
                      - ONBOARDING_FORM_IDENTITY
                      - PREBOARDING_LINK
                      - DIRECT_LINK
                      - EMBED_WIDGET
                      - APP_CLIP
                      - APP
                      - CRM_SYNC
                  channelConfidence:
                    type: string
                    description: >-
                      DECLARED when the channel came from utm_medium or the
                      caller, INFERRED otherwise; PUSH is always DECLARED
                    enum:
                      - DECLARED
                      - INFERRED
                  landingPath:
                    maxLength: 200
                    type: string
                    description: >-
                      Landing route template (e.g. /p/{nanoId}/{memberId}),
                      never a real id
                  identityProvider:
                    pattern: ^[a-z0-9-]{1,50}$
                    type: string
                    description: >-
                      Identity provider slug (e.g. vipps) the person
                      authenticated with. Required with mechanism
                      ONBOARDING_FORM_IDENTITY and rejected with 400 on any
                      other mechanism.
                additionalProperties: false
                description: >-
                  Attribution: whose surface created the pass (origin), how it
                  was created (mechanism) and where the person came from
                  (channel + campaign). Every field is optional; absent fields
                  default to origin MERCHANT, mechanism API, channel inferred,
                  reference = request id.
              externalId:
                maxLength: 100
                type: string
                description: >-
                  External reference ID from CRM or other systems (max 100
                  chars)
              activationDate:
                type: string
                description: ISO 8601 date when the pass becomes active
                format: date-time
              entryState:
                type: object
                additionalProperties: true
                description: Entry-related state data
              customer:
                type: object
                properties:
                  firstName:
                    type: string
                    description: Customer first name
                  lastName:
                    type: string
                    description: Customer last name
                  emailAddress:
                    type: string
                    description: Customer email address
                    format: email
                  personalId:
                    maxLength: 64
                    type: string
                    description: >-
                      National/personal identity number (e.g., Swedish
                      personnummer). Optional. PII — sent only when required by
                      merchant.
                  lookupSource:
                    maxLength: 50
                    pattern: ^[a-z0-9-]+$
                    type: string
                    description: >-
                      Which CRM was queried for new/existing determination
                      (e.g., "voyado")
                  mobileNumber:
                    type: string
                    description: Customer mobile phone number
                  isNew:
                    type: boolean
                    description: >-
                      Whether the customer is new (not found in merchant CRM).
                      Set at creation, immutable.
                additionalProperties: true
                description: Customer information for personalization
              expirationDate:
                type: string
                description: ISO 8601 date when the pass expires
                format: date-time
            description: One pass to create within the batch
        options:
          type: object
          properties:
            stopOnError:
              type: boolean
              description: 'Stop processing on first error (default: false)'
            skipDuplicates:
              type: boolean
              description: 'Skip passes where externalId already exists (default: false)'
          description: Batch processing options
        programId:
          minLength: 1
          type: string
          description: >-
            ID of the program to create passes for (all passes in batch use the
            same program)
      description: Request to batch create multiple passes.
    BatchCreatePassesResponseModel:
      title: BatchCreatePassesResponseModel
      required:
        - data
        - requestId
      type: object
      properties:
        data:
          required:
            - results
            - summary
          type: object
          properties:
            summary:
              required:
                - failed
                - processingTimeMs
                - skipped
                - succeeded
                - total
              type: object
              properties:
                total:
                  type: integer
                  description: Total passes in request
                processingTimeMs:
                  type: integer
                  description: Total processing time in milliseconds
                failed:
                  type: integer
                  description: Passes that failed to create
                succeeded:
                  type: integer
                  description: Passes created successfully
                skipped:
                  type: integer
                  description: Passes skipped (duplicates)
              description: Batch processing summary
            results:
              type: array
              description: Per-pass results in request order
              items:
                required:
                  - index
                  - status
                type: object
                properties:
                  passId:
                    type: string
                    description: ID of created pass (when status=created)
                  link:
                    type: string
                    description: >-
                      Permanent public link for the created pass (when
                      status=created). Never expires; resolves at open time to
                      the applicable wallet action. Append ?delivery=direct to
                      302 straight to the wallet artifact instead of the landing
                      page.
                    format: uri
                  index:
                    type: integer
                    description: Position in original request array
                  externalId:
                    type: string
                    description: External ID from request
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Error code
                      message:
                        type: string
                        description: Human-readable error message
                    description: Error details (when status=failed)
                  status:
                    type: string
                    description: Result status for this pass
                    enum:
                      - created
                      - failed
                      - skipped
                description: Result for one pass from the batch request
          description: Batch creation summary and per-pass results
        requestId:
          pattern: ^[0-9A-Z]{26}$
          type: string
          description: Unique request identifier for debugging
      description: Response from batch pass creation.
    Error400Model:
      title: Error400Model
      required:
        - error
        - requestId
      type: object
      properties:
        requestId:
          pattern: ^[0-9A-Z]{26}$
          type: string
          description: Unique request identifier for debugging
        error:
          required:
            - code
            - message
          type: object
          properties:
            code:
              type: string
              description: Machine-readable error code
              enum:
                - BAD_REQUEST
            details:
              type: object
              additionalProperties: true
              description: Additional error context
            message:
              type: string
              description: Human-readable error message
              default: Invalid request parameters
          description: Error information
      description: Bad request with validation details.
    Error401Model:
      title: Error401Model
      required:
        - error
        - requestId
      type: object
      properties:
        requestId:
          pattern: ^[0-9A-Z]{26}$
          type: string
          description: Unique request identifier for debugging
        error:
          required:
            - code
            - message
          type: object
          properties:
            code:
              type: string
              description: Machine-readable error code
              enum:
                - UNAUTHORIZED
            details:
              type: object
              additionalProperties: true
              description: Additional error context
            message:
              type: string
              description: Human-readable error message
              default: Authentication required
          description: Error information
      description: Authentication failed.
    Error403Model:
      title: Error403Model
      required:
        - error
        - requestId
      type: object
      properties:
        requestId:
          pattern: ^[0-9A-Z]{26}$
          type: string
          description: Unique request identifier for debugging
        error:
          required:
            - code
            - message
          type: object
          properties:
            code:
              type: string
              description: Machine-readable error code
              enum:
                - FORBIDDEN
            details:
              type: object
              additionalProperties: true
              description: Additional error context
            message:
              type: string
              description: Human-readable error message
              default: Access denied to this resource
          description: Error information
      description: Access denied.
    Error404Model:
      title: Error404Model
      required:
        - error
        - requestId
      type: object
      properties:
        requestId:
          pattern: ^[0-9A-Z]{26}$
          type: string
          description: Unique request identifier for debugging
        error:
          required:
            - code
            - message
          type: object
          properties:
            code:
              type: string
              description: Machine-readable error code
              enum:
                - NOT_FOUND
            details:
              type: object
              additionalProperties: true
              description: Additional error context
            message:
              type: string
              description: Human-readable error message
              default: Resource not found
          description: Error information
      description: Resource not found.
    Error500Model:
      title: Error500Model
      required:
        - error
        - requestId
      type: object
      properties:
        requestId:
          pattern: ^[0-9A-Z]{26}$
          type: string
          description: Unique request identifier for debugging
        error:
          required:
            - code
            - message
          type: object
          properties:
            code:
              type: string
              description: Machine-readable error code
              enum:
                - INTERNAL_ERROR
            details:
              type: object
              additionalProperties: true
              description: Additional error context
            message:
              type: string
              description: Human-readable error message
              default: An internal server error occurred
          description: Error information
      description: Internal server error.
  securitySchemes:
    StellApiAuthorizer:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: |-
        API key authentication. Include your API key as a Bearer token.

        Example: `Bearer sk_prod_xxxxxx`

        Get your API key from the Stell Dashboard.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.