openapi: 3.0.3
info:
  title: Codinfy API
  version: 1.1.0
  description: >
    Documentation OpenAPI de l API Codinfy. Cette specification couvre
    l authentification SPA/API, les feature flags, le checkout produits,
    les webhooks de paiement et l API de validation des licences securisees.
servers:
  - url: https://codinfy.com
    description: Production
  - url: http://localhost:8000
    description: Local
paths:
  /api/admin/validate:
    post:
      summary: Valider une licence Codinfy
      description: >
        Recoit une requete signee HMAC-SHA256 et renvoie un payload signe
        par JWT RS256. Une grace period de 72h doit etre appliquee cote SDK.
      operationId: validateLicense
      parameters:
        - in: header
          name: X-Codinfy-Signature
          required: true
          schema:
            type: string
          description: Signature HMAC-SHA256 du corps JSON.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LicenseValidationRequest'
      responses:
        '200':
          description: Validation executee
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LicenseValidationResponse'
        '422':
          description: Signature invalide ou fenetre anti-replay depassee
  /api/auth/register:
    post:
      summary: Creer un compte client
      operationId: registerUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RegisterRequest'
      responses:
        '201':
          description: Compte cree
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
  /api/auth/login:
    post:
      summary: Authentifier un utilisateur
      operationId: loginUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Connexion reussie
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthResponse'
  /api/auth/logout:
    post:
      summary: Fermer la session API courante
      security:
        - sanctumBearer: []
      operationId: logoutUser
      responses:
        '200':
          description: Session fermee
  /api/settings/features:
    get:
      summary: Lire les feature flags du compte courant
      security:
        - sanctumBearer: []
      operationId: getFeatureFlags
      responses:
        '200':
          description: Flags retournes
          content:
            application/json:
              schema:
                type: object
                properties:
                  features:
                    type: object
                    additionalProperties:
                      type: boolean
  /api/payments/checkout:
    post:
      summary: Creer une facture et initialiser un checkout produit
      security:
        - sanctumBearer: []
      operationId: createProductCheckout
      description: >
        Selon la gateway, la plateforme renvoie soit une URL de redirection distante
        (Stripe, CinetPay), soit une URL locale de bridge widget (KKiaPay), soit
        un checkout URL heberge configure cote marchand (TouchPay).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CheckoutRequest'
      responses:
        '201':
          description: Checkout cree
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CheckoutResponse'
        '422':
          description: Validation invalide ou gateway non configuree
  /api/payments/webhooks/{gateway}:
    get:
      summary: Verifier la disponibilite d un endpoint webhook
      operationId: paymentWebhookProbe
      parameters:
        - in: path
          name: gateway
          required: true
          schema:
            type: string
            enum: [stripe, paypal, cinetpay, touchpay, kkiapay]
      responses:
        '200':
          description: Endpoint disponible
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  gateway:
                    type: string
    post:
      summary: Recevoir un webhook de passerelle
      operationId: paymentWebhook
      parameters:
        - in: path
          name: gateway
          required: true
          schema:
            type: string
            enum: [stripe, paypal, cinetpay, touchpay, kkiapay]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
      responses:
        '200':
          description: Webhook traite
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'
        '404':
          description: Facture introuvable
        '422':
          description: Signature invalide
components:
  securitySchemes:
    sanctumBearer:
      type: http
      scheme: bearer
      bearerFormat: Sanctum
  schemas:
    LicenseValidationRequest:
      type: object
      required:
        - purchase_code
        - domain
        - product_id
        - script_version
        - timestamp
      properties:
        purchase_code:
          type: string
          format: uuid
        domain:
          type: string
          example: monsite.com
        product_id:
          type: integer
          example: 42
        script_version:
          type: string
          example: 2.1.0
        timestamp:
          type: integer
          example: 1735000000
        signature:
          type: string
          nullable: true
          description: Signature de secours si l entete n est pas utilise.
    LicenseValidationResponse:
      type: object
      properties:
        status:
          type: string
          enum: [valid, invalid, expired, suspended, domain_limit]
        message:
          type: string
        support_active:
          type: boolean
        support_expires_at:
          type: string
          nullable: true
          format: date-time
        update_available:
          type: boolean
        latest_version:
          type: string
        grace_until:
          type: string
          format: date-time
        jwt_token:
          type: string
    RegisterRequest:
      type: object
      required: [name, username, email, password]
      properties:
        name:
          type: string
        username:
          type: string
        email:
          type: string
          format: email
        password:
          type: string
          format: password
    LoginRequest:
      type: object
      required: [email, password]
      properties:
        email:
          type: string
          format: email
        password:
          type: string
          format: password
    AuthResponse:
      type: object
      properties:
        message:
          type: string
        token:
          type: string
        user:
          type: object
          properties:
            id:
              type: integer
            name:
              type: string
            username:
              type: string
            email:
              type: string
    CheckoutRequest:
      type: object
      required: [product_id, license_type, gateway]
      properties:
        product_id:
          type: integer
          example: 1
        license_type:
          type: string
          enum: [standard, extended, agency]
        gateway:
          type: string
          enum: [stripe, paypal, cinetpay, touchpay, kkiapay]
        currency:
          type: string
          example: XOF
        phone:
          type: string
          description: Numero mobile utilise notamment pour TouchPay direct payin.
          example: "+2250700000000"
        touchpay_channel:
          type: string
          enum: [default, om, mtn, moov, wave]
          description: Canal operateur prefere pour TouchPay.
        coupon_code:
          type: string
          description: Coupon marketing optionnel applique avant paiement.
          example: WELCOME25
        use_wallet_balance:
          type: boolean
          description: Regle immediatement la commande si le wallet couvre la totalite du montant restant.
        success_url:
          type: string
          format: uri
        cancel_url:
          type: string
          format: uri
    CheckoutResponse:
      type: object
      properties:
        invoice:
          $ref: '#/components/schemas/Invoice'
        checkout:
          type: object
          properties:
            status:
              type: string
              example: redirect
            message:
              type: string
              nullable: true
            checkout_url:
              type: string
              nullable: true
              format: uri
              example: https://checkout.cinetpay.com/payment/abc123
            gateway_reference:
              type: string
              nullable: true
            invoice_id:
              type: integer
    WebhookResponse:
      type: object
      properties:
        status:
          type: string
          enum: [paid, recorded, invalid_signature, invoice_not_found]
          example: paid
        normalized:
          type: object
          additionalProperties: true
        invoice:
          $ref: '#/components/schemas/Invoice'
    Invoice:
      type: object
      properties:
        id:
          type: integer
        number:
          type: string
        amount:
          type: number
          format: float
        currency:
          type: string
        gateway:
          type: string
        gateway_ref:
          type: string
          nullable: true
        checkout_url:
          type: string
          nullable: true
          format: uri
        status:
          type: string
          enum: [draft, pending, paid, failed, refunded]
