VitrinaAPI

Escribir correos con un asistente

Un asistente conectado prepara el correo; una persona lo revisa y lo envía.

Un borrador de correo es un correo que alguien deja listo sin enviarlo: destinatario, asunto, cuerpo y firma, guardado para que una persona lo revise. Aparece en la bandeja, bajo «Borradores».

Lo puede escribir una persona desde Vitrina, o su propio asistente de IA. Ese asistente se conecta por la MCP de Vitrina, una API key o un token personal. Guardar un borrador nunca lo envía: enviarlo es un paso aparte, y siempre lo hace una persona, o una credencial que actúa como ella.

Leer pide conversations:read. Guardar, editar y descartar piden conversations:write. Enviar pide además messages:send, la misma condición que enviar un mensaje.

El camino recomendado para un asistente conectado por MCP:

  1. Leer GET /copilot/email-voice, y el historial del contacto.
  2. Escribir el correo con esa voz.
  3. Guardarlo con POST /email-drafts.
  4. Dejar que una persona lo revise y lo envíe.

La voz del workspace

Antes de escribir, un asistente puede leer GET /copilot/email-voice. No llama a ningún modelo: junta datos que el workspace ya tiene, para que el borrador suene como el equipo y no como quien lo redacta.

curl "https://api.vitrinadev.com/api/v1/copilot/email-voice?contact_id=22222222-0000-4000-8000-000000000001" \
  -H "Authorization: Bearer $VITRINA_KEY"
{
  "data": {
    "locale": "es",
    "style_guide": "Cercano y claro. Tuteamos. Frases cortas. Nunca prometemos plazos que no controlamos.",
    "agent_instructions": "Eres el asistente del equipo. Respondes con calidez y precisión, tuteas y cierras siempre con un próximo paso concreto.",
    "agent": { "id": "33333333-0000-4000-8000-000000000001", "name": "Asistente" },
    "sample_emails": [
      {
        "subject": "Tu cotización",
        "body_text": "Hola Pedro,\n\nTe adjunto la cotización que conversamos. Cualquier duda me escribes por aquí o al WhatsApp.\n\nUn abrazo,",
        "sent_at": "2026-09-20T13:40:00.000Z"
      }
    ],
    "signature": {
      "id": "44444444-0000-4000-8000-000000000001",
      "name": "Firma principal",
      "text": "Persona del equipo\nEquipo comercial"
    },
    "contact": {
      "id": "22222222-0000-4000-8000-000000000001",
      "name": "María González",
      "email": "[email protected]"
    }
  }
}

Cada campo trae una pieza distinta.

CampoQué trae
localeEl idioma en que escribir
style_guideLa guía de estilo del workspace, si tiene una
agent_instructionsLa persona del agente de IA asignado al correo: su tono, no su mecánica de canal. Recortada a 6.000 caracteres
sample_emailsHasta cinco correos reales que el equipo envió hace poco, sin duplicados, cada uno recortado a 1.200 caracteres
signatureLa firma por defecto de quien llama
contactEl contacto, cuando llega contact_id

Los correos de muestra son del workspace, no de una persona. Casi ninguna respuesta humana pasa por el compositor de Vitrina, así que lo único medible es cómo escribe el equipo.

Guardar un borrador

POST /email-drafts guarda un correo sin enviarlo.

curl -X POST https://api.vitrinadev.com/api/v1/email-drafts \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"contact_id":"22222222-0000-4000-8000-000000000001","subject":"Resumen de lo que conversamos hoy","body_text":"Hola María,\n\nTe dejo por escrito lo que revisamos hoy. Quedamos en coordinar la próxima reunión para el [fecha].\n\nSaludos,"}'
{
  "data": {
    "id": "5d5d5d5d-0000-4000-8000-000000000001",
    "contact": {
      "id": "22222222-0000-4000-8000-000000000001",
      "name": "María González",
      "email": "[email protected]"
    },
    "conversation_id": null,
    "to_address": "[email protected]",
    "cc": [],
    "subject": "Resumen de lo que conversamos hoy",
    "body_html": "<p>Hola María,</p><p>Te dejo por escrito lo que revisamos hoy. Quedamos en coordinar la próxima reunión para el [fecha].</p><p>Saludos,</p>",
    "body_text": "Hola María,\n\nTe dejo por escrito lo que revisamos hoy. Quedamos en coordinar la próxima reunión para el [fecha].\n\nSaludos,",
    "signature_id": null,
    "origin": "mcp",
    "created_by": {
      "id": "11111111-0000-4000-8000-000000000001",
      "name": "Persona del equipo"
    },
    "created_at": "2026-09-24T14:02:11.000Z",
    "updated_at": "2026-09-24T14:05:40.000Z"
  }
}

