Pomelo Cards API

Create nominated and innominated physical or virtual cards, retrieve and update card status, affinity group and PIN, activate physical cards, manage batches of innominated cards, and update card shipment addresses.

OpenAPI Specification

pomelo-openapi.yml Raw ↑
openapi: 3.0.1
info:
  title: Pomelo API
  description: >-
    REST API for Pomelo (pomelo.la), the Latin American card-issuing and
    embedded-finance platform. Covers user onboarding and identity verification
    (KYC/KYB), card issuing and lifecycle management, card accounts and balances,
    transaction processing and history, transfers and settlements, and the
    real-time authorizer plus event webhooks. Authentication uses the OAuth 2.0
    client-credentials grant; the issued JWT is sent as a Bearer token on every
    request.
  termsOfService: https://www.pomelo.la
  contact:
    name: Pomelo Developers
    url: https://developers.pomelo.la
  version: '1.0'
servers:
  - url: https://api.pomelo.la
    description: Pomelo production API
  - url: https://auth.pomelo.la
    description: Pomelo OAuth 2.0 token issuer
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: OAuth 2.0 client-credentials token issuance.
  - name: Users
    description: Cardholder records and KYC/KYB identity verification.
  - name: Cards
    description: Issuing and lifecycle of physical and virtual cards.
  - name: Card Accounts
    description: Card account balances, activities, and movements.
  - name: Transactions
    description: Processed transactions, summaries, and history.
  - name: Transfers
    description: Money movement and settlements across card accounts.
  - name: Authorizations
    description: Real-time authorizer callback contract (client-implemented).
