VitrinaAPI

Método de pago

El proveedor de pago del workspace y el estado de su mandato — lo que habilita activar complementos por autoservicio — y la escritura que lo conecta con Fintoc o Mercado Pago.

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.

MétodoRutaQué hace
GET/billing/conversationsBilled conversations of one billing month (paginated)
POST/billing/conversations/{conversationId}/disputeReport («Reportar») a billed conversation
GET/billing/conversations/exportExport the billed conversations of one month (CSV)
GET/billing/historyBilling history: one row per billed month («Historial»)
GET/billing/history/exportExport the billing history (CSV)
POST/billing/invoices/{id}/transfer-claim«Ya pagué por transferencia»: pause automatic charging of a cobro
POST/billing/invoices/{id}/transfer-claim/comprobanteAttach or replace the comprobante of a pending «Ya pagué»
GET/billing/invoices/{id}/transfer-claim/comprobantesThe comprobantes attached to a cobro’s «Ya pagué» claims
GET/billing/payment-methodCurrent payment provider + mandate status for the tenant
POST/billing/payment-method/setupConnect a payment provider (Fintoc hosted PAC redirect, or MercadoPago tokenized card)
GET/billing/payment-methodsThe workspace’s payment methods, or how to pay by transfer
POST/billing/payment-methodsStart adding a payment method (PAC or card)
DELETE/billing/payment-methods/{id}Remove a payment method
POST/billing/payment-methods/{id}/defaultMake an active payment method the default
GET/billing/profileTenant billing/tax identity (the DTE receptor)
PUT/billing/profileUpdate the tenant billing/tax identity
GET/billing/usage/exportExport the daily usage of one month (CSV)
GET/billing/usage/liveUsage of a month: daily meters, amount, month-end estimate, history

GET /billing/conversations

Billed conversations of one billing month (paginated)

Every conversation that counted toward the month: its billable moment, channel, the contact masked to the last 4 phone digits, its review state and, for a month an invoice billed, whether a later review exempted it (credited on a later invoice). A billed month reads the set the invoice froze at the close (period.source = invoice), so summary.count equals the invoice’s conversations; any other month reads the live meter. Never returns message text. Keyset-paginated (next_cursor). Requires billing:read.

ParámetroEnTipoObligatorioRestricciones
periodquerystringnopatrón ^\d{4}-(0[1-9]|1[0-2])$
cursorquerystringnomáx. 200
limitqueryintegerno≥ 1, ≤ 500
curl https://api.vitrinadev.com/api/v1/billing/conversations \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "period": {
      "month": "2026-10",
      "start": "2026-10-01T03:00:00.000Z",
      "end": "2026-11-01T03:00:00.000Z",
      "closed": true,
      "source": "invoice"
    },
    "invoice": {
      "id": "b1b1b1b1-0000-4000-8000-000000000001",
      "number": "INV-00000000-202610",
      "status": "issued",
      "issued_at": "2026-11-01T09:00:00.000Z"
    },
    "summary": {
      "count": 2,
      "unreviewed": 1,
      "exempted_after_close": 1,
      "conversations_uf": 0.024
    },
    "items": [
      {
        "conversation_id": "c1c1c1c1-0000-4000-8000-000000000001",
        "display_id": "C-1001",
        "first_billable_at": "2026-10-03T14:12:09.000Z",
        "channel": "whatsapp",
        "contact_last4": "4321",
        "review_state": "billable",
        "counted_because": "customer_wrote_agent_replied",
        "exempted_after_close": null
      },
      {
        "conversation_id": "c1c1c1c1-0000-4000-8000-000000000002",
        "display_id": "C-1002",
        "first_billable_at": "2026-10-29T22:40:51.000Z",
        "channel": "instagram",
        "contact_last4": null,
        "review_state": "unreviewed",
        "counted_because": "customer_wrote_agent_replied",
        "exempted_after_close": {
          "reason": "El cliente solo saludó y no volvió a responder.",
          "exempted_at": "2026-11-02T10:00:00.000Z",
          "credited_on_invoice": null
        }
      }
    ],
    "next_cursor": null
  }
}

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

POST /billing/conversations/{conversationId}/dispute

