# Integración de MontosVE API (guía para agentes de IA)

> Sigue estos pasos para integrar la API de tasas de cambio de MontosVE en este proyecto. Aplica solo los pasos del stack que detectes. No inventes endpoints: usa los documentados aquí y en la referencia completa.

- **Base URL:** `https://api.montosve.com/v1`
- **Autenticación:** header `X-API-Key: <tu-api-key>`
- **Referencia completa (leer si falta contexto):** https://montosve.com/llms-full.txt
- **Especificación OpenAPI:** https://montosve.com/docs/api.json
- **Obtener una API key:** https://montosve.com/register

## Antes de escribir código

1. Detecta el stack del proyecto (por ejemplo `package.json` → JS/TS, o `composer.json` → PHP/Laravel).
2. Busca dónde se guardan las credenciales (`.env`, `config/`, `process.env`). Nunca hardcodees la API key ni la commitees.
3. Agrega la variable `MONTOSVE_API_KEY` con el valor que el usuario te indique. Si no la tiene, pídesela antes de continuar.
4. Crea un único cliente HTTP reutilizable para la API; no disperses llamadas sueltas por el código.

## JavaScript / TypeScript

Crea un cliente mínimo y reusable (por ejemplo `src/lib/montosve.ts`):

```ts
const BASE_URL = 'https://api.montosve.com/v1';
const API_KEY = process.env.MONTOSVE_API_KEY;

type Rate = {
  market: string;
  currency_pair: string;
  rate: number;
  trade_type?: string;
  updated_at: string;
};

async function request<T>(path: string, params: Record<string, string | number> = {}): Promise<T> {
  const url = new URL(BASE_URL + path);
  Object.entries(params).forEach(([key, value]) => url.searchParams.set(key, String(value)));

  const response = await fetch(url, {
    headers: { 'X-API-Key': API_KEY ?? '' },
  });

  if (response.status === 401) {
    throw new Error('MontosVE: API key ausente o invállida.');
  }
  if (response.status === 429) {
    throw new Error('MontosVE: rate limit o cuota mensual excedida.');
  }
  if (! response.ok) {
    throw new Error(`MontosVE: error ${response.status}`);
  }

  return response.json() as Promise<T>;
}

export function getRates(tradeType: 'buy' | 'sell' = 'buy') {
  return request<{ data: Rate[]; meta: { timestamp: string; sources_count: number } }>('/fx/rates', {
    trade_type: tradeType,
  });
}

export function convert(amount: number, from = 'USD', to = 'VES', market = 'bcv') {
  return request<{ amount: number; converted_amount: number; rate: number; market: string }>('/fx/convert', {
    amount,
    from,
    to,
    market,
  });
}
```

Uso:

```ts
const { data } = await getRates('buy');
const conversion = await convert(100, 'USD', 'VES', 'bcv');
```

## PHP / Laravel

Agrega la base URL y la key a `config/services.php`:

```php
'montosve' => [
    'base_url' => env('MONTOSVE_BASE_URL', 'https://api.montosve.com/v1'),
    'api_key' => env('MONTOSVE_API_KEY'),
],
```

Y define `MONTOSVE_API_KEY` en `.env`. Crea el cliente (por ejemplo `app/Services/MontosveClient.php`):

```php
namespace App\Services;

use Illuminate\Http\Client\PendingRequest;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\Response;

final class MontosveClient
{
    private function client(): PendingRequest
    {
        return Http::baseUrl(config('services.montosve.base_url'))
            ->withHeaders(['X-API-Key' => config('services.montosve.api_key')])
            ->acceptJson()
            ->timeout(10);
    }

    /** @return array<string, mixed> */
    public function getRates(string $tradeType = 'buy'): array
    {
        return $this->client()
            ->get('/fx/rates', ['trade_type' => $tradeType])
            ->throw()
            ->json();
    }

    /** @return array<string, mixed> */
    public function convert(float $amount, string $from = 'USD', string $to = 'VES', string $market = 'bcv'): array
    {
        return $this->client()
            ->get('/fx/convert', compact('amount', 'from', 'to', 'market'))
            ->throw()
            ->json();
    }
}
```

Para manejo explícito de errores, reemplaza `->throw()` por `->failed()` y revisa `$response->status()` (`401`, `403`, `422`, `429`).

## Semántica que debes respetar

- Mercados: `bcv` (oficial), `binance_p2p` y `bybit_p2p` (USDT/VES P2P).
- `trade_type`: `buy` (compra) o `sell` (venta); por defecto `buy`.
- Cada respuesta incluye `timestamp`/`updated_at` y puede incluir `stale`; reenvíalos a la UI para trazabilidad.
- Errores esperados: `401` key inválida, `403` feature o cuota, `404` mercado inexistente, `422` parámetros, `429` rate limit, `500`/`503` fuente no disponible.

## Verificación

1. Confirma que el cliente hace una llamada real (sin mocks) y devuelve `data`.
2. Si el proyecto tiene tests, agrega uno que valide el parseo de la respuesta (usa `Http::fake()` en Laravel o un mock de `fetch` en JS).
3. No imprimas la API key en logs.

## Al terminar

- Resume qué archivos creaste/modificaste y qué variable de entorno debe configurar el usuario.
- Si falta un caso de uso (spread, historial, health), consulta https://montosve.com/llms-full.txt antes de improvisar.
