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

# Autenticación

> Obtén una clave de API para tu clínica dental, envíala como token bearer, mantenla en tu servidor, rótala o revócala y entiende cada error de autenticación.

Toda solicitud a `/v1` se autentica con una **clave de API**: una credencial secreta de máquina que pertenece a una sola clínica dental y tiene una lista explícita de [scopes](/docs/es/api-reference/scopes). El endpoint MCP `/mcp` usa ingreso y autorización con OAuth en Console.

## Cómo se envía la clave

Envía la clave en el encabezado `Authorization` con el esquema `Bearer`, en cada solicitud:

```http theme={null}
GET /v1/me HTTP/1.1
Host: api.muveya.com
Authorization: Bearer mvy_test_EXAMPLE...
```

* La clave es una cadena opaca, no un JWT. No intentes decodificarla.
* `Authorization: Bearer` es el único medio aceptado. No existe un encabezado `X-API-Key` ni un parámetro de consulta para la clave.
* El nombre del esquema no distingue mayúsculas de minúsculas, pero la clave debe enviarse exactamente como fue emitida, sin comillas ni saltos de línea.

## Cómo es una clave

```text theme={null}
mvy_test_<24 letras y dígitos>_<4 letras y dígitos>
```

| Parte | Significado |
| - | - |
| `mvy` | El prefijo de muveya. Permite que los escáneres de secretos reconozcan una clave filtrada. |
| `test` | El entorno de la clave. Es el único entorno que se emite en v1 y **no** significa datos de prueba: una clave `mvy_test_` lee los datos reales de la clínica dental a la que pertenece. `GET /v1/me` lo informa como `"environment": "test"`. |
| 24 caracteres | El secreto aleatorio. |
| 4 caracteres | Una suma de verificación. Una clave mal escrita o incompleta se rechaza antes de que muveya la busque. |

muveya guarda solo un hash SHA-256 de la clave y sus primeros 12 caracteres (el **prefijo**, por ejemplo `mvy_test_ab1`). La clave completa se muestra una sola vez, al crearla, y no se puede recuperar después. Si se pierde, pide una nueva.

## Una clave, una clínica dental

Una clave queda asociada a una clínica dental en el servidor al momento de crearla. Eso tiene tres consecuencias:

1. **Ninguna solicitud nombra una clínica dental.** Ninguna ruta, parámetro ni encabezado de `/v1` acepta un id de tenant o de espacio de trabajo. `GET /v1/me` te dice qué clínica dental lee la clave, como `workspaceId`.
2. **Una clave lee toda la clínica dental.** No la limita el acceso a sedes y bodegas que se aplica a los miembros del equipo: dentro de sus scopes, lee todas las sedes y todas las bodegas.
3. **Para integrar dos clínicas dentales, usa dos claves.** Un registro de otra clínica dental responde `404`, exactamente como si no existiera.

Una clave no es una persona. No puede aprobar pedidos, confirmar entregas ni hacer nada que el producto reserva a un miembro del equipo.

## Obtener una clave

<Warning>
  Todavía no hay una pantalla en la consola para crear, listar o revocar claves de API. El equipo de muveya emite las claves a pedido.
</Warning>

<Steps>
  <Step title="Pídela desde una cuenta que gestione integraciones">
    Un miembro de tu clínica dental que tenga el permiso **Gestionar integraciones y claves API** (`integrations.manage`) escribe a [team@muveya.com](mailto:team@muveya.com). Consulta [Roles y permisos](/docs/es/account/roles-and-permissions) para ver cómo se otorga ese permiso.
  </Step>

  <Step title="Indica para qué es la clave">
    Incluye un nombre para la integración (por ejemplo "Sincronización de existencias con el ERP") y los scopes exactos que necesita. Elígelos con las recetas de mínimo privilegio de [Scopes](/docs/es/api-reference/scopes). Una clave debe tener al menos un scope.
  </Step>

  <Step title="Guarda la clave en cuanto la recibas">
    La clave se crea para ese miembro y tu clínica dental, con exactamente los scopes que pediste. Guárdala de inmediato en tu gestor de secretos: se muestra una sola vez.
  </Step>

  <Step title="Compruébala">
    Llama a `GET /v1/me` (más abajo) y confirma que `workspaceId` y `scopes` son los esperados.
  </Step>
</Steps>

Reglas que se aplican a toda clave:

| Regla | Valor |
| - | - |
| Scopes | Al menos uno; consulta [Scopes](/docs/es/api-reference/scopes). No se pueden cambiar los scopes de una clave existente: pide una clave nueva. |
| Claves activas por clínica dental | Como máximo 10 |
| Vencimiento | Las claves emitidas hoy no tienen fecha de vencimiento. Funcionan hasta que se revocan o hasta que se cumple alguna de las condiciones de abajo. |

### Cuando una clave deja de funcionar

Una clave funciona solo mientras el miembro para quien se creó siga activo en la clínica dental:

* Si se **suspende** o se **retira** a ese miembro de la clínica dental, la clave deja de funcionar de inmediato.
* **Reactivar** al miembro no recupera la clave. La consola lo advierte al reactivar a alguien: las claves de API anteriores a la suspensión siguen cerradas. Pide una clave nueva.
* Si la clínica dental está suspendida, se rechazan todas sus claves.

Pide las claves desde un miembro que vaya a seguir a cargo de la integración, como un propietario o un administrador que tenga el permiso **Gestionar integraciones y claves API** (ningún rol lo incluye).