Report («Reportar») a billed conversation

The workspace disputes ONE conversation its cobro billed, with a reason code (not_real_customer, duplicate, answered_by_human, other) and an optional comment. One open dispute per conversation (409 otherwise). A dispute never blocks or delays the automatic charge: an approved one is discounted on the next invoice (or refunded). The founder is notified. The conversation list (GET /billing/conversations) carries each conversation’s latest dispute and its status. Requires billing:read.

ParámetroEnTipoObligatorioRestricciones
conversationIdpathuuidsí

Cuerpo

CampoTipoObligatorioRestricciones
reason_codenot_real_customer \duplicate \answered_by_human \
commentstring—máx. 500
curl -X POST https://api.vitrinadev.com/api/v1/billing/conversations/<id>/dispute \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason_code": "duplicate",
    "comment": "Es la misma persona de ayer."
  }'

Ejemplo de respuesta (201)

{
  "data": {
    "id": "d1d1d1d1-0000-4000-8000-000000000001",
    "conversation_id": "c1c1c1c1-0000-4000-8000-000000000001",
    "status": "open",
    "reason_code": "duplicate",
    "reason_label": "Conversación duplicada",
    "comment": "Es la misma persona de ayer.",
    "resolution": null,
    "resolution_note": null,
    "created_at": "2026-10-05T14:00:00.000Z",
    "resolved_at": null
  }
}

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

GET /billing/conversations/export

Export the billed conversations of one month (CSV)

The same rows as GET /billing/conversations, the whole month, streamed as UTF-8 CSV (with BOM). Requires billing:read.

ParámetroEnTipoObligatorioRestricciones
periodquerystringnopatrón ^\d{4}-(0[1-9]|1[0-2])$
curl https://api.vitrinadev.com/api/v1/billing/conversations/export \
  -H "Authorization: Bearer $VITRINA_KEY"

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

GET /billing/history

Billing history: one row per billed month («Historial»)

Every cobro the workspace was issued (drafts and voided ones excluded) and every month invoiced outside the system, together, newest month first. Each row carries the cobro number, neto, IVA and total in whole CLP, the client-facing status, the paid date, the month’s conversation count (the same count GET /billing/conversations?period= reports) and its documents: the cobro PDF, and — once the cobro is paid and the factura electrónica emitted — the factura folio with its PDF and XML. A cobro issued by hand for a month billed outside the monthly close is an ordinary cobro row on the month it was issued for; another month it also billed reads kind: manual with that cobro in billed_in and its status and documents, but no amount (the amount is on the cobro’s own row). A month invoiced by hand with no cobro on record reads kind: manual, status: billed_outside and no amount. filter = all | paid | open; 12 rows per page, keyset-paginated (next_cursor). Requires billing:read (owners and admins).

ParámetroEnTipoObligatorioRestricciones
filterqueryall \paid \open
cursorquerystringnomáx. 300
limitqueryintegerno≥ 1, ≤ 100
curl https://api.vitrinadev.com/api/v1/billing/history \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "filter": "all",
    "items": [
      {
        "row_key": "b1b1b1b1-0000-4000-8000-000000000001",
        "kind": "invoice",
        "period": "2026-10",
        "invoice_id": "b1b1b1b1-0000-4000-8000-000000000001",
        "number": "VT-2026-0007",
        "status": "paid",
        "clp_net": 150000,
        "iva_amount": 28500,
        "clp_total": 178500,
        "issued_at": "2026-11-01T12:00:00.000Z",
        "due_date": "2026-11-05",
        "paid_at": "2026-11-03T15:20:00.000Z",
        "paid_date": "2026-11-03",
        "conversation_count": 412,
        "payable": false,
        "billed_in": null,
        "concept": null,
        "documents": {
          "cobro_pdf_path": "/api/v1/billing/invoices/b1b1b1b1-0000-4000-8000-000000000001/pdf",
          "factura_state": "issued",
          "factura": {
            "folio": "1042",
            "pdf_path": "/api/v1/billing/invoices/b1b1b1b1-0000-4000-8000-000000000001/factura/pdf",
            "xml_path": "/api/v1/billing/invoices/b1b1b1b1-0000-4000-8000-000000000001/factura/xml"
          }
        }
      },
      {
        "row_key": "manual:2026-09",
        "kind": "manual",
        "period": "2026-09",
        "invoice_id": null,
        "number": null,
        "status": "billed_outside",
        "clp_net": null,
        "iva_amount": null,
        "clp_total": null,
        "issued_at": null,
        "due_date": null,
        "paid_at": null,
        "paid_date": null,
        "conversation_count": 388,
        "payable": false,
        "billed_in": null,
        "concept": null,
        "documents": {
          "cobro_pdf_path": null,
          "factura_state": "none",
          "factura": null
        }
      }
    ],
    "next_cursor": null
  }
}

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

