Pomelo Users & KYC API

Register and manage end users (cardholders) and the identity verification lifecycle - create, retrieve, search, and modify users, plus KYC and KYB sessions for individuals and companies across operating countries.

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