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