openapi: 3.0.3
info:
  title: Mobile Check Cashing SDK — Add or Update Card (Non-Tokenized)
  version: '1'
  description: |
    Add or update a card for a customer using the raw card PAN
    (15- or 16-digit unformatted). Card Partner specific.

    Behavior:

    - If the submitted card data exactly matches the data stored at
      Ingo, no changes are made and the card is not re-authorized.
    - If any card data changes (e.g., expiration), the card is
      reauthorized (AVS check, etc.). An authorization failure flags
      the card as invalid and returns the failure detail in the
      response error.
    - Partners may only update cards they own.

    For PCI-friendlier flows where the partner never exposes the raw
    PAN to Ingo, use `POST /api/v1/partners/add-or-update-tokenized-card`
    (see `cdrm-sdk-card-add-or-update-tokenized.yaml`). Partner
    configuration controls which of the two endpoints is enabled.

    Card-Partner only. Requires an active SDK partner session — the
    `SessionId` header from `POST /api/v1/partners/authenticate` — plus
    the customer's `customerId`. It does not require the OBO `ssoToken`;
    card setup typically runs before `/authenticate-obo`.
servers:
  - url: https://check-cashing-uat.spykemobile.net
    description: UAT (Sandbox)
  - url: https://check-cashing.spykemobile.net
    description: Production
security:
  - OAuth2:
      - sdkapi
tags:
  - name: Cards
    description: Card account management for Card Partners.
paths:
  /api/v1/partners/add-or-update-card:
    post:
      tags:
        - Cards
      operationId: addOrUpdateCard
      summary: Add or update a card (raw PAN)
      description: |
        Adds a new card or updates an existing card for the customer.
        See the operation `description` field in the info block for
        the full update-vs-reauth semantics.
      parameters:
        - $ref: '#/components/parameters/SessionIdHeader'
        - $ref: '#/components/parameters/DeviceIdHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AddOrUpdateCardRequest'
            example:
              customerId: 333554bf-b273-4d6e-b4f8-d319a1929608
              cardNumber: '4111111504856777'
              expirationMonthYear: '1225'
              cardNickname: Home
              nameOnCard: Test User
              addressLine1: 123 Main Street
              addressLine2: ''
              city: Nashville
              state: TN
              zip: '37075'
      responses:
        '200':
          description: Card added or updated. Returns the resulting card list.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardListResponse'
              example:
                cards:
                  - cardId: 1db0c5a1-62fc-4295-8a12-7997056d4fc9
                    lastFourDigits: '6777'
                    customerId: ''
                    showTermsAndConditions: false
                    termsAndConditionsId: ''
                    cardArtAsBase64Png: ''
                    cardProgram: ''
                    cardNickname: ''
                    expirationMonthYear: ''
                    cardProgramPhone: ''
                    currentCardMax: 0
                    currentCardMin: 0
                    issuerType: 0
                    hashId: ''
        '400':
          description: Validation error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationProblemDetails'
              example:
                errors: {}
                type: https://tools.ietf.org/html/rfc7231#section-6.5.1
                title: Bad Request
                status: 400
                detail: One or more validation errors occurred.
                instance: /api/v1/partners/add-or-update-card
                validationErrors:
                  - key: command.CardNumber
                    message: CardNumber cannot exceed 19 characters
components:
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://auth.spykemobile.net/connect/token
          scopes:
            sdkapi: Mobile Check Cashing SDK partner methods
  parameters:
    SessionIdHeader:
      name: SessionId
      in: header
      required: true
      schema:
        type: string
    DeviceIdHeader:
      name: DeviceId
      in: header
      required: true
      schema:
        type: string
  schemas:
    AddOrUpdateCardRequest:
      type: object
      required:
        - customerId
        - cardNumber
        - expirationMonthYear
        - cardNickname
        - addressLine1
        - addressLine2
        - city
        - state
        - zip
      properties:
        customerId:
          type: string
          format: uuid
          minLength: 36
          maxLength: 36
        cardNumber:
          type: string
          minLength: 15
          maxLength: 19
          pattern: ^[0-9]{15,19}$
          description: |
            Unformatted card PAN — 15 or 16 digits per dev-center
            doc; allowed up to 19 by the validator. Never log this
            value.
        expirationMonthYear:
          type: string
          minLength: 4
          maxLength: 4
          pattern: ^(0[1-9]|1[0-2])[0-9]{2}$
          description: |
            MMYY format. Single-digit months must be zero-padded
            (e.g., May 2025 = `0525`).
        cardNickname:
          type: string
          minLength: 1
          maxLength: 20
          description: User-set nickname, up to 20 characters.
        nameOnCard:
          type: string
          maxLength: 100
        addressLine1:
          type: string
          minLength: 1
          maxLength: 50
        addressLine2:
          type: string
          minLength: 1
          maxLength: 50
        city:
          type: string
          minLength: 1
          maxLength: 50
        state:
          type: string
          minLength: 1
          maxLength: 2
          description: Two-character US state code.
        zip:
          type: string
          minLength: 5
          maxLength: 5
          pattern: ^[0-9]{5}$
    CardListResponse:
      type: object
      required:
        - cards
      properties:
        cards:
          type: array
          items:
            $ref: '#/components/schemas/Card'
    Card:
      type: object
      properties:
        cardId:
          type: string
          format: uuid
        customerId:
          type: string
        cardNickname:
          type: string
        cardProgram:
          type: string
        cardArtAsBase64Png:
          type: string
        lastFourDigits:
          type: string
          maxLength: 4
        showTermsAndConditions:
          type: boolean
        termsAndConditionsId:
          type: string
        issuerType:
          type: integer
        expirationMonthYear:
          type: string
        cardProgramPhone:
          type: string
        currentCardMin:
          type: integer
        currentCardMax:
          type: integer
        hashId:
          type: string
    ValidationProblemDetails:
      type: object
      required:
        - type
        - title
        - status
      properties:
        errors:
          type: object
          additionalProperties: true
        type:
          type: string
          format: uri
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        instance:
          type: string
        validationErrors:
          type: array
          items:
            type: object
            required:
              - key
              - message
            properties:
              key:
                type: string
              message:
                type: string