GET /billing/history/export

Export the billing history (CSV)

Every row of GET /billing/history for the filter, one line per month, as UTF-8 CSV with BOM: period, kind, cobro number, neto, IVA, total, status, paid date, conversations, factura folio and the cobro PDF, factura PDF and factura XML links. Requires billing:read.

ParámetroEnTipoObligatorioRestricciones
filterqueryall \paid \open
curl https://api.vitrinadev.com/api/v1/billing/history/export \
  -H "Authorization: Bearer $VITRINA_KEY"

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

POST /billing/invoices/{id}/transfer-claim

«Ya pagué por transferencia»: pause automatic charging of a cobro

The owner says this cobro was already paid by bank transfer (for example without its reference, which the reconciliation cannot match). While the claim is pending nothing charges the cobro automatically — not the scheduled charge, not a retry — and it does not advance in collections; the Vitrina team verifies the transfer and either records the payment or resumes the charge with a fresh heads-up. Idempotent (created: false when already pending). 409 when the cobro is no longer open (paid, voided, or a charge is in flight). Requires billing:write.

Optional comprobante (#7094): send the proof of the transfer with the claim as a multipart file part (or the JSON file variant below). A PDF, JPG or PNG of at most 10 MB, type read from the bytes; a refused file (400 comprobante_empty, 413 comprobante_too_large, 415 comprobante_type) refuses the whole request and nothing is claimed. It is a claim, not proof: it changes nothing on the cobro. comprobante in the answer is the file THIS call attached (null without one). If the claim was made but the file could not be stored, the answer is still 200 with comprobante: null and comprobante_error {reason comprobante_not_stored, retryable true}: retry only the file. Add or replace it later with POST …/transfer-claim/comprobante.

Or a JSON body (application/json) — what an MCP connector sends through call_operation, which cannot build multipart: \{ filename, content, content_encoding?, content_type? \} plus the operation's own form fields. content is UTF-8 text by default, or base64 when content_encoding is "base64" (images, PDF, audio, video). The same byte cap applies to the decoded bytes (413 above it); invalid base64 is a 400; the content type defaults from the filename extension.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí

Cuerpo

CampoTipoObligatorioRestricciones
filenamestringsímín. 1, máx. 255
contentstringsímín. 1, máx. 35000000
content_encodingutf8 \base64—
content_typestring—máx. 200
curl -X POST https://api.vitrinadev.com/api/v1/billing/invoices/<id>/transfer-claim \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": "(binary part)"
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "created": true,
    "claimedAt": "2026-10-14T13:20:00.000Z",
    "number": "VT-2026-0002"
  }
}

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

POST /billing/invoices/{id}/transfer-claim/comprobante

Attach or replace the comprobante of a pending «Ya pagué»

Adds the proof of the transfer to the cobro’s pending «Ya pagué por transferencia» claim, or replaces the one already there (the old file is deleted). A PDF, JPG or PNG of at most 10 MB; the type is read from the bytes, never from the request (415 comprobante_type; 413 comprobante_too_large; 400 comprobante_empty / comprobante_missing). It is a claim, not proof: it changes nothing on the cobro, its collection or its automatic charge; the Vitrina team checks the transfer. 409 no_pending_claim when the cobro has no pending claim (claim first, or attach the file to the claim itself); 409 comprobante_frozen when the claim’s file already went with a recorded payment; 404 for a cobro of another workspace. Requires billing:write (owners).