## Tu primera llamada: `GET /v1/me`

`GET /v1/me` no requiere ningún scope. Úsala para comprobar una clave antes que nada.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.muveya.com/v1/me \
    -H "Authorization: Bearer $MUVEYA_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch("https://api.muveya.com/v1/me", {
    headers: { Authorization: `Bearer ${process.env.MUVEYA_API_KEY}` },
  });
  console.log(response.status, await response.json());
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.get(
      "https://api.muveya.com/v1/me",
      headers={"Authorization": f"Bearer {os.environ['MUVEYA_API_KEY']}"},
      timeout=30,
  )
  print(response.status_code, response.json())
  ```
</CodeGroup>

```json 200 OK theme={null}
{
  "workspaceId": "66d0a1f0c0ffee0000000001",
  "environment": "test",
  "scopes": ["clinics:read", "catalog:read", "inventory:read"]
}
```

<ResponseField name="workspaceId" type="string" required>
  La clínica dental a la que pertenece la clave, determinada por el servidor.
</ResponseField>

<ResponseField name="environment" type="string" required>
  El entorno de la clave. Siempre `test` en v1.
</ResponseField>

<ResponseField name="scopes" type="string[]" required>
  Los scopes de la clave, con la forma de dos puntos que usa toda la API (`catalog:read`).
</ResponseField>

La respuesta nunca contiene la clave, su hash ni ningún otro secreto.

## Mantén las claves en tu servidor

* Guarda la clave en un gestor de secretos o en una variable de entorno del servidor, y léela en tiempo de ejecución.
* Nunca la pongas en código de navegador, una app móvil, una hoja de cálculo compartida, un repositorio de código, una URL, una línea de log o un reporte de errores.
* Usa una clave por integración, para poder revocar una sin detener las demás.
* Cuando hables con soporte sobre una clave, identifícala por su nombre o su prefijo (los primeros 12 caracteres), nunca por la clave completa.
* Si una clave pudo haberse filtrado, pide que la revoquen de inmediato y reemplázala.

El constructor de solicitudes de las páginas de **Endpoints** nunca envía solicitudes ni guarda tu clave, pero de todos modos no pegues una clave en ninguna página web.

## Rotar una clave

<Steps>
  <Step title="Consigue una segunda clave">
    Pide una clave nueva con los mismos scopes (consulta [Obtener una clave](#obtener-una-clave)). Ambas claves funcionan al mismo tiempo y ambas cuentan para el límite de 10 claves activas.
  </Step>

  <Step title="Despliégala">
    Reemplaza la clave anterior en todos los sistemas que la usan.
  </Step>

  <Step title="Verifica">
    Llama a `GET /v1/me` desde cada sistema con la clave nueva.
  </Step>

  <Step title="Revoca la clave anterior">
    Pide que revoquen la clave anterior (más abajo).
  </Step>
</Steps>

## Revocar una clave

Un miembro con **Gestionar integraciones y claves API** (`integrations.manage`) escribe a [team@muveya.com](mailto:team@muveya.com) con el nombre o el prefijo de la clave.

* La revocación se aplica desde la siguiente solicitud. No hay caché que esperar.
* No se puede deshacer: una clave revocada no vuelve a funcionar. Pide una clave nueva si todavía necesitas acceso.
* El registro de la clave se conserva para la auditoría de tu clínica dental, igual que los eventos de creación y revocación.

## Respuestas 401 y 403

| Estado | `code` | Cuándo |
| - | - | - |
| `401` | `api_keys.invalid` | Falta el encabezado `Authorization`, usa otro esquema o está vacío; la clave está mal formada o su suma de verificación no coincide; la clave es desconocida o fue revocada; su miembro fue suspendido o retirado; o su clínica dental está suspendida. |
| `403` | `api_keys.scope_missing` | La clave es válida pero le falta un scope que la operación requiere. |

```json 401 Unauthorized (Accept-Language: es) theme={null}
{
  "type": "https://docs.muveya.com/errors/api_keys.invalid",
  "title": "API key inválida",
  "status": 401,
  "detail": "La API key falta, es inválida, fue revocada o expiró. Envía una key válida como token Bearer e inténtalo de nuevo.",
  "instance": "/v1/me",
  "code": "api_keys.invalid",
  "requestId": "8d0e5b8a-2f4c-4e1b-9a7d-0c3b5e6f7a81"
}
```

* El `401` es idéntico para todas las causas, a propósito: no revela si una clave existe. Revisa primero el formato del encabezado y luego consulta con el miembro que pidió la clave si fue revocada o si ese miembro sigue activo.
* El `403` no indica qué scope falta. Llama a `GET /v1/me`, compara los `scopes` con la tabla de [Scopes](/docs/es/api-reference/scopes) y pide una clave con los scopes correctos.
* Las solicitudes rechazadas con `401` o `403` no consumen tu presupuesto de [límites de uso](/docs/es/api-reference/rate-limits) y no traen encabezados de límite.
* Un registro que pertenece a otra clínica dental responde `404`, nunca `403`.

La lista completa de códigos está en [Errores](/docs/es/api-reference/errors).

## MCP usa OAuth

Una clave de API no autentica `https://api.muveya.com/mcp`. Conecta un cliente MCP mediante el [ingreso y la autorización en Console](/docs/es/mcp/connect).


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