paths:
  /oauth/token:
    post:
      operationId: createToken
      tags:
        - Authentication
      summary: Obtain an OAuth 2.0 access token.
      description: >-
        Exchange client credentials for a Bearer access token (JWT) using the
        client_credentials grant. Issued against https://auth.pomelo.la. The
        same token is returned until it expires, after which a new one is issued.
      servers:
        - url: https://auth.pomelo.la
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TokenRequest'
      responses:
        '200':
          description: A new or cached access token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /users/v1:
    post:
      operationId: createUser
      tags:
        - Users
      summary: Create a user.
      description: Register a new cardholder. An email uniquely identifies the user on the platform.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserRequest'
      responses:
        '201':
          description: User created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserEnvelope'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      operationId: searchUsers
      tags:
        - Users
      summary: Search users.
      description: Query the user database by parameters such as identification, email, or status.
      parameters:
        - name: identification_value
          in: query
          schema:
            type: string
        - name: email
          in: query
          schema:
            type: string
            format: email
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/UserStatus'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/PageNumber'
      responses:
        '200':
          description: Matching users.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'
        '401':
          $ref: '#/components/responses/Unauthorized'
  /users/v1/{id}:
    parameters:
      - $ref: '#/components/parameters/UserId'
    get:
      operationId: getUser
      tags:
        - Users
      summary: Get a user.
      responses:
        '200':
          description: The requested user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: modifyUser
      tags:
        - Users
      summary: Modify a user.
      description: Update existing personal information for a user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserPatch'
      responses:
        '200':
          description: Updated user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
  /cards/v1:
    post:
      operationId: createCard
      tags:
        - Cards
      summary: Create a card.
      description: >-
        Create a new nominated card, which can be physical or virtual, for a user.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CardRequest'
      responses:
        '201':
          description: Card created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardEnvelope'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
    get:
      operationId: searchCards
      tags:
        - Cards
      summary: Search cards.
      parameters:
        - name: user_id
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/CardStatus'
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/PageNumber'
      responses:
        '200':
          description: Matching cards.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardList'
  /cards/v1/{id}:
    parameters:
      - $ref: '#/components/parameters/CardId'
    get:
      operationId: getCard
      tags:
        - Cards
      summary: Get a card.
      responses:
        '200':
          description: The requested card.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: updateCard
      tags:
        - Cards
      summary: Update a card.
      description: Update the status, affinity group, or PIN of a card.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CardPatch'
      responses:
        '200':
          description: Updated card.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
  /cards/v1/activation:
    post:
      operationId: activateCard
      tags:
        - Cards
      summary: Activate a physical card.
      description: Activate a physical card and optionally set its PIN.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CardActivationRequest'
      responses:
        '200':
          description: Card activated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardEnvelope'
        '400':
          $ref: '#/components/responses/BadRequest'
  /cards/v1/batches:
    post:
      operationId: createCardBatch
      tags:
        - Cards
      summary: Create a batch of innominated cards.
      description: Create a batch of innominated cards (maximum 1,000 cards per batch).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CardBatchRequest'
      responses:
        '201':
          description: Batch created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardBatchEnvelope'
  /cards/v1/{id}/shipment:
    parameters:
      - $ref: '#/components/parameters/CardId'
    patch:
      operationId: updateCardShipment
      tags:
        - Cards
      summary: Update a card shipment address.
      description: >-
        Update the shipping address of a card. The card must be a physical
        nominated card with status CREATED.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ShipmentRequest'
      responses:
        '200':
          description: Shipment updated.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardEnvelope'
  /accounts/v1:
    get:
      operationId: searchCardAccounts
      tags:
        - Card Accounts
      summary: Search card accounts.
      parameters:
        - name: user_id
          in: query
          schema:
            type: string
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/PageNumber'
      responses:
        '200':
          description: Matching card accounts.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardAccountList'
  /accounts/v1/{id}:
    parameters:
      - $ref: '#/components/parameters/AccountId'
    get:
      operationId: getCardAccount
      tags:
        - Card Accounts
      summary: Get a card account.
      responses:
        '200':
          description: The requested card account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CardAccountEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
  /accounts/v1/{id}/movements:
    parameters:
      - $ref: '#/components/parameters/AccountId'
    get:
      operationId: listAccountMovements
      tags:
        - Card Accounts
      summary: List account movements.
      description: List the balance movements and activities for a card account.
      parameters:
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/PageNumber'
      responses:
        '200':
          description: Movements for the account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MovementList'
  /transactions/v1:
    get:
      operationId: searchTransactions
      tags:
        - Transactions
      summary: Search transactions.
      description: Search processed card transactions by user, card, date range, or status.
      parameters:
        - name: user_id
          in: query
          schema:
            type: string
        - name: card_id
          in: query
          schema:
            type: string
        - name: status
          in: query
          schema:
            $ref: '#/components/schemas/TransactionStatus'
        - name: from
          in: query
          schema:
            type: string
            format: date-time
        - name: to
          in: query
          schema:
            type: string
            format: date-time
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/PageNumber'
      responses:
        '200':
          description: Matching transactions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionList'
  /transactions/v1/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
    get:
      operationId: getTransaction
      tags:
        - Transactions
      summary: Get a transaction.
      responses:
        '200':
          description: The requested transaction.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
  /transfers/v1:
    post:
      operationId: createTransfer
      tags:
        - Transfers
      summary: Create a transfer.
      description: Move funds between card accounts to fund or reconcile the program.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransferRequest'
      responses:
        '201':
          description: Transfer created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransferEnvelope'
        '400':
          $ref: '#/components/responses/BadRequest'
    get:
      operationId: searchTransfers
      tags:
        - Transfers
      summary: Search transfers.
      parameters:
        - $ref: '#/components/parameters/PageSize'
        - $ref: '#/components/parameters/PageNumber'
      responses:
        '200':
          description: Matching transfers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransferList'
  /transfers/v1/{id}:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
    get:
      operationId: getTransfer
      tags:
        - Transfers
      summary: Get a transfer.
      responses:
        '200':
          description: The requested transfer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransferEnvelope'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: OAuth 2.0 client-credentials access token issued by /oauth/token.
    oauth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: https://auth.pomelo.la/oauth/token
          scopes: {}
  parameters:
    UserId:
      name: id
      in: path
      required: true
      schema:
        type: string
    CardId:
      name: id
      in: path
      required: true
      schema:
        type: string
    AccountId:
      name: id
      in: path
      required: true
      schema:
        type: string
    PageSize:
      name: page[size]
      in: query
      schema:
        type: integer
        default: 25
    PageNumber:
      name: page[number]
      in: query
      schema:
        type: integer
        default: 0
  responses:
    BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid Bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  schemas:
    TokenRequest:
      type: object
      required:
        - client_id
        - client_secret
        - audience
        - grant_type
      properties:
        client_id:
          type: string
        client_secret:
          type: string
        audience:
          type: string
          example: https://api.pomelo.la
        grant_type:
          type: string
          enum:
            - client_credentials
    TokenResponse:
      type: object
      properties:
        access_token:
          type: string
          description: JWT Bearer token.
        scope:
          type: string
        expires_in:
          type: integer
          example: 86400
        token_type:
          type: string
          example: Bearer
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            details:
              type: array
              items:
                type: object
                properties:
                  code:
                    type: string
                  detail:
                    type: string
    UserStatus:
      type: string
      enum:
        - ACTIVE
        - BLOCKED
        - DISABLED
    Address:
      type: object
      properties:
        street_name:
          type: string
        street_number:
          type: string
        zip_code:
          type: string
        city:
          type: string
        region:
          type: string
        country:
          type: string
          description: ISO 3166-1 alpha-3 country code.
    UserRequest:
      type: object
      required:
        - name
        - surname
        - email
        - operation_country
      properties:
        name:
          type: string
        surname:
          type: string
        identification_type:
          type: string
          example: DNI
        identification_value:
          type: string
        birthdate:
          type: string
          format: date
        gender:
          type: string
          enum:
            - MALE
            - FEMALE
            - OTHER
        email:
          type: string
          format: email
        phone:
          type: string
        legal_address:
          $ref: '#/components/schemas/Address'
        operation_country:
          type: string
          description: ISO 3166-1 alpha-3 operating country (e.g. ARG, BRA, MEX).
    UserPatch:
      type: object
      properties:
        email:
          type: string
          format: email
        phone:
          type: string
        legal_address:
          $ref: '#/components/schemas/Address'
        status:
          $ref: '#/components/schemas/UserStatus'
    User:
      allOf:
        - $ref: '#/components/schemas/UserRequest'
        - type: object
          properties:
            id:
              type: string
            status:
              $ref: '#/components/schemas/UserStatus'
            created_at:
              type: string
              format: date-time
    UserEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/User'
    UserList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        meta:
          $ref: '#/components/schemas/PageMeta'
    CardStatus:
      type: string
      enum:
        - CREATED
        - ACTIVE
        - BLOCKED
        - DISABLED
        - EMERGENCY
    CardRequest:
      type: object
      required:
        - user_id
        - card_type
      properties:
        user_id:
          type: string
        affinity_group_id:
          type: string
        card_type:
          type: string
          enum:
            - PHYSICAL
            - VIRTUAL
        previous_card_id:
          type: string
        address:
          $ref: '#/components/schemas/Address'
    CardPatch:
      type: object
      properties:
        status:
          $ref: '#/components/schemas/CardStatus'
        status_reason:
          type: string
          example: CLIENT_INTERNAL_REASON
        affinity_group_id:
          type: string
        pin:
          type: string
    CardActivationRequest:
      type: object
      required:
        - card_id
      properties:
        card_id:
          type: string
        pin:
          type: string
    CardBatchRequest:
      type: object
      required:
        - affinity_group_id
        - quantity
      properties:
        affinity_group_id:
          type: string
        card_type:
          type: string
          enum:
            - PHYSICAL
            - VIRTUAL
        quantity:
          type: integer
          maximum: 1000
    ShipmentRequest:
      type: object
      properties:
        address:
          $ref: '#/components/schemas/Address'
        external_tracking_id:
          type: string
    Card:
      type: object
      properties:
        id:
          type: string
        user_id:
          type: string
        affinity_group_id:
          type: string
        card_type:
          type: string
          enum:
            - PHYSICAL
            - VIRTUAL
        product_type:
          type: string
          enum:
            - PREPAID
            - DEBIT
            - CREDIT
        status:
          $ref: '#/components/schemas/CardStatus'
        status_detail:
          type: string
        shipment_id:
          type: string
        last_four:
          type: string
        provider:
          type: string
          enum:
            - MASTERCARD
            - VISA
        start_date:
          type: string
          format: date
    CardEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Card'
    CardList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Card'
        meta:
          $ref: '#/components/schemas/PageMeta'
    CardBatchEnvelope:
      type: object
      properties:
        data:
          type: object
          properties:
            batch_id:
              type: string
            quantity:
              type: integer
            status:
              type: string
    CardAccount:
      type: object
      properties:
        id:
          type: string
        user_id:
          type: string
        balance:
          type: number
          format: double
        currency:
          type: string
          description: ISO 4217 currency code.
        status:
          type: string
    CardAccountEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/CardAccount'
    CardAccountList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/CardAccount'
        meta:
          $ref: '#/components/schemas/PageMeta'
    Movement:
      type: object
      properties:
        id:
          type: string
        account_id:
          type: string
        type:
          type: string
          enum:
            - CREDIT
            - DEBIT
        amount:
          type: number
          format: double
        currency:
          type: string
        created_at:
          type: string
          format: date-time
    MovementList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Movement'
        meta:
          $ref: '#/components/schemas/PageMeta'
    TransactionStatus:
      type: string
      enum:
        - APPROVED
        - REJECTED
        - REVERSED
    Amount:
      type: object
      properties:
        total:
          type: number
          format: double
        currency:
          type: string
        details:
          type: array
          items:
            type: object
            properties:
              type:
                type: string
              amount:
                type: number
                format: double
              currency:
                type: string
    Merchant:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        mcc:
          type: string
        country:
          type: string
    Transaction:
      type: object
      properties:
        id:
          type: string
        country_code:
          type: string
        type:
          type: string
          enum:
            - PURCHASE
            - WITHDRAWAL
            - EXTRACASH
            - BALANCE_INQUIRY
            - REFUND
            - PAYMENT
            - REVERSAL
            - ADJUSTMENT
        point_type:
          type: string
          enum:
            - POS
            - ECOMMERCE
            - ATM
            - MOTO
        entry_mode:
          type: string
          enum:
            - MANUAL
            - CHIP
            - CONTACTLESS
            - CREDENTIAL_ON_FILE
            - OTHER
        origin:
          type: string
          enum:
            - DOMESTIC
            - INTERNATIONAL
        source:
          type: string
          enum:
            - DOMESTIC
            - INTERNATIONAL
        local_date_time:
          type: string
          format: date-time
        original_transaction_id:
          type: string
        user_id:
          type: string
        card_id:
          type: string
        amount:
          $ref: '#/components/schemas/Amount'
        merchant:
          $ref: '#/components/schemas/Merchant'
        status:
          $ref: '#/components/schemas/TransactionStatus'
        status_detail:
          type: string
    TransactionEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Transaction'
    TransactionList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Transaction'
        meta:
          $ref: '#/components/schemas/PageMeta'
    TransferRequest:
      type: object
      required:
        - origin_account_id
        - destination_account_id
        - amount
      properties:
        origin_account_id:
          type: string
        destination_account_id:
          type: string
        amount:
          type: number
          format: double
        currency:
          type: string
        description:
          type: string
    Transfer:
      type: object
      properties:
        id:
          type: string
        origin_account_id:
          type: string
        destination_account_id:
          type: string
        amount:
          type: number
          format: double
        currency:
          type: string
        status:
          type: string
          enum:
            - PENDING
            - COMPLETED
            - REJECTED
        created_at:
          type: string
          format: date-time
    TransferEnvelope:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/Transfer'
    TransferList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/Transfer'
        meta:
          $ref: '#/components/schemas/PageMeta'
    PageMeta:
      type: object
      properties:
        pagination:
          type: object
          properties:
            page_size:
              type: integer
            page_number:
              type: integer
            total_pages:
              type: integer
            total_elements:
              type: integer