Or a JSON body (application/json) — what an MCP connector sends through call_operation, which cannot build multipart: \{ filename, content, content_encoding?, content_type? \} plus the operation's own form fields. content is UTF-8 text by default, or base64 when content_encoding is "base64" (images, PDF, audio, video). The same byte cap applies to the decoded bytes (413 above it); invalid base64 is a 400; the content type defaults from the filename extension.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí

Cuerpo

CampoTipoObligatorioRestricciones
filenamestringsímín. 1, máx. 255
contentstringsímín. 1, máx. 35000000
content_encodingutf8 \base64—
content_typestring—máx. 200
curl -X POST https://api.vitrinadev.com/api/v1/billing/invoices/<id>/transfer-claim/comprobante \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file": "(binary part)"
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "comprobante": {
      "id": "5b0e6c1a-9a7d-4c3e-8f21-0c4d2e1f7a90",
      "invoice_id": "9a1bd325-3ab8-47e8-afe1-7b87c550b139",
      "claimed_at": "2026-11-05T13:31:00.000Z",
      "filename": "comprobante_transferencia.pdf",
      "mime": "application/pdf",
      "size_bytes": 48211,
      "uploaded_at": "2026-11-05T13:31:02.000Z",
      "state": "pending",
      "rejected_at": null,
      "received_payment_id": null
    },
    "replaced": false
  }
}

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

GET /billing/invoices/{id}/transfer-claim/comprobantes

The comprobantes attached to a cobro’s «Ya pagué» claims

Every file the workspace attached to a «Ya pagué» on this cobro, the newest claim first, with what became of each claim (state). A rejected claim’s file stays here as history. Descriptors only; download one with GET …/comprobantes/\{comprobanteId\}. 404 for a cobro of another workspace. Requires billing:read (owners and admins).

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí
curl https://api.vitrinadev.com/api/v1/billing/invoices/<id>/transfer-claim/comprobantes \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": [
    {
      "id": "5b0e6c1a-9a7d-4c3e-8f21-0c4d2e1f7a90",
      "invoice_id": "9a1bd325-3ab8-47e8-afe1-7b87c550b139",
      "claimed_at": "2026-11-05T13:31:00.000Z",
      "filename": "comprobante_transferencia.pdf",
      "mime": "application/pdf",
      "size_bytes": 48211,
      "uploaded_at": "2026-11-05T13:31:02.000Z",
      "state": "pending",
      "rejected_at": null,
      "received_payment_id": null
    }
  ]
}

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

GET /billing/payment-method

Current payment provider + mandate status for the tenant

The workspace's chosen payment provider (fintoc for a PAC bank mandate, mercadopago for a tokenized card) and the status of its newest mandate: active means add-ons can be activated self-serve (POST /entitlements/\{feature\}/activate), pending means the Fintoc hosted setup was started but not finished. All three fields are null before any enrollment. Carries no payment instrument data — no card number, bank account or provider token is ever returned.

curl https://api.vitrinadev.com/api/v1/billing/payment-method \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "provider": "fintoc",
    "status": "active",
    "mandateId": "f1f1f1f1-0000-4000-8000-000000000001"
  }
}

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

POST /billing/payment-method/setup

Connect a payment provider (Fintoc hosted PAC redirect, or MercadoPago tokenized card)

Makes provider the workspace's single payment account and creates its mandate. Fintoc answers status: "pending" with a setupUrl to send the owner to (the hosted PAC setup, which returns to returnUrl); MercadoPago takes a cardToken minted client-side by MercadoPago's own SDK — never a raw card number — and answers status: "active" with setupUrl: null. email (the payer) is required by both providers; rut (optional) goes on the Fintoc customer. Requires billing:write, which only the workspace owner holds.

Cuerpo

CampoTipoObligatorioRestricciones
providerfintoc \mercadopago \transbank_oneclick
returnUrlstring—uri, máx. 2048
cardTokenstring—mín. 1, máx. 256
emailstring—email, máx. 320
namestring—mín. 1, máx. 256
rutstring—mín. 1, máx. 32
cancelUrlstring—uri, máx. 2048
bankstring—mín. 1, máx. 64
curl -X POST https://api.vitrinadev.com/api/v1/billing/payment-method/setup \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "fintoc",
    "returnUrl": "https://app.vitrinadev.com/w/agencia/settings/billing/invoices?fintoc=return",
    "email": "[email protected]",
    "rut": "76.123.456-7"
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "provider": "fintoc",
    "status": "pending",
    "mandateId": "f1f1f1f1-0000-4000-8000-000000000002",
    "setupUrl": "https://pay.fintoc.com/subscriptions/setup/example"
  }
}

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

