openapi: 3.0.1
info:
  title: Cards Connector REST APIs
  description: Cards Connector Internal REST APIs
  version: '1'
servers:
  - url: 'https://api.plumery.com'
    description: Live Server
paths:
  '/internal/v1/cards/{token}':
    get:
      description: |
        Retrieve details of a specific card. The response contains confidential card 
        details such as the full Primary Account Number (PAN) and CVV2 number.
      operationId: Get card
      parameters:
        - $ref: '#/components/parameters/cardToken'
        - $ref: '#/components/parameters/xClientPublicKey'
      responses:
        '200':
          $ref: "#/components/responses/CardResponse"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}/pin':
    get:
      operationId: Retrieve card PIN
      parameters:
        - $ref: '#/components/parameters/cardToken'
        - $ref: '#/components/parameters/xClientPublicKey'
      responses:
        '200':
          $ref: '#/components/responses/CardPinResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}:terminate':
    post:
      description: |
        Terminate a specific card.
      operationId: Terminate card
      parameters:
        - $ref: '#/components/parameters/cardToken'
      responses:
        '204':
          $ref: "#/components/responses/NoContent"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}:freeze':
    post:
      description: |
        Freeze a specific card.
      operationId: Freeze card
      parameters:
        - $ref: '#/components/parameters/cardToken'
      responses:
        '204':
          $ref: "#/components/responses/NoContent"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}:unfreeze':
    post:
      description: |
        Unfreeze a specific card.
      operationId: Unfreeze card
      parameters:
        - $ref: '#/components/parameters/cardToken'
      responses:
        '204':
          $ref: "#/components/responses/NoContent"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}:update-alias':
    post:
      description: |
        Update alias for a specific card.
      operationId: Update alias
      parameters:
        - $ref: '#/components/parameters/cardToken'
      requestBody:
        $ref: "#/components/requestBodies/UpdateAliasRequest"
      responses:
        '204':
          $ref: "#/components/responses/NoContent"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}:provision-google-wallet':
    post:
      description: |
        Initiates the provisioning of a card to Google Wallet.
      operationId: Provision Google Wallet
      parameters:
        - $ref: '#/components/parameters/cardToken'
      requestBody:
        $ref: "#/components/requestBodies/ProvisionGoogleWalletRequest"
      responses:
        '200':
          $ref: "#/components/responses/GoogleWalletProvisionResponse"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true

  '/internal/v1/cards/{token}:provision-apple-wallet':
    post:
      description: |
        Initiates the provisioning of a card to Apple Wallet.
      operationId: Provision Apple Wallet
      parameters:
        - $ref: '#/components/parameters/cardToken'
      requestBody:
        $ref: "#/components/requestBodies/ProvisionAppleWalletRequest"
      responses:
        '200':
          $ref: "#/components/responses/AppleWalletProvisionResponse"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
  '/internal/v1/cards/{token}:activate':
    post:
      description: |
        Activate a specific card.
      operationId: Activate card
      parameters:
        - $ref: '#/components/parameters/cardToken'
      responses:
        '204':
          $ref: "#/components/responses/NoContent"
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/ServerError'
      x-internal: true