Todo campo es opcional: un borrador es trabajo en curso. El destinatario es contact_id, que gana si además llega to_address, o una dirección suelta cuando el contacto todavía no existe. body_text es el texto plano, hasta 8.000 caracteres; body_html es la versión enriquecida, opcional. signature_id acepta el id de una firma guardada, "none" para no llevar ninguna, o se omite para la firma por defecto de quien envía. La firma nunca va escrita dentro del cuerpo.

origin lo pone el servidor, nunca el cuerpo enviado. Es mcp para una API key, un token personal o una aplicación conectada, y human para una persona con sesión abierta en Vitrina.

Leer, listar y editar

GET /email-drafts lista los borradores, del más reciente al más antiguo. mine=true, el valor por defecto, trae solo los propios. mine=false trae los del workspace entero. La excepción es un rol con la visibilidad de registros acotada: ese rol ve siempre los suyos, sin importar mine. La lista pagina por cursor: next_cursor se devuelve una vez y se pasa de vuelta como cursor.

{
  "data": [{ "id": "5d5d5d5d-0000-4000-8000-000000000001", "subject": "Resumen de lo que conversamos hoy" }],
  "next_cursor": null,
  "meta": { "pagination": { "nextCursor": null, "limit": 20 } }
}

GET /email-drafts/{id} trae uno solo. PATCH /email-drafts/{id} cambia solo los campos que mandas, con las mismas reglas que POST; conversation_id no se edita ahí. Un borrador que quien llama no puede ver responde 404, igual que uno que ya no existe.

Enviar

POST /email-drafts/{id}/send envía el borrador por el mismo camino que POST /conversations/email. Resuelve el buzón de envío del workspace, abre la conversación bajo control humano, la asigna a quien envía y agrega su firma. Pide conversations:write y, además, messages:send: es el instante en que un mensaje sale de Vitrina.

El borrador desaparece en cuanto el correo sale. Si el envío falla, queda tal cual estaba: un rechazo nunca pierde el texto. Enviarlo dos veces no duplica nada: la segunda solicitud no encuentra el borrador y responde 404.

Sin buzón de envío resuelto, la respuesta es 422 EMAIL_SENDER_UNRESOLVED. Un borrador con conversation_id, es decir una respuesta dentro de un hilo, todavía no se puede enviar por aquí: responde 422, con el campo nombrado en error.field_errors.

Trampa

Enviar pide una persona detrás

Guardar un borrador funciona con una API key del workspace, sin ninguna persona detrás. Enviarlo no: la credencial tiene que resolver a una persona, sea una sesión, un token personal o una aplicación conectada que ella autorizó. Sin eso, la respuesta es 400.

curl -X POST https://api.vitrinadev.com/api/v1/email-drafts/5d5d5d5d-0000-4000-8000-000000000001/send \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
{
  "data": {
    "conversation": {
      "id": "bbbbbbbb-0000-4000-8000-000000000001",
      "display_id": "C-132",
      "channel": "email",
      "status": "open",
      "handler": "human",
      "assignee_user_id": "11111111-0000-4000-8000-000000000001"
    },
    "message": {
      "id": "eeeeeeee-0000-4000-8000-000000000002",
      "content": "Hola María, te dejo por escrito lo que revisamos hoy.",
      "delivery_status": "sent"
    },
    "contact": {
      "id": "22222222-0000-4000-8000-000000000001",
      "created": false,
      "email": "[email protected]"
    }
  }
}

Idempotency-Key funciona igual que en cualquier otro POST publicado: repetir la misma llave devuelve la misma respuesta en vez de enviar el correo dos veces. Está descrito en Errores.

Descartar

DELETE /email-drafts/{id} lo borra. No hay vuelta atrás.

curl -X DELETE https://api.vitrinadev.com/api/v1/email-drafts/5d5d5d5d-0000-4000-8000-000000000001 \
  -H "Authorization: Bearer $VITRINA_KEY"

Responde 204, sin cuerpo.

En esta página