openapi: 3.0.3
info:
  title: 'Kurrency API'
  description: 'High-performance, edge-cached Fiat and Crypto currency conversion API.'
  version: 1.0.0
  contact:
    email: support@kurrency.dev
servers:
  -
    url: 'https://api.kurrency.dev'
    description: 'Production API Server'
tags:
  -
    name: 'Rates & Conversion'
    description: 'Core currency conversion and rate aggregation endpoints'
  -
    name: 'Account Management'
    description: 'Public endpoints for user registration and dashboard authentication'
  -
    name: 'API Keys'
    description: 'Endpoints for managing your developer API keys'
paths:
  /v1/rates:
    get:
      tags:
        - 'Rates & Conversion'
      summary: 'Get all current exchange rates'
      description: 'Retrieves the latest aggregated exchange rates for both fiat and cryptocurrencies relative to USD. Served from our global cache network closest to each client for sub-10ms latency.'
      security:
        -
          ApiKeyAuth: {  }
        -
          ApiKeyQuery: {  }
      responses:
        200:
          description: 'Successfully retrieved rates'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RatesResponse'
        401:
          description: 'Missing or invalid API Key'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        503:
          description: 'Rates currently unavailable or caching'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/convert:
    get:
      tags:
        - 'Rates & Conversion'
      summary: 'Convert between two currencies'
      description: 'Calculates the exchange rate between any two supported fiat or cryptocurrencies.'
      security:
        -
          ApiKeyAuth: {  }
        -
          ApiKeyQuery: {  }
      parameters:
        -
          name: from
          in: query
          required: true
          description: 'The source currency code (e.g., USD, EUR, BTC)'
          schema:
            type: string
        -
          name: to
          in: query
          required: true
          description: 'The target currency code (e.g., GBP, JPY, ETH)'
          schema:
            type: string
        -
          name: from_type
          in: query
          required: false
          description: 'Force the source currency type if there is a conflict (e.g., fiat or crypto)'
          schema:
            type: string
            enum:
              - fiat
              - crypto
        -
          name: to_type
          in: query
          required: false
          description: 'Force the target currency type if there is a conflict (e.g., fiat or crypto)'
          schema:
            type: string
            enum:
              - fiat
              - crypto
      responses:
        200:
          description: 'Successful conversion rate calculation'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConvertResponse'
        400:
          description: 'Missing required parameters'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        401:
          description: 'Missing or invalid API Key'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        404:
          description: 'Currency not found'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        503:
          description: 'Rates currently unavailable or caching'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /auth/register:
    post:
      tags:
        - 'Account Management'
      summary: 'Register a new developer account'
      description: 'Creates a new developer account. The account must be verified by an administrator before API keys can be generated.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
                  minLength: 6
      responses:
        200:
          description: 'Registration successful'
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  message: { type: string }
        400:
          description: 'Invalid input or email already exists'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /auth/login:
    post:
      tags:
        - 'Account Management'
      summary: 'Login to developer dashboard'
      description: 'Authenticates a developer and returns a JWT token for dashboard access.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
              properties:
                email:
                  type: string
                  format: email
                password:
                  type: string
      responses:
        200:
          description: 'Login successful'
          content:
            application/json:
              schema:
                type: object
                properties:
                  token: { type: string, description: 'JWT Bearer Token' }
                  user: { type: object, properties: { id: { type: string }, email: { type: string }, is_verified: { type: integer, enum: [0, 1] } } }
        401:
          description: 'Invalid credentials'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /user/keys:
    get:
      tags:
        - 'API Keys'
      summary: 'List your API keys'
      description: 'Retrieves all API keys associated with your account.'
      security:
        -
          JwtAuth: {  }
      responses:
        200:
          description: 'Successfully retrieved API keys'
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ApiKey'
        401:
          description: 'Unauthorized (Missing or invalid JWT)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      tags:
        - 'API Keys'
      summary: 'Create a new API key'
      description: 'Generates a new secure API key. Your account must be verified by an admin to use this endpoint.'
      security:
        -
          JwtAuth: {  }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              properties:
                name:
                  type: string
                  description: 'A descriptive name for the API key'
      responses:
        200:
          description: 'Successfully generated API key'
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  api_key: { type: string }
        401:
          description: 'Unauthorized (Missing or invalid JWT)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        403:
          description: 'Account not verified by admin'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  '/user/keys/{id}':
    delete:
      tags:
        - 'API Keys'
      summary: 'Revoke an API key'
      description: 'Permanently revokes and deletes the specified API key.'
      security:
        -
          JwtAuth: {  }
      parameters:
        -
          name: id
          in: path
          required: true
          description: 'The unique ID of the API key to revoke'
          schema:
            type: string
      responses:
        200:
          description: 'Successfully revoked API key'
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
        401:
          description: 'Unauthorized (Missing or invalid JWT)'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    JwtAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: 'Provide your JWT session token obtained from `/auth/login`'
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: 'Provide your API Key as a Bearer token (e.g., `Authorization: Bearer sk_...`)'
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: 'Alternatively, provide your API Key via the `api_key` query string parameter.'
  schemas:
    RatesResponse:
      type: object
      properties:
        updatedAt:
          type: integer
          description: 'Unix timestamp (in milliseconds) of the last rate aggregation'
        fiat:
          type: object
          additionalProperties:
            type: number
          description: "Dictionary mapping Fiat currency codes (e.g., 'EUR') to their value in USD"
        crypto:
          type: object
          additionalProperties:
            type: number
          description: "Dictionary mapping Crypto ticker symbols (e.g., 'BTC') to their value in USD"
    ConvertResponse:
      type: object
      properties:
        from:
          type: string
        to:
          type: string
        rate:
          type: number
          description: 'The exact calculated exchange rate multiplier from the source to target currency'
        updatedAt:
          type: integer
          description: 'Unix timestamp (in milliseconds) of the rates used for this calculation'
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
        details:
          type: string
    ApiKey:
      type: object
      properties:
        id:
          type: string
        api_key:
          type: string
        name:
          type: string
        is_active:
          type: integer
          enum:
            - 0
            - 1
        created_at:
          type: string
          format: date-time