GET /billing/payment-methods

The workspace’s payment methods, or how to pay by transfer

Every payment method with its rail (fintoc_pac, fintoc_card, oneclick, mercadopago) named by the rail that holds it, its display fields (PAC: bank + last digits + mandate status activo / pendiente_firma / rechazado; card: brand + last 4 + expiry + credit/debit when reported) and which one is the default the cobros are charged to. With no active method pays_by is transfer and transfer carries Vitrina’s bank account and the reference of the cobro to pay. Never returns a card number, a full account number or a provider token. Requires billing:read.

curl https://api.vitrinadev.com/api/v1/billing/payment-methods \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "methods": [
      {
        "id": "f1f1f1f1-0000-4000-8000-000000000003",
        "rail": "fintoc_pac",
        "rail_name": "Débito automático (PAC)",
        "status": "activo",
        "is_default": true,
        "bank": {
          "name": "Banco de Chile",
          "last4": "9212"
        },
        "card": null,
        "removable": false,
        "created_at": "2026-10-02T14:05:00.000Z"
      },
      {
        "id": "f1f1f1f1-0000-4000-8000-000000000004",
        "rail": "oneclick",
        "rail_name": "Tarjeta (Webpay Oneclick)",
        "status": "activo",
        "is_default": false,
        "bank": null,
        "card": {
          "brand": "Visa",
          "last4": "6623",
          "exp_month": null,
          "exp_year": null
        },
        "removable": true,
        "created_at": "2026-09-15T10:00:00.000Z"
      }
    ],
    "default_method_id": "f1f1f1f1-0000-4000-8000-000000000003",
    "pays_by": "method",
    "pending_cobro": {
      "invoice_id": "f1f1f1f1-0000-4000-8000-000000000010",
      "number": "INV-2026-10-0007",
      "reference": "VT-7K2QM9",
      "due_at": "2026-11-08T03:00:00.000Z"
    },
    "transfer": null,
    "available_rails": [
      {
        "rail": "fintoc_pac",
        "rail_name": "Débito automático (PAC)",
        "recommended": true
      },
      {
        "rail": "oneclick",
        "rail_name": "Tarjeta (Webpay Oneclick)",
        "recommended": false
      }
    ],
    "pac_banks": [
      {
        "code": "cl_banco_de_chile",
        "name": "Banco de Chile"
      },
      {
        "code": "cl_banco_estado",
        "name": "BancoEstado"
      }
    ]
  }
}

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

POST /billing/payment-methods

Start adding a payment method (PAC or card)

Starts the rail’s own enrolment and answers where to send the browser: fintoc_pac → a GET to Fintoc’s hosted PAC checkout; fintoc_card → a GET to Fintoc’s hosted card checkout (credit or debit; offered in available_rails only while Fintoc has the card product enabled for Vitrina, else refused with fintoc_card_unavailable); oneclick → a form POST of TBK_TOKEN to Transbank’s inscription page; mercadopago takes a card token minted by Mercado Pago’s SDK and is active at once (redirect: null). The provider sends the browser back to return_url, which must be on the app’s own origin. The current default stays in place until the new method is active; then it becomes the default and any outstanding cobro is retried on it right away. Requires billing:write.

curl -X POST https://api.vitrinadev.com/api/v1/billing/payment-methods \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rail": "oneclick",
    "return_url": "https://app.vitrinadev.com/w/agencia/settings/billing/invoices?medio=tarjeta"
  }'

Ejemplo de respuesta (201)

{
  "data": {
    "method_id": "f1f1f1f1-0000-4000-8000-000000000005",
    "rail": "oneclick",
    "status": "pendiente",
    "redirect": {
      "url": "https://webpay3g.transbank.cl/webpayserver/bp_multicode_inscription.cgi",
      "method": "POST",
      "fields": {
        "TBK_TOKEN": "01ab23cd45ef67ab89cd01ef23ab45cd67ef89ab01cd23ef45ab67cd89ef01ab"
      }
    }
  }
}

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

