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

# Quickstart

> Make your first server-side request and use exchange rates in your application.

<span id="paso-1" />

## Create an API key

Create an account, verify your email and generate a key under **API Keys** in the [dashboard](https://app.cotizave.com). It is shown once. Store `COTIZAVE_API_KEY` in your private server configuration without extra quotes or whitespace. Exclude secret files from Git.

Keep the key out of browser JavaScript and applications distributed to users. These examples do not contain a valid credential.

<span id="paso-2" />

## Set up your server client

Save the first example as `cotizave.mjs` (Node.js 20 or later), or the second as `cotizave.py` (Python 3.10 or later with `requests` installed). Other pages import these files. Both check HTTP status, set timeouts and reject redirects. Neither retries automatically.

<CodeGroup>
  ```javascript cotizave.mjs theme={null}
  export async function cotizave(path, { method = 'GET', body } = {}) {
    const key = process.env.COTIZAVE_API_KEY?.trim();
    if (!key) throw new Error('Set COTIZAVE_API_KEY on the server');
    const url = new URL(path, 'https://api.cotizave.com');
    if (url.origin !== 'https://api.cotizave.com' || !url.pathname.startsWith('/v1/')) {
      throw new Error('Invalid Cotizave API path');
    }
    const response = await fetch(url, {
      method,
      headers: {
        'X-API-Key': key,
        Accept: 'application/json',
        ...(body === undefined ? {} : { 'Content-Type': 'application/json' })
      },
      ...(body === undefined ? {} : { body: JSON.stringify(body) }),
      redirect: 'error',
      signal: AbortSignal.timeout(10_000)
    });
    let data;
    try { data = await response.json(); } catch { data = null; }
    if (!response.ok || data === null) {
      const error = new Error(`Cotizave HTTP ${response.status}`);
      error.status = response.status;
      error.code = data?.code ?? 'invalid_response';
      error.field = data?.field;
      error.details = data?.details;
      error.scope = response.headers.get('X-RateLimit-Scope');
      error.retryAfter = response.headers.get('Retry-After');
      error.reset = response.headers.get('X-RateLimit-Reset');
      throw error;
    }
    return data;
  }
  ```

  ```python cotizave.py theme={null}
  import os
  import requests

  class CotizaveError(Exception):
      def __init__(self, response, data):
          super().__init__(f"Cotizave HTTP {response.status_code}")
          payload = data if isinstance(data, dict) else {}
          self.status = response.status_code
          self.code = payload.get("code", "invalid_response")
          self.field = payload.get("field")
          self.details = payload.get("details")
          self.scope = response.headers.get("X-RateLimit-Scope")
          self.retry_after = response.headers.get("Retry-After")
          self.reset = response.headers.get("X-RateLimit-Reset")

  def cotizave(path, *, method="GET", body=None):
      key = os.environ.get("COTIZAVE_API_KEY", "").strip()
      if not key:
          raise ValueError("Set COTIZAVE_API_KEY on the server")
      if not path.startswith("/v1/"):
          raise ValueError("Invalid Cotizave API path")
      with requests.request(
          method, "https://api.cotizave.com" + path,
          headers={"X-API-Key": key, "Accept": "application/json"},
          json=body, timeout=(3, 10), allow_redirects=False
      ) as response:
          try:
              data = response.json()
          except ValueError:
              data = None
          if not 200 <= response.status_code < 300 or data is None:
              raise CotizaveError(response, data)
          return data
  ```
</CodeGroup>

The `requests` timeout limits connection and read inactivity; it is not a total execution deadline. If your application has an overall deadline, enforce it in the calling layer too. For curl, configure the key without whitespace and do not add `--location`.

Run these examples on your server. JavaScript and Python use the clients in the [quickstart](/en/api/quickstart#paso-2); configure `COTIZAVE_API_KEY` there.

<CodeGroup>
  ```bash curl theme={null}
  curl --fail-with-body --max-time 10 "https://api.cotizave.com/v1/fx/rates/reference" \
    -H "X-API-Key: $COTIZAVE_API_KEY"
  ```

  ```javascript Node.js theme={null}
  import { cotizave } from './cotizave.mjs';

  const data = await cotizave('/v1/fx/rates/reference');
  console.log(data);
  ```

  ```python Python theme={null}
  from cotizave import cotizave

  data = cotizave('/v1/fx/rates/reference')
  print(data)
  ```
</CodeGroup>

<span id="paso-3" />

## Read the response

Illustrative response: figures and dates are not current quotes.

```json theme={null}
{
  "market": "reference",
  "type": "reference",
  "mid": 475.0083,
  "updated_at": "2026-10-19T04:00:00Z",
  "effective_date": "2026-10-19"
}
```

`mid` is VES per USD for `reference`. `eur_reference` is VES per EUR. `updated_at` is the update timestamp and `effective_date` is the BCV value date. They are not interchangeable. A value date can remain applicable over several non-business days.

<span id="paso-4" />

## Connect your application

Your backend calls Cotizave and exposes its own endpoint with the fields your UI needs. The browser calls that endpoint without receiving the API key. For repeated use, share a cache across users and decide how long older data is acceptable. Read [quotas and limits](/en/api/rate-limits) before scheduling refreshes.

```javascript theme={null}
// Server-side example; use the client saved above.
import { cotizave } from './cotizave.mjs';
const snapshot = await cotizave('/v1/fx/rates');
const rate = snapshot.rates.find(item => item.market === 'reference');
if (!rate) throw new Error('BCV rate unavailable');
console.log({ rate: rate.mid, effective_date: rate.effective_date });
```

<span id="proximos" />

## Next steps

Read about [authentication](/en/api/authentication), [conversion](/en/api/endpoints/convert), [history](/en/api/endpoints/history) and [webhooks](/en/guides/webhooks).

<span id="tips" />

## Errors and freshness

Do not retry parameter, credential or plan errors. For `429`, distinguish `burst` from `monthly` and honour the headers. Bound GET retries for transient failures; do not automatically repeat a POST with an uncertain outcome. A successful HTTP response does not guarantee every source is recent.

<span id="problemas" />

## Troubleshooting

The [common errors](/en/api/errors) for authentication, quota and availability also apply. API error responses are JSON; branch on `code`, not on the text of `message`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.