VitrinaAPI

Borradores de correo

Un correo que alguien, o su asistente de IA, deja listo para que una persona lo revise y lo envíe: listar, crear, editar, descartar y enviar.

Beta
Puede cambiar en cualquier momento, con una entrada en el changelog y aviso a quienes la llamaron recientemente — ver versionado.

Descarga la proyección completa de la API pública: openapi.json.

Escribir correos con un asistente explica este recurso en prosa, con ejemplos ejecutables.

MétodoRutaQué hace
GET/email-draftsList email drafts
POST/email-draftsSave an email draft for a person to review and send
DELETE/email-drafts/{id}Discard an email draft
GET/email-drafts/{id}Get an email draft
PATCH/email-drafts/{id}Edit an email draft
POST/email-drafts/{id}/sendSend an email draft

GET /email-drafts

List email drafts

Drafts newest first (by last edit). mine=true (the default) lists the caller's own; mine=false every draft of the workspace — except for a member whose role narrows record visibility, who always sees only their own. Keyset-paginated: pass next_cursor back as cursor.

ParámetroEnTipoObligatorioRestricciones
minequeryanynopor defecto true
limitqueryintegerno≥ 1, ≤ 100, por defecto 20
cursorquerystringnomáx. 512
curl https://api.vitrinadev.com/api/v1/email-drafts \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "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"
    }
  ],
  "next_cursor": null,
  "meta": {
    "pagination": {
      "nextCursor": null,
      "limit": 20
    }
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /email-drafts

Save an email draft for a person to review and send

Prepares a new email WITHOUT sending it. This is how an assistant connected through the Vitrina MCP hands an email to a person: read GET /copilot/email-voice first so it sounds like the workspace, save it here, and a person reviews and sends it from Vitrina. origin is set by the server from the credential — mcp for an API key, personal token or connected app, human for a signed-in member.

Every field is optional — a draft is work in progress, so an empty subject, an empty body or no recipient yet are all storable; what is SENDABLE is decided by POST /email-drafts/\{id\}/send. Recipient: contact_id (wins when both are set) or to_address. body_text is the plain text (≤8,000 characters) and what is sent as the text part; body_html the rich version, optional. signature_id: one of the sender's saved signatures, "none" for no signature, or null for the sender's default at send time. Never put a signature in the body.

Cuerpo

CampoTipoObligatorioRestricciones
contact_idstring | null—
to_addressstring | null—email, máx. 255
ccstring[]—
subjectstring—máx. 255
body_htmlstring—máx. 200000
body_textstring—máx. 8000
signature_idany—
from_account_idstring | null—
conversation_idstring | null—
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,"
  }'

Ejemplo de respuesta (201)

{
  "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"
  }
}

Responde: 201 · 400 · 401 · 403 · 404 · 409 · 429

DELETE /email-drafts/{id}

Discard an email draft

The draft is gone; there is no undo.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí
curl -X DELETE https://api.vitrinadev.com/api/v1/email-drafts/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Responde: 204 · 400 · 401 · 403 · 404 · 409 · 429

GET /email-drafts/{id}

Get an email draft

One draft. A draft a narrowed member may not see answers 404, the same as one that does not exist.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí
curl https://api.vitrinadev.com/api/v1/email-drafts/<id> \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "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"
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

PATCH /email-drafts/{id}

Edit an email draft

Partial update: only the fields sent change.

Every field is optional — a draft is work in progress, so an empty subject, an empty body or no recipient yet are all storable; what is SENDABLE is decided by POST /email-drafts/\{id\}/send. Recipient: contact_id (wins when both are set) or to_address. body_text is the plain text (≤8,000 characters) and what is sent as the text part; body_html the rich version, optional. signature_id: one of the sender's saved signatures, "none" for no signature, or null for the sender's default at send time. Never put a signature in the body.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí

Cuerpo

CampoTipoObligatorioRestricciones
contact_idstring | null—
to_addressstring | null—email, máx. 255
ccstring[]—
subjectstring—máx. 255
body_htmlstring—máx. 200000
body_textstring—máx. 8000
signature_idany—
from_account_idstring | null—
curl -X PATCH https://api.vitrinadev.com/api/v1/email-drafts/<id> \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "subject": "Resumen de nuestra reunión",
    "cc": [
      "[email protected]"
    ]
  }'

Ejemplo de respuesta (200)