DELETE /billing/payment-methods/{id}

Remove a payment method

Stops charging the method at once (a Oneclick card is also deleted at Transbank). 409 default_method_has_pending_cobro for the default while a cobro is pending — add or choose another method first — and 409 while a charge is in progress on the method. Removing the default with nothing pending hands the default to the next active method, if any. Answers the updated payment methods. Requires billing:write.

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

Ejemplo de respuesta (200)

{
  "data": {
    "methods": [
      {
        "id": "f1f1f1f1-0000-4000-8000-000000000003",
        "rail": "fintoc_pac",
        "rail_name": "Débito automático (PAC)",
        "status": "activo",
        "is_default": true,
        "bank": {
          "name": "Banco de Chile",
          "last4": "9212"
        },
        "card": null,
        "removable": false,
        "created_at": "2026-10-02T14:05:00.000Z"
      },
      {
        "id": "f1f1f1f1-0000-4000-8000-000000000004",
        "rail": "oneclick",
        "rail_name": "Tarjeta (Webpay Oneclick)",
        "status": "activo",
        "is_default": false,
        "bank": null,
        "card": {
          "brand": "Visa",
          "last4": "6623",
          "exp_month": null,
          "exp_year": null
        },
        "removable": true,
        "created_at": "2026-09-15T10:00:00.000Z"
      }
    ],
    "default_method_id": "f1f1f1f1-0000-4000-8000-000000000003",
    "pays_by": "method",
    "pending_cobro": {
      "invoice_id": "f1f1f1f1-0000-4000-8000-000000000010",
      "number": "INV-2026-10-0007",
      "reference": "VT-7K2QM9",
      "due_at": "2026-11-08T03:00:00.000Z"
    },
    "transfer": null,
    "available_rails": [
      {
        "rail": "fintoc_pac",
        "rail_name": "Débito automático (PAC)",
        "recommended": true
      },
      {
        "rail": "oneclick",
        "rail_name": "Tarjeta (Webpay Oneclick)",
        "recommended": false
      }
    ],
    "pac_banks": [
      {
        "code": "cl_banco_de_chile",
        "name": "Banco de Chile"
      },
      {
        "code": "cl_banco_estado",
        "name": "BancoEstado"
      }
    ]
  }
}

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

POST /billing/payment-methods/{id}/default

Make an active payment method the default

The cobros are charged to this method from now on, and any outstanding cobro (issued or past due, nothing in flight) is retried on it right away — once per cobro and method. Choosing the current default again changes nothing. 409 for a method that is not active. Answers the updated payment methods. Requires billing:write.

ParámetroEnTipoObligatorioRestricciones
idpathuuidsí
curl -X POST https://api.vitrinadev.com/api/v1/billing/payment-methods/<id>/default \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "methods": [
      {
        "id": "f1f1f1f1-0000-4000-8000-000000000003",
        "rail": "fintoc_pac",
        "rail_name": "Débito automático (PAC)",
        "status": "activo",
        "is_default": true,
        "bank": {
          "name": "Banco de Chile",
          "last4": "9212"
        },
        "card": null,
        "removable": false,
        "created_at": "2026-10-02T14:05:00.000Z"
      },
      {
        "id": "f1f1f1f1-0000-4000-8000-000000000004",
        "rail": "oneclick",
        "rail_name": "Tarjeta (Webpay Oneclick)",
        "status": "activo",
        "is_default": false,
        "bank": null,
        "card": {
          "brand": "Visa",
          "last4": "6623",
          "exp_month": null,
          "exp_year": null
        },
        "removable": true,
        "created_at": "2026-09-15T10:00:00.000Z"
      }
    ],
    "default_method_id": "f1f1f1f1-0000-4000-8000-000000000003",
    "pays_by": "method",
    "pending_cobro": {
      "invoice_id": "f1f1f1f1-0000-4000-8000-000000000010",
      "number": "INV-2026-10-0007",
      "reference": "VT-7K2QM9",
      "due_at": "2026-11-08T03:00:00.000Z"
    },
    "transfer": null,
    "available_rails": [
      {
        "rail": "fintoc_pac",
        "rail_name": "Débito automático (PAC)",
        "recommended": true
      },
      {
        "rail": "oneclick",
        "rail_name": "Tarjeta (Webpay Oneclick)",
        "recommended": false
      }
    ],
    "pac_banks": [
      {
        "code": "cl_banco_de_chile",
        "name": "Banco de Chile"
      },
      {
        "code": "cl_banco_estado",
        "name": "BancoEstado"
      }
    ]
  }
}

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

