{"openapi":"3.1.0","info":{"title":"ruiv.ai — API REST","version":"1.0.0","description":"API REST de ruiv.ai para envío y consulta de correo transaccional. Autenticación por **API key** (`Authorization: Bearer rv_...`). Todo el producto también es accionable por **MCP** (OAuth 2.1) para tu agente.","contact":{"name":"ruiv.ai","url":"https://ruiv.ai"}},"servers":[{"url":"https://ruiv.ai","description":"Producción"}],"tags":[{"name":"Emails","description":"Envío y consulta de correos"},{"name":"Sistema","description":"Salud del servicio"}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"API key del workspace (`Authorization: Bearer rv_live_...`). Crea y gestiona keys en Settings → API Keys. Scopes: `full`, `sending`, `read`."}},"schemas":{"SendEmailRequest":{"type":"object","required":["to","subject"],"description":"Debes incluir `html` o `text`.","properties":{"from":{"type":"string","example":"Acme <hola@acme.com>","description":"Remitente. Opcional: si se omite, se usa el remitente por defecto del workspace. El dominio debe estar verificado en el workspace."},"to":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"},"maxItems":50}],"example":"cliente@ejemplo.com"},"subject":{"type":"string","maxLength":998,"example":"Bienvenido a Acme"},"html":{"type":"string","example":"<h1>Hola {{first_name}}</h1><p>Gracias por registrarte.</p>"},"text":{"type":"string","example":"Hola, gracias por registrarte."},"cc":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"}}]},"bcc":{"oneOf":[{"type":"string","format":"email"},{"type":"array","items":{"type":"string","format":"email"}}]},"reply_to":{"type":"string","format":"email"},"tags":{"type":"object","additionalProperties":{"type":"string","maxLength":256},"maxProperties":10,"example":{"campaign":"welcome","env":"prod"}}}},"SendEmailResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid","example":"a1b2c3d4-..."}}},"Email":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"to":{"type":"array","items":{"type":"string","format":"email"}},"from":{"type":"string"},"subject":{"type":"string"},"html":{"type":"string","nullable":true},"text":{"type":"string","nullable":true},"status":{"type":"string","enum":["queued","sent","delivered","bounced","complained","failed"]},"cc":{"type":"array","items":{"type":"string"},"nullable":true},"bcc":{"type":"array","items":{"type":"string"},"nullable":true},"reply_to":{"type":"string","nullable":true},"tags":{"type":"object","additionalProperties":{"type":"string"},"nullable":true},"provider_message_id":{"type":"string","nullable":true},"last_event_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string","example":"validation_error","description":"validation_error · invalid_json · from_not_verified · from_domain_restricted · rate_limit_exceeded · send_limit_exceeded · not_found · delivery_error · internal_error"}}},"request_id":{"type":"string"}}}}},"security":[{"ApiKey":[]}],"paths":{"/api/emails":{"post":{"tags":["Emails"],"summary":"Enviar un correo","description":"Envía un correo transaccional. Requiere scope `full` o `sending`. Soporta el header `Idempotency-Key` para reintentos seguros. Rate-limited por API key.","operationId":"sendEmail","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string"},"description":"Clave de idempotencia para evitar envíos duplicados."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequest"}}}},"responses":{"200":{"description":"Correo aceptado para envío.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailResponse"}}}},"401":{"description":"API key faltante o inválida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Dominio del remitente no verificado o restringido por la key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Cuerpo inválido (validación).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit o límite de plan excedido (incluye `Retry-After`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Fallo del proveedor de entrega.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/emails/{id}":{"get":{"tags":["Emails"],"summary":"Consultar un correo","description":"Devuelve el estado y metadatos de un correo. Requiere scope `full` o `read`.","operationId":"getEmail","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"ID del correo (devuelto por POST /api/emails)."}],"responses":{"200":{"description":"Correo encontrado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Email"}}}},"401":{"description":"API key faltante o inválida.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Scope insuficiente.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Correo no encontrado.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/health":{"get":{"tags":["Sistema"],"summary":"Salud del servicio","description":"Endpoint público de salud. No requiere autenticación.","operationId":"health","security":[],"responses":{"200":{"description":"Operativo.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"vinden-mail"},"revision":{"type":"string"},"time":{"type":"string","format":"date-time"}}}}}}}}}}}