{
  "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"
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /email-drafts/{id}/send

Send an email draft

Sends the draft exactly as POST /conversations/email would — same sending mailbox resolution (refused 422 EMAIL_SENDER_UNRESOLVED when none resolves), a new thread under HUMAN control assigned to the sender, the sender's signature appended, no unsubscribe footer — and returns the same response. The draft is deleted once the email has left; a send that fails leaves it in place. A draft that is not sendable yet (no recipient, empty subject or body) is refused 422 with error.field_errors naming the draft fields. Needs messages:send: this is the moment a message leaves Vitrina, and it must be a signed-in person or a token acting as one.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí
curl -X POST https://api.vitrinadev.com/api/v1/email-drafts/<id>/send \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (201)

{
  "data": {
    "conversation": {
      "id": "bbbbbbbb-0000-4000-8000-000000000001",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "display_seq": 132,
      "display_id": "C-132",
      "channel": "email",
      "external_id": "web:visitor-9f2c1a",
      "messaging_account_id": "16161616-0000-4000-8000-000000000001",
      "brand": null,
      "contact_id": "22222222-0000-4000-8000-000000000001",
      "ticket_id": "dddddddd-0000-4000-8000-000000000001",
      "status": "open",
      "handler": "human",
      "assignee_user_id": "11111111-0000-4000-8000-000000000001",
      "assignee_assigned_at": "2026-09-22T11:06:54.183Z",
      "snoozed_until": null,
      "resolved_at": null,
      "resolved_by": null,
      "closed_at": null,
      "close_deferred_until": null,
      "transfer_immediately": false,
      "filtered_at": null,
      "filtered_reason": null,
      "summary": null,
      "summarized_at": null,
      "history_summary": null,
      "history_summary_upto_message_id": null,
      "first_billable_at": null,
      "billable": null,
      "billing_reason": null,
      "assigned_unanswered_alerted_at": null,
      "assigned_unanswered_realerted_at": null,
      "bot_gate_override_at": null,
      "bot_gate_override_by": null,
      "source": null,
      "awaiting_human_since": null,
      "awaiting_payment_since": null,
      "awaiting_payment_escalated_at": null,
      "awaiting_obligation_id": null,
      "ad_referral": null,
      "ad_join": null,
      "ad_welcome": null,
      "metadata": null,
      "ai_control_source": "legacy",
      "ai_control_changed_at": null,
      "ai_control_revision": 0,
      "ai_control_window_start": null,
      "ai_control_window_end": null,
      "ai_control_account_revision": null,
      "ai_blocked_until": null,
      "ai_keep_with_human": false,
      "external_id_provisional": false,
      "originated_at": null,
      "originated_by_kind": null,
      "originated_by_ai_agent_id": null,
      "originated_by_user_id": null,
      "originated_outbound_action_id": null,
      "last_message_date": "2026-09-22T11:08:10.882Z",
      "created_at": "2026-09-22T11:06:33.744Z",
      "updated_at": "2026-09-22T11:08:10.882Z"
    },
    "message": {
      "id": "eeeeeeee-0000-4000-8000-000000000002",
      "tenant_id": "a1a1a1a1-0000-4000-8000-000000000001",
      "conversation_id": "bbbbbbbb-0000-4000-8000-000000000001",
      "content": "Hola Rodrigo, te confirmo la visita del jueves a las 10:00.",
      "type": "text",
      "sender_role": "assistant",
      "sender_type": "api_key",
      "sender_id": "c1c1c1c1-0000-4000-8000-000000000001",
      "correlation_id": null,
      "external_message_id": null,
      "media_urls": null,
      "media_sensitivity": null,
      "media_processing_state": null,
      "media_expires_at": null,
      "derived_context_expires_at": null,
      "metadata": null,
      "tool_calls": null,
      "tool_call_id": null,
      "delivery_status": "sent",
      "delivery_error": null,
      "delivery_attempt": 1,
      "next_attempt_at": null,
      "delivered_at": null,
      "read_at": null,
      "author": {
        "kind": "api_key",
        "id": "c1c1c1c1-0000-4000-8000-000000000001",
        "name": "CRM propio"
      },
      "created_at": "2026-09-22T11:08:10.882Z",
      "updated_at": "2026-09-22T11:08:10.882Z"
    },
    "contact": {
      "id": "22222222-0000-4000-8000-000000000001",
      "created": false,
      "email": "[email protected]"
    }
  }
}

Responde: 201 · 400 · 401 · 403 · 404 · 409 · 422 · 429

En esta página