GET /billing/profile

Tenant billing/tax identity (the DTE receptor)

«Datos de facturación»: who Vitrina invoices for this workspace — RUT, razón social, giro, address and comuna — and billing_emails, every address that receives the cobros, the payment reminders and collections emails, and the factura electrónica (first one = billing_email). complete says whether a factura can be issued with this data and missing lists what is still needed. Requires billing:read.

curl https://api.vitrinadev.com/api/v1/billing/profile \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "legal_name": "Automotora Ejemplo SpA",
    "rut": "76086428-5",
    "giro": "Compraventa de vehículos",
    "address": {
      "line1": "Av. Apoquindo 1234",
      "line2": "Of. 501",
      "city": "Las Condes",
      "region": "Metropolitana de Santiago",
      "postal_code": null,
      "country": "CL",
      "comuna_code": "13114"
    },
    "billing_email": "[email protected]",
    "cc_emails": [
      "[email protected]"
    ],
    "billing_emails": [
      "[email protected]",
      "[email protected]"
    ],
    "complete": true,
    "missing": [],
    "source": "in_app",
    "confirmed_at": "2026-10-07T15:00:00.000Z"
  }
}

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

PUT /billing/profile

Update the tenant billing/tax identity

Partial update of «Datos de facturación»: only the fields sent change. The RUT check digit, the SII lengths (razón social 100, giro 40, address 70) and the comuna are validated. billing_emails replaces the whole recipient list (1–10 addresses, in order; repeats dropped). Changes apply to the cobros and facturas issued from now on — an issued factura is never changed — and facturas waiting for this data are re-checked at once. Requires billing:write.

Cuerpo

CampoTipoObligatorioRestricciones
legal_namestring | null—máx. 256
rutstring | null—máx. 32
girostring | null—máx. 256
addressobject | null—
billing_emailstring | null—email, máx. 320
cc_emailsarray | null—
billing_emailsarray | null—
curl -X PUT https://api.vitrinadev.com/api/v1/billing/profile \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "billing_emails": [
      "[email protected]",
      "[email protected]"
    ]
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "legal_name": "Automotora Ejemplo SpA",
    "rut": "76086428-5",
    "giro": "Compraventa de vehículos",
    "address": {
      "line1": "Av. Apoquindo 1234",
      "line2": "Of. 501",
      "city": "Las Condes",
      "region": "Metropolitana de Santiago",
      "postal_code": null,
      "country": "CL",
      "comuna_code": "13114"
    },
    "billing_email": "[email protected]",
    "cc_emails": [
      "[email protected]"
    ],
    "billing_emails": [
      "[email protected]",
      "[email protected]"
    ],
    "complete": true,
    "missing": [],
    "source": "in_app",
    "confirmed_at": "2026-10-07T15:00:00.000Z"
  }
}

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

GET /billing/usage/export

Export the daily usage of one month (CSV)

The daily block of GET /billing/usage/live for the same period as UTF-8 CSV (with BOM): one row per Santiago day (fecha), one column per metric (conversaciones, minutos_voz, minutos_desvio, correos_marketing, and uso_&lt;feature&gt; per add-on), then a total row equal to the totals the page shows. Counts only, never conversation content; the billed conversations themselves are GET /billing/conversations/export. Requires billing:read.

ParámetroEnTipoObligatorioRestricciones
periodquerystringnopatrón ^\d{4}-(0[1-9]|1[0-2])$
curl https://api.vitrinadev.com/api/v1/billing/usage/export \
  -H "Authorization: Bearer $VITRINA_KEY"

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

GET /billing/usage/live

Usage of a month: daily meters, amount, month-end estimate, history

