> ## Documentation Index
> Fetch the complete documentation index at: https://developer.fexpayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Register a new merchant

> Creates a merchant account and provisions a Keycloak `client_credentials` client. Returns `client_id` and `client_secret` — **the secret is shown only once**. POS terminals authenticate using these credentials via Keycloak's token endpoint. **Requires platform admin JWT** (realm role `admin`).



## OpenAPI

````yaml /swagger.json post /merchant/api/v1/register
openapi: 3.0.3
info:
  title: Merchant API
  description: >-
    API for merchants to create and manage payment intents, POS counters, and
    transaction history in the FEX Payment Platform. Authentication uses
    Keycloak JWT (human merchants via password flow, POS terminals via client
    credentials).
  version: 1.0.0
  contact:
    name: FEX Payments Platform
servers:
  - url: http://api-sandbox.fexpayments.com
    description: Merchant API sandbox server
security: []
tags:
  - name: Payment Intents
    description: Create and manage payment intents
  - name: Counters
    description: >-
      POS terminal (counter) management — each counter has its own Keycloak
      client credentials and webhook endpoint
  - name: Admin
    description: Back-office endpoints restricted to platform admin role (`admin`)
  - name: Public
    description: Public endpoints accessible without authentication (for QR code payments)
  - name: Onboarding
    description: Merchant registration — requires platform admin JWT (realm role `admin`)
paths:
  /merchant/api/v1/register:
    post:
      tags:
        - Onboarding
      summary: Register a new merchant
      description: >-
        Creates a merchant account and provisions a Keycloak
        `client_credentials` client. Returns `client_id` and `client_secret` —
        **the secret is shown only once**. POS terminals authenticate using
        these credentials via Keycloak's token endpoint. **Requires platform
        admin JWT** (realm role `admin`).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterMerchantRequest'
            example:
              email: shop@example.com
              business_name: My Shop
      responses:
        '201':
          description: Merchant registered — store client_secret securely
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RegisterResult'
              example:
                success: true
                merchant_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                client_id: merchant-a1b2c3d4-e5f6-7890-abcd-ef1234567890
                client_secret: s3cr3t-shown-once
                note: Store client_secret securely — it will not be shown again.
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - BearerAuth: []
components:
  schemas:
    RegisterMerchantRequest:
      type: object
      required:
        - email
        - business_name
      properties:
        email:
          type: string
          format: email
          example: shop@example.com
        business_name:
          type: string
          example: My Shop
    RegisterResult:
      type: object
      properties:
        success:
          type: boolean
          example: true
        merchant_id:
          type: string
          format: uuid
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        client_id:
          type: string
          example: merchant-a1b2c3d4-e5f6-7890-abcd-ef1234567890
        client_secret:
          type: string
          example: s3cr3t-shown-once
          description: Shown only once — store securely.
        note:
          type: string
          example: Store client_secret securely — it will not be shown again.
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          example: Invalid request body
      required:
        - success
        - error
  responses:
    BadRequest:
      description: Bad request — invalid input
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error: Amount must be greater than 0
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error: Failed to create payment intent
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Keycloak JWT. Roles: `admin` (platform admin — can register merchants,
        act on behalf of any merchant), `merchant` (dashboard user — scoped to
        their own `merchant_id` via user attribute mapper), POS terminals use
        client credentials flow with `merchant_id` injected via protocol mapper.

````