components:
  responses:
    CardResponse:
      description: Card
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CardResponse"
    CardPinResponse:
      description: Pin belonging to a card
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/CardPin"
    GoogleWalletProvisionResponse:
      description: Provision Google Wallet Response
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/GoogleWalletProvisionResponse"
    AppleWalletProvisionResponse:
      description: Provision Apple Wallet Response
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/AppleWalletProvisionResponse"
    NoContent:
      description: Request was successfully executed, without further response being returned.
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/NoContentResponse"
    BadRequest:
      description: Invalid request was provided
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BadRequestResponse'
    ServerError:
      description: Internal server error occurred
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InternalServerErrorResponse'
  parameters:
    cardToken:
      in: path
      name: token
      required: true
      description: Internal unique identifier for the card. See CardToken model.
      schema:
        $ref: "#/components/schemas/CardToken"
    xClientPublicKey:
      in: header
      name: X-Client-Public-Key
      required: true
      description: |
        Base64-encoded ECDH client public key using `secp256r1` elliptic curve. See XClientPublicKey model.
      schema:
        $ref: "#/components/schemas/xClientPublicKey"
  schemas:
    NoContentResponse:
      type: string
      description: |
        Request was successfully executed, without further response being returned.
    BadRequestResponse:
      description: Bad Request Response
      type: object
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
        requestId:
          type: string
        fieldErrors:
          type: array
          items:
            $ref: '#/components/schemas/FieldError'
    InternalServerErrorResponse:
      description: Internal server error response
      type: object
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
        message:
          type: string
        requestId:
          type: string
        fieldErrors:
          type: array
          items:
            $ref: '#/components/schemas/FieldError'
    ErrorCode:
      type: string
      enum:
        - 'urn:plmr:cards:connector:CARD_NOT_FOUND'
        - 'urn:plmr:cards:connector:CARD_ALREADY_TERMINATED'
        - 'urn:plmr:cards:connector:INVALID_CLIENT_PUBLIC_KEY'
        - 'urn:plmr:cards:connector:INVALID_CARD_STATE'
        - 'urn:plmr:cards:connector:IN_APP_PROVISION_NOT_ALLOWED'
        - 'urn:plmr:cards:connector:INVALID_CERTIFICATE_CHAIN'
      example: 'urn:plmr:cards:connector:BAD_REQUEST'
    FieldErrorCode:
      type: string
      enum:
        - 'urn:plmr:cards:connector:NOT_BLANK'
        - 'urn:plmr:cards:connector:NOT_NULL'
    FieldError:
      type: object
      properties:
        code:
          $ref: '#/components/schemas/FieldErrorCode'
        message:
          type: string
        field:
          type: string
    CardResponse:
      $ref: "#/components/schemas/CardDetails"
    CardDetails:
      type: object
      description: |
        Sensitive card details. The PAN and CVV2 are encrypted in the `encryptedPayload` field.
        After decryption, the JSON structure will conform to `DecryptedCardDetails`.
      properties:
        token:
          $ref: "#/components/schemas/CardToken"
        expirationDate:
          type: string
          description: Expiry date of the card
          format: MM/YY
          example: 07/24
        encryptedPayload:
          $ref: "#/components/schemas/EncryptedPayload"
      required:
        - token
        - expirationDate
        - encryptedPayload
    DecryptedCardDetails:
      type: object
      description: Decrypted sensitive card details.
      properties:
        pan:
          type: string
          description: Full, unmasked Primary Account Number (PAN)
          example: 1111113200305162
        securityCode:
          type: string
          description: Card's CVV2 security code
          example: 123
      required:
        - pan
        - securityCode
    CardToken:
      type: string
      description: Internal unique identifier for the card.
      example: 89d94bb5-03a6-43cf-8c29-9ddaecb07f12
    xClientPublicKey:
      type: string
      description: Base64-encoded ECDH client public key using `secp256r1` elliptic curve.
      pattern: '^[A-Za-z0-9+/=]+$'
    UpsertAliasRequest:
      type: object
      description: |
        Update alias request body.
      properties:
        alias:
          $ref: "#/components/schemas/CardAlias"
      required:
        - alias
    CardAlias:
      type: string
      description:
        The card alias.
      example: Online Shopping
    CardPin:
      type: object
      description: |
        The card PIN is encrypted in the `encryptedPayload` field.

        After decryption, the JSON structure will conform to `DecryptedCardPin` structure.
      properties:
        encryptedPayload:
          $ref: "#/components/schemas/EncryptedPayload"
      required:
        - encryptedPayload
    DecryptedCardPin:
      type: object
      description: Decrypted card PIN.
      properties:
        pin:
          type: string
          pattern: '^\d+$'
          description: The PIN belonging to a card. Numeric only.
          example: 1234
      required:
        - pin
    EncryptedPayload:
      type: object
      properties:
        iv:
          type: string
          format: byte
          description: |
            Base64-encoded 12-byte IV (nonce) for AES-256-GCM.
        encryptedData:
          type: string
          format: byte
          description: |
            Base64-encoded ciphertext, including the 16-byte AES-GCM authentication tag appended.
        serverPublicKey:
          type: string
          format: byte
          description: |
            Base64-encoded ephemeral EC public key generated by the server for ECDH key agreement.
            The consumer is to combine this with its private key to derive the shared secret.
        salt:
          type: string
          format: byte
          description: |
            Base64-encoded random salt to be used with the agreed static HKDF function (HKDF-SHA256)
            to derive the AES-256 key from the ECDH shared secret.
      required:
        - iv
        - encryptedData
        - serverPublicKey
        - salt
      description: |
        Encrypted payload using AES-256-GCM. The encryption algorithm and KDF are fixed by convention:
        1. Symmetric encryption: AES-256-GCM
        2. Key derivation: HKDF-SHA256 from ECDH shared secret

    ProvisionGoogleWalletRequest:
      type: object
      description: |
        Provision Google Wallet request body.
      required:
        - deviceId
        - deviceType
        - provisioningAppVersion
        - walletAccountId
      properties:
        deviceId:
          $ref: "#/components/schemas/DeviceId"
        deviceType:
          $ref: "#/components/schemas/DeviceType"
        provisioningAppVersion:
          $ref: "#/components/schemas/ProvisioningAppVersion"
        walletAccountId:
          $ref: "#/components/schemas/WalletAccountId"
        stableHardwareId:
          $ref: "#/components/schemas/StableHardwareId"
    ProvisionAppleWalletRequest:
      type: object
      description: |
        Provision Apple Wallet request body.
      required:
        - certificates
        - deviceType
        - nonce
        - nonceSignature
        - provisioningAppVersion
      properties:
        certificates:
          $ref: "#/components/schemas/Certificates"
        deviceType:
          $ref: "#/components/schemas/DeviceType"
        nonce:
          $ref: "#/components/schemas/Nonce"
        nonceSignature:
          $ref: "#/components/schemas/NonceSignature"
        provisioningAppVersion:
          $ref: "#/components/schemas/ProvisioningAppVersion"
    DeviceId:
      type: string
      minLength: 1
      maxLength: 24
      description: Unique identifier of the user’s Google device. Must be between 1 and 24 characters.
    DeviceType:
      type: string
      enum:
        - MOBILE_PHONE
        - TABLET
        - WATCH
      description: Type of device where the digital wallet token will be provisioned.
    ProvisioningAppVersion:
      type: string
      minLength: 1
      maxLength: 50
      description: Version of the application initiating the provisioning request.
    WalletAccountId:
      type: string
      minLength: 1
      maxLength: 50
      description: The user's Google Wallet account ID, provided by Google during the provisioning process.
    StableHardwareId:
      type: string
      minLength: 1
      maxLength: 50
      description: A stable hardware identifier for the user's device, such as ANDROID_ID for Android devices.
    Certificates:
      type: array
      items:
        type: string
      minItems: 1
      description: |
        An array of Base64-encoded certificates provided by Apple.
        The first element must be the leaf certificate, followed by any subordinate CA certificates, in order.
    Nonce:
      type: string
      description: A one-time-use, Base64-encoded nonce provided by Apple for security purposes.
    NonceSignature:
      type: string
      description: A Base64-encoded signature of the nonce.
    GoogleWalletProvisionResponse:
      type: object
      description: The necessary details to complete the card provisioning.
      required:
        - provisioningData
      properties:
        provisioningData:
          $ref: "#/components/schemas/ProvisioningData"
    AppleWalletProvisionResponse:
      type: object
      description: The necessary details to complete the card provisioning.
      required:
        - activationData
        - encryptedPassData
        - ephemeralPublicKey
      properties:
        activationData:
          type: string
          description: data provided to the payment network as a cryptographic one-time password.
        encryptedPassData:
          type: string
          description: Encrypted data containing the sensitive information needed to add a card to Apple Wallet.
        ephemeralPublicKey:
          type: string
          description: Ephemeral public key used for the provisioning attempt.
    ProvisioningData:
      type: string
      description: |
        A provider-specific cryptographic payload required to complete card provisioning.
        This value is returned by the issuer/processor and must be passed unmodified into the Google wallet SDK on the device.
  requestBodies:
    UpdateAliasRequest:
      description: Update alias
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/UpsertAliasRequest"
    ProvisionGoogleWalletRequest:
      description: Provision Google Wallet Request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ProvisionGoogleWalletRequest"
    ProvisionAppleWalletRequest:
      description: Provision Apple Wallet Request
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ProvisionAppleWalletRequest"