Without period, the month in progress priced by the same meters and rate card the monthly close uses (what the next close would bill), in UF and in CLP at today's UF; a month-end projection that is an estimate (linear by elapsed Santiago days); every add-on and its inclusion reason; and history: past months as the ISSUED invoice amounts (never recomputed), months invoiced outside the system labelled external. mode says how to read it: fixed-contract workspaces see their fixed price with usage at $0, not-billed workspaces see usage without prices (show_prices false), and a workspace whose billing has not started yet gets billing_starts_on.

With period=YYYY-MM (a past Santiago month, #3760) the same shape describes that month: its meters over the whole month, and for the amount only what was billed — the issued cobro's frozen lines and totals with its frozen UF (amount_source: invoice), a month invoiced by hand (external) or nothing (none, usage only); never today's prices. A cobro that froze its billed set counts conversations from it (conversations_source: invoice), so the count equals the cobro's. projection is null for a past month. A future month is a 400.

daily carries every metric per Santiago day (conversations, voice and forwarded minutes, billed agent-eval runs, email-campaign sends, per-unit add-on usage); each series' total is the sum of its days. GET /billing/usage/export is the same as CSV.

next_charge (current month only; null for a past month or when prices are hidden) is the cobro the close will issue: its cut-off, issue and charge dates, whether it is charged automatically or paid by transfer, and its lines in pesos (so far and at month end) exactly as the hosted cobro will show them. Counts and money only, never conversation content. Requires billing:read.

ParámetroEnTipoObligatorioRestricciones
periodquerystringnopatrón ^\d{4}-(0[1-9]|1[0-2])$
curl https://api.vitrinadev.com/api/v1/billing/usage/live \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "as_of": "2026-10-07T15:00:00.000Z",
    "period": {
      "month": "2026-09",
      "start": "2026-09-01T04:00:00.000Z",
      "end": "2026-10-01T03:00:00.000Z",
      "elapsed_days": 30,
      "total_days": 30,
      "closed": true
    },
    "mode": "metered",
    "billing_starts_on": null,
    "show_prices": true,
    "uf": {
      "clp": 39485.65,
      "date": "2026-10-01",
      "stale": false
    },
    "usage": {
      "conversations": 3,
      "voice_minutes": 4,
      "forwarded_voice_minutes": 0,
      "eval_runs": 0,
      "email_marketable_contacts": 0,
      "email_marketing_sent": 0
    },
    "lines": [
      {
        "kind": "conversations",
        "count": 3,
        "uf_unit": 0.012,
        "uf_subtotal": 0.036
      },
      {
        "kind": "voice_minutes",
        "count": 4,
        "uf_unit": 0.006,
        "uf_subtotal": 0.024
      }
    ],
    "totals": {
      "subtotal_uf": 0.06,
      "clp_net": 2369,
      "iva_amount": 450,
      "clp_total": 2819
    },
    "projection": null,
    "next_charge": null,
    "amount_source": "invoice",
    "invoice": {
      "id": "b1b1b1b1-0000-4000-8000-000000000001",
      "number": "INV-00000000-202609",
      "status": "paid",
      "issued_at": "2026-10-01T09:00:00.000Z"
    },
    "conversations_source": "invoice",
    "daily": {
      "days": [
        "2026-09-01",
        "2026-09-02",
        "2026-09-03"
      ],
      "series": [
        {
          "metric": "conversations",
          "feature": null,
          "total": 3,
          "values": [
            1,
            0,
            2
          ]
        },
        {
          "metric": "voice_minutes",
          "feature": null,
          "total": 4,
          "values": [
            0,
            4,
            0
          ]
        },
        {
          "metric": "forwarded_voice_minutes",
          "feature": null,
          "total": 0,
          "values": [
            0,
            0,
            0
          ]
        },
        {
          "metric": "eval_runs",
          "feature": null,
          "total": 0,
          "values": [
            0,
            0,
            0
          ]
        },
        {
          "metric": "email_marketing_sent",
          "feature": null,
          "total": 0,
          "values": [
            0,
            0,
            0
          ]
        }
      ]
    },
    "addons": [],
    "history": []
  }
}

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

En esta página