# Cord documentation (full text) > Every page of docs.cordhq.app in one file, generated at build time. Index and integration rules: https://cordhq.app/llms.txt. OpenAPI: https://cordhq.app/openapi.json. --- # Integrations URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones Last updated: 2026-10-11 The 13 apps that connect with Cord in Settings › Integrations: what each one does, which way the data flows, which plan it needs, its status, what fits each case and who can connect them. ## The app directory Open **Settings › Integrations**. Each app shows as a card with its logo, its category and its status. **Connected** apps are at the top and **Available** ones below, so the page does not grow as apps are added. Tap a card to open that app's page. Everything about the integration lives there: the connection, its settings, a link to the guide and, where it applies, **Use it in Workflows** with workflow ideas that use that app and that you can create with one tap. ## The 13 apps | App | What it does | Data direction | Plan | Status | Guide | |---|---|---|---|---|---| | **HubSpot** | Clients as Companies and Contacts, quotes as Deals that move on their own, and the Cord card inside HubSpot. | Both: clients both ways; quotes from Cord to HubSpot | All | Available; the card inside HubSpot is a new feature | [Connect](/en/docs/automatizacion/integraciones/hubspot) | | **Slack** | Alerts in your channel, your own messages from workflows, link previews, the `/cord` command and approval buttons. | From Cord to Slack; the command and buttons answer from Slack | All (approval buttons, Scale or higher) | Available; previews, `/cord` and buttons are a new feature | [Slack](/en/docs/automatizacion/integraciones/slack) | | **Microsoft Teams** | A card in your channel when a quote moves forward, and your own messages from workflows. | From Cord to Teams | All | Available with Power Automate; **Connect with Microsoft** is a new feature | [Teams](/en/docs/automatizacion/integraciones/teams) | | **WhatsApp Business** | Your approved WhatsApp template to the client's phone, from a workflow. | From Cord to the client | All | Available | [WhatsApp](/en/docs/automatizacion/integraciones/whatsapp) | | **Gmail** | Quotes, invoices and reminders go out from your address; inside Gmail, the thread's quote and quoting with AI. | Sending: from Cord to Gmail. Add-on: reads the open email and creates in Cord | All | Sending as a new feature; the add-on cannot be installed yet | [Gmail](/en/docs/automatizacion/integraciones/gmail) | | **Google Sheets** | Every quote and every invoice as a row in your spreadsheet, kept current on its own. | From Cord to the spreadsheet | All | Available | [Google Sheets](/en/docs/automatizacion/integraciones/google-sheets) | | **Microsoft Excel** | The same, in an Excel table inside a workbook in your OneDrive. | From Cord to the workbook | All | Available | [Excel](/en/docs/automatizacion/integraciones/excel) | | **QuickBooks Online** | Every final invoice is posted with its customer, its lines and its currency. | Invoices from Cord to QuickBooks; payments both ways | All | New feature | [QuickBooks](/en/docs/automatizacion/integraciones/quickbooks) | | **Xero** | The same, as a draft for your accountant to approve. | Invoices from Cord to Xero; payments both ways | All | Available; payments are a new feature | [Xero](/en/docs/automatizacion/integraciones/xero) | | **Shopify** | Your store's catalog and customers for wholesale quoting, and the order back when the quote closes. | Catalog and customers from Shopify to Cord; orders from Cord to Shopify; paid store orders to invoice drafts in Cord | All | Available; stock, B2B prices and invoicing orders are a new feature | [Shopify](/en/docs/automatizacion/integraciones/shopify) | | **Zapier** | Connect Cord with thousands of apps without code. | Both: Cord events go out, actions create data in Cord | All; uses the monthly API quota | Available by invitation | [Zapier](/en/docs/automatizacion/integraciones/zapier) | | **Make** | Receive Cord events in your scenarios and create or update data in Cord. | Both | All; uses the monthly API quota | Available by invitation | [Make](/en/docs/automatizacion/integraciones/make) | | **n8n** | Your own flows with the `n8n-nodes-cord` node, with verified signatures. | Both | All; uses the monthly API quota | Available on self-hosted n8n | [n8n](/en/docs/automatizacion/integraciones/n8n) | No integration requires a paid plan to connect. What does depend on the plan: - **Zapier, Make and n8n** work with the Cord API, and every call counts against the [monthly API quota](#integrations-and-the-api-quota). - Slack, Teams, WhatsApp and HubSpot actions inside a workflow count like any workflow: 1 active on Free, 5 on Starter and no limit from Pro. See [Workflow limits](/en/docs/automatizacion/workflows/limites). - **Products and customers** that come in from Shopify count against your plan's limit, like the ones you create by hand. - Slack's **approval buttons** and the Teams approval card only appear with internal approvals, which come with the **Scale** plan or higher. ## What each status means | Status | Meaning | |---|---| | **Connected** | The integration is active and working. | | **Needs reconnecting** | The connection exists but lost its authorization (for example, someone removed the app in HubSpot). Open the app and click **Reconnect**. | | **Not connected** | Available and not set up yet. | | **Direct connection** | Connected from the other tool and authorized with one click on a Cord screen, without keys. This is the case for Zapier and Make. | | **With an API key** | Connected from the other tool by pasting a Cord API key. This is the case for n8n. | | **Coming soon** | On the way and not usable yet. | ## What fits each case | You want | Use | |---|---| | Your sales team to see Cord's clients and sales in HubSpot | **HubSpot** | | To hear in a channel when the client opens, approves or pays | **Slack** or **Microsoft Teams** with the alerts in Settings › Notifications | | A Slack or Teams message with your own text, or only in some cases | **Slack** or **Teams** with a [workflow](/en/docs/automatizacion/workflows) | | Your client to get the reminder where they actually read it | **WhatsApp Business** with a [workflow](/en/docs/automatizacion/workflows) | | To create tasks or email the team when something happens in Cord | [Cord Workflows](/en/docs/automatizacion/workflows), without connecting anything | | Your quotes and invoices in a spreadsheet | **Google Sheets** or **Microsoft Excel**, without exporting anything by hand | | Your invoices and their payments to appear in your accounting without entering them twice | **QuickBooks Online** (posted) or **Xero** (as a draft) | | To quote wholesale with your online store's catalog | **Shopify** | | Your quotes and invoices to go out from your own email | **Gmail**: connect your account in Settings › Integrations › Gmail | | To see the thread's quote and quote with AI inside Gmail | The **Cord for Gmail** add-on, once it is published (it cannot be installed yet) | | To send Cord data to an ERP or any other app without coding | **Zapier** or **Make** | | The same, on your own server or with flows you control | Self-hosted **n8n** | | To send an event to your system only in some cases | The **Send the data to a URL** action in [Workflows](/en/docs/automatizacion/workflows/acciones) | | Your client to pay with Mercado Pago | [Mercado Pago](/en/docs/pagos/mercado-pago), in **Settings › Payments › Payment methods** (it is a payment rail, not a directory app) | | To build your own integration | The [developer guide](/en/docs/desarrolladores/herramientas/integraciones) | ## Status of each integration What works today and what is still missing, as of October 7, 2026. What is marked as a **new feature** is already built, but may not be enabled on your account yet; if you do not see it, write to us. | App | Works today | Still missing | |---|---|---| | **HubSpot** | One-click connection and sync of clients, contacts and Deals. The Cord card inside HubSpot, as a new feature. | A listing in the HubSpot marketplace. | | **Slack** | **Add to Slack** to pick the channel, with your own webhook as an alternative. Link previews, the `/cord` command and approval buttons, as a new feature. | A listing in the Slack app directory. | | **Microsoft Teams** | With a Power Automate flow. **Connect with Microsoft** to pick team and channel in Cord, as a new feature. | Microsoft publisher verification: until then, Microsoft may show an unverified publisher notice. Buttons to decide approvals inside Teams. | | **WhatsApp Business** | Messages with your approved template, by pasting the phone number ID and a Meta token. | Connecting with a button, once Meta approves Cord as a provider. | | **Make** | Cord app with an invitation and one-click authorization, in every Make zone. | A listing in Make's public catalog. | | **Zapier** | Cord app with an invitation and one-click authorization. | A listing in Zapier's public directory. | | **n8n** | The `n8n-nodes-cord` node on npm for self-hosted n8n. | n8n's verification, submitted on September 21, so it appears in n8n Cloud. | | **Shopify** | Catalog and customers into Cord, and the order back when the quote is approved or paid, in the quote's currency if your store accepts it. The order starts off and you turn it on. Stock, B2B prices and invoicing the store's orders, as a new feature. | Quoting from the Shopify admin. | | **Google Sheets** and **Excel** | One row per quote and per invoice, kept current, with amounts as real numbers. | Picking a spreadsheet you already have instead of Cord creating one. | | **QuickBooks Online** and **Xero** | The final invoice arrives with its customer and lines: posted in QuickBooks, a draft in Xero. QuickBooks, and payments both ways in both, are a new feature. | QuickBooks: Intuit approving the app for every account. Xero: whoever connected before payments must reconnect. | | **Gmail** | Quotes, invoices and payment reminders go out from your Gmail address, as a new feature. The add-on shows the thread's quote, replies with it and quotes with AI from the email. | Google verification: until then, you may see the notice "Google hasn't verified this app". Publishing the add-on in the Google Workspace Marketplace. | | **Mercado Pago** (Settings › Payments › Payment methods) | Collecting quotes and invoices with your account in Mexico and Latin America, with refunds read back. | Recurring retainers, which stay on Cord Payments. Details in [Mercado Pago](/en/docs/pagos/mercado-pago). | Upcoming work also appears on the [roadmap](https://cordhq.app/en/roadmap). ## Integrations and the API quota Zapier, Make and n8n work with the Cord API. Every action or search they run in Cord (create a client, find a quote, mark it paid) is at least one API call, and so is registering or removing their webhook when you turn a Zap, scenario or flow on or off. Receiving Cord events does not use calls. | Plan | API calls included per month | When you go over | |---|---|---| | **Free** | 100 | Calls are rejected until the next month | | **Starter** | 1,000 | Billed as overage | | **Pro** | 5,000 | Billed as overage | | **Scale** | 10,000 | Billed as overage | | **Developer** | 50,000 | Billed as overage | - Only calls in **live mode** count. With an `sk_test_…` key (n8n or your own requests) you work against your test environment without using quota. - On plans with overage there is a safety cap of 10 times what is included: if a connection runs away, Cord stops it there and asks you to write to us. - Besides the monthly quota, each key has a per-minute limit; if you exceed it, the call returns **429** until the minute is over. - Webhooks created by your integrations have their own allowance of **100 per organization**, separate from your plan's webhook endpoints. Your usage for the month is in **Settings › Plans & subscription › Subscription**, in the **API calls** row. Overage pricing and plans are in [Your Cord subscription](/en/docs/cuenta/suscripcion). ## Who can connect integrations Connecting, configuring and disconnecting integrations requires the **Settings** permission. If someone without it tries to connect HubSpot, they see "You need Settings permission to connect integrations." Integrations belong to the **organization**, not a person: if whoever connected HubSpot leaves the team, the connection keeps working. Every connect, configure, sync or disconnect action is recorded in **Settings › Audit log**. ## Security - **Cord never asks for another tool's password.** HubSpot, Slack, Teams, Shopify, Google Sheets, Excel, Gmail, QuickBooks and Xero are authorized on the provider's own page. n8n uses a key you generate and can revoke, and Zapier and Make are authorized on a Cord screen that you can also revoke. - **Each integration asks for the narrowest permission it needs.** Google Sheets can only open the spreadsheet Cord created, not the rest of your Drive; sending from Gmail can only send, not read your inbox; Xero gets access to invoices, contacts and payments, plus reading your accounting settings, but not bank transactions or manual journals. - **Access credentials are stored encrypted** and only used for what each integration describes. - **Disconnecting really cuts access.** For HubSpot, Cord also revokes its authorization in your account. - **Webhook URLs are secrets.** Anyone with the URL of your Slack webhook, your Teams flow or Make can post to it; do not share them. ## If your tool is not listed With Cord's webhooks and API you can connect today any system that receives or makes HTTP calls, or use Zapier, Make or n8n as a bridge. If you want a direct integration with another app, write to contacto@cordhq.app. ## Related - [Cord Workflows](/en/docs/automatizacion/workflows): use Slack, Teams, WhatsApp and HubSpot inside a rule. - [Notifications](/en/docs/gestion/notificaciones): which alerts reach Slack and Teams. - [Webhooks for developers](/en/docs/desarrolladores/herramientas/webhooks): the events Zapier, Make and n8n receive. - [Cord OAuth](/en/docs/desarrolladores/herramientas/oauth): how Zapier and Make authorize. --- # Microsoft Excel URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/excel Last updated: 2026-10-08 How to connect Excel with Cord: the workbook Cord creates in your OneDrive with real Excel tables, its columns, how rows update by number and how to fix problems. ## How it works Cord creates an Excel workbook in your OneDrive and writes your quotes and invoices into it: one row per document, updated on its own when the document changes status. Data goes into a real **Excel table**, not a loose range: you get filters, banding, a header that stays visible while scrolling and formulas by column name, such as `=SUM(CordCotizaciones[total])`. The tables are named `CordCotizaciones` and `CordFacturas`. **Cord works only with the workbook it creates.** When you authorize, Microsoft asks for permission to read and write your OneDrive files; Cord only opens and writes the workbook it created. Connecting Excel does not give Cord access to your Teams channels. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. | | **Microsoft Excel** | A Microsoft 365 work or school account with OneDrive. Cord creates the file in that account. | | **Another spreadsheet** | You can have Google Sheets connected at the same time; each one keeps its own file. | ## Connect 1. Go to **Settings › Integrations › Microsoft Excel**. You need the **Settings** permission. 2. Click **Connect Excel** and authorize with your Microsoft work or school account. 3. When you come back, Cord creates the workbook in your OneDrive and starts filling it with what you already had. 4. Click **Open the sheet** to see it. ## What the sheet contains Two tabs, **Quotes** and **Invoices**, with one row per document: | Tab | Columns | |---|---| | **Quotes** | Number, client, status, date, valid until, currency, subtotal, discount, taxes, total, collected and public link. | | **Invoices** | Number, client, status, tax status, date, due date, currency, total, paid, balance and public link. | - **Amounts are numbers, not text.** You can sum, average and chart them without cleaning anything. - **Currency has its own column.** If you sell in two currencies, the sheet says so instead of hiding it inside the number, so you never add pesos to dollars. - **Dates use your account's time zone**, in `YYYY-MM-DD` format, which sorts correctly and both apps recognize as a date. - **The header row arrives frozen and filtered**, with columns sized to their content. ## How it stays current When a quote is sent, resent, approved, rejected, expires, receives a partial payment or is paid —and when an invoice is issued, sent, paid, becomes overdue, is voided or is marked uncollectible— Cord looks for its **number in column A** and replaces that row. If it is not there, it adds it at the end. Drafts are not written. That is why you can sort, filter and add your own columns to the right: Cord matches by number, not by row position. The only thing you should not touch is **column A**. **Update now** rewrites your latest 500 documents in each tab. Use it right after connecting or whenever you are unsure. ## What flows and in which direction Microsoft Excel is an **outbound-only** integration: Cord writes to the workbook in your OneDrive and reads nothing back. | Direction | What flows | When | |---|---|---| | **From Cord to the spreadsheet** | One row per quote and one per invoice, with the columns above. | When you connect (initial fill), when the document changes status and when you click **Update now**. | | **From the spreadsheet to Cord** | Nothing. Editing a cell, deleting a row or adding columns changes nothing in Cord. | — | If you fix a row by hand, Cord writes it again the next time that document changes. Your columns to the right of Cord's are not touched. ## Limits | Limit | Value | |---|---| | Files per connection | One, which Cord creates when you connect | | Initial fill and **Update now** | The latest 500 documents in each tab | | **Update now** | Up to 3 times every 5 minutes | | Connections per organization | One per provider | | Documents included | Quotes from sent onward and issued invoices; drafts are not | ## Disconnect With **Disconnect** on the card. The file stays in your account with what it had; it simply stops updating. If you connect again, Cord creates a new file. ## Common issues | Message or symptom | What to do | |---|---| | **"The connection to your sheet stopped working"** | Access was revoked or the account password changed. Reconnect from the card. | | **You deleted the file** | Disconnect and connect again; Cord creates and fills a new one. | | **You deleted the first row** | No problem: Cord writes it again on the next update. | | **"The workbook could not be opened"** right after connecting | OneDrive sometimes takes a few seconds to have a new file ready. Click **Update now** in a minute. | | **A row got duplicated** | Check that nobody edited column A; Cord matches by number. | ## Related - [Google Sheets](/en/docs/automatizacion/integraciones/google-sheets) - [QuickBooks Online](/en/docs/automatizacion/integraciones/quickbooks) and [Xero](/en/docs/automatizacion/integraciones/xero), if what you want is to take invoices to your accounting. - [Reports and sales performance](/en/docs/gestion/informes): your business numbers without leaving Cord. - [Custom reports and email delivery](/en/docs/gestion/informes-personalizados): if what you want is a periodic summary, every table report exports to CSV and a saved report reaches you every Monday or every 1st with the CSV attached, ready to open in Excel or Google Sheets. Unlike this integration, it's a snapshot of the period, not a sheet that updates itself. --- # Gmail URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/gmail Last updated: 2026-10-15 How to send quotes and invoices from your Gmail, and how to use the Cord add-on inside Gmail: the thread quote live, quote with AI, reply in the thread and insert while composing. ## Two ways to connect it | | Send from your Gmail | Cord add-on for Gmail | |---|---|---| | **What it does** | Quotes, invoices and payment reminders go out from your address. | A panel inside Gmail with your clients and quotes. | | **Where you connect it** | **Settings › Integrations › Gmail** | Inside Gmail, with **Connect with Cord** | | **Google permission** | Send only (`gmail.send`); it does not read your email. | Only the email you have open. | | **Available** | Yes, as a new feature | Pending publication on Google Workspace Marketplace | ## Requirements | Where | What you need | |---|---| | **Cord** | For sending, the **Settings** permission. For the add-on, the Settings permission in the workspace you authorize. Any plan. | | **Google** | A Gmail or Google Workspace account. If your Google Workspace organization blocks unverified apps, an administrator will need to allow the Cord app while Google finishes verifying it. | | **Quote with AI** | AI quotes available on your plan: 3 a month on Free, 20 on Starter, 50 on Pro, 500 on Scale and no numeric quota on Developer. | ## Send from your Gmail This feature is new and may not be enabled on your account yet. If you do not see it, write to us. 1. Go to **Settings › Integrations › Gmail**. You need the **Settings** permission. 2. Click **Connect Gmail** and authorize with your Google account. If Google shows checkboxes, keep **send email** checked: without it the connection is not completed. 3. When you come back, the card shows which address emails go out from. Send a quote as usual: it appears in your Sent folder. While Google finishes verifying the Cord app, you may see the notice "Google hasn't verified this app" when you authorize. If your Google Workspace organization blocks unverified apps, an administrator will need to allow it. These emails Cord sends **to your clients** go out from your Gmail: | Email | When | |---|---| | Quote sent | When you send or resend a quote. | | Invoice | When you issue or send an invoice, with its PDF attached. | | Payment reminder | Automatic reminders for invoices about to fall due or overdue. | | Workflow email to the client | The workflow action that writes to the client. | Internal notifications (to you and your team) still go out from Cord. **If Gmail rejects a send** —you changed your password, removed access or hit Gmail's daily limit— the email goes out from Cord so your client still gets it, and the card asks you to reconnect. A collection email is never lost to a broken connection. ## The add-on inside Gmail Open an email and click the Cord icon in the right panel. The first time, click **Connect with Cord** and authorize on the Cord screen: no key to copy. The add-on speaks English or Spanish according to your Gmail language. ### On an open email - **Who is writing.** If the sender is already your client, you see their company and latest quotes. - **The thread's quote, live.** If the subject or the start of the email carries a quote number (for example, your client's reply to "Quote COT-0006"), the panel shows it at the top with its status, amount and the last thing that happened to it. From there: - **Reply with it** opens a reply in the same thread, from your Gmail, with the quote card. - **Resend via Cord** sends the quote email again. - **Open** takes you to the quote in Cord. - **Quote with AI.** Cord reads the order in the email, matches it to your products and shows the proposed lines with quantity and price. You review them and **Create quote** creates it as a draft. If the sender is not your client yet, Cord adds them with their name and email. - **Blank quote.** Creates the quote with the subject as its first line, for you to finish in Cord. ### While composing In the compose toolbar, the Cord icon (or the three-dot menu, when Gmail hides it for space) opens **Insert quote**: it lists the recipient's sent quotes and inserts one as a card with number, amount, validity and a **View quote** button. ### Quote with AI: good to know - It uses one AI quote from your plan, same as in the Cord editor. - It ignores quoted earlier emails: it quotes what the latest message asks for. - A line not in your catalog arrives as a free-form item and says so. - Prices come from your catalog; if the client states a unit price, it is taken as the negotiated price. - It doesn't use your [connected systems](/en/docs/cotizacion/ia#your-connected-systems): the email comes from someone else and could carry hidden instructions, so Cord AI reads it without access to them. ## What Cord reads from your Google account - **Sending:** only the permission to send and your address. It cannot read your inbox. - **The add-on:** only the email you have open, and from it the sender, the subject and a quote number. The email text reaches Cord **only when you click Quote with AI**. It never reads your full inbox. While composing, it only reads the draft's recipients. Cord does not sell this data or use it for advertising, and its use of information received from Google APIs adheres to the Google API Services User Data Policy, including the Limited Use requirements. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to Gmail** (sending) | Emails to your clients (quote, invoice with its PDF, payment reminder and a workflow's email to the client) go out through your account and stay in your Sent folder. | Every time Cord writes to a client. | | **From Gmail to Cord** (add-on) | From the open email: the sender, the subject and a quote number. The email's text, only when you click **Quote with AI**. | When you open the Cord panel on an email. | | **From Cord to Gmail** (add-on) | The thread's quote with its status, your quotes for that client and the card you insert while composing. | When you open the panel or insert. | | **What it creates in Cord** (add-on) | A new client if the sender did not exist, and the quote as a draft. | When you click **Create quote** or **Blank quote**. | Cord never reads your whole inbox or stores your emails. ## Limits | Limit | Value | |---|---| | Gmail accounts for sending | One per organization | | Emails that go out through Gmail | Cord's emails to your clients, within your Google account's daily sending limit. If Gmail rejects a send, it goes out from Cord. | | Internal alerts | Still go out from Cord, not from your Gmail | | Quote with AI | Uses one AI quote from your plan per read | | API quota | The add-on does not use your plan's monthly API quota | ## Disconnect - **Sending:** **Stop sending from Gmail** on the card. Emails go back to being sent from Cord. - **The add-on:** **Disconnect** on the add-on's home card, which revokes access in Cord. You can also revoke it under **Settings › Developer mode** (authorized connections). - Either way, you can remove access from your Google account's security settings. ## Common issues | Message or symptom | What to do | |---|---| | **"The permission to send email is missing"** | You unchecked the send box when authorizing. Reconnect and keep it checked. | | **"Google hasn't verified this app"** | While Google's verification finishes, click **Advanced › Go to Cord**. | | **The add-on says authorization is required** | Open the Cord icon and accept every permission Google asks for, without unchecking any. | | **"Your Cord plan used its AI quotes for this month"** | Create a blank quote or upgrade your plan. | | **"Quote in this thread" does not appear** | The email has no quote number in the subject or at the start of the text. | ## Related - [Preview and sending](/en/docs/cotizacion/envio) - [Cord AI: automatic quotes](/en/docs/cotizacion/ia) - [Google Sheets](/en/docs/automatizacion/integraciones/google-sheets): uses the same Google account, with its own permission. - [Integrations](/en/docs/automatizacion/integraciones) --- # Google Sheets URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/google-sheets Last updated: 2026-10-08 How to connect Google Sheets with Cord: the sheet Cord creates in your Drive, its columns, how rows update by number, the permission it asks for and how to fix problems. ## How it works Cord creates a spreadsheet in your Google Drive and writes your quotes and invoices into it: one row per document, updated on its own when the document changes status. It is there for the usual work —totaling the month, filtering by client, building a chart— without exporting anything by hand. **Cord can only open the sheet it creates.** It asks for `drive.file`, the narrowest permission Google offers: it sees nothing else in your Drive. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. | | **Google Sheets** | A Google account (Gmail or Google Workspace) with Google Drive. Cord creates the file in that account. | | **Another spreadsheet** | You can have Microsoft Excel connected at the same time; each one keeps its own file. | ## Connect 1. Go to **Settings › Integrations › Google Sheets**. You need the **Settings** permission. 2. Click **Connect Google Sheets** and authorize with your Google account. 3. When you come back, Cord creates the file in your Drive (named after your business and the year) and starts filling it with what you already had. 4. Click **Open the sheet** to see it. The first fill takes a moment if you have a lot of history. You can have Google Sheets and Excel connected at the same time; each keeps its own file. ## What the sheet contains Two tabs, **Quotes** and **Invoices**, with one row per document: | Tab | Columns | |---|---| | **Quotes** | Number, client, status, date, valid until, currency, subtotal, discount, taxes, total, collected and public link. | | **Invoices** | Number, client, status, tax status, date, due date, currency, total, paid, balance and public link. | - **Amounts are numbers, not text.** You can sum, average and chart them without cleaning anything. - **Currency has its own column.** If you sell in two currencies, the sheet says so instead of hiding it inside the number, so you never add pesos to dollars. - **Dates use your account's time zone**, in `YYYY-MM-DD` format, which sorts correctly and both apps recognize as a date. - **The header row arrives frozen and filtered**, with columns sized to their content. ## How it stays current When a quote is sent, resent, approved, rejected, expires, receives a partial payment or is paid —and when an invoice is issued, sent, paid, becomes overdue, is voided or is marked uncollectible— Cord looks for its **number in column A** and replaces that row. If it is not there, it adds it at the end. Drafts are not written. That is why you can sort, filter and add your own columns to the right: Cord matches by number, not by row position. The only thing you should not touch is **column A**. **Update now** rewrites your latest 500 documents in each tab. Use it right after connecting or whenever you are unsure. ## What flows and in which direction Google Sheets is an **outbound-only** integration: Cord writes to the spreadsheet in your Google Drive and reads nothing back. | Direction | What flows | When | |---|---|---| | **From Cord to the spreadsheet** | One row per quote and one per invoice, with the columns above. | When you connect (initial fill), when the document changes status and when you click **Update now**. | | **From the spreadsheet to Cord** | Nothing. Editing a cell, deleting a row or adding columns changes nothing in Cord. | — | If you fix a row by hand, Cord writes it again the next time that document changes. Your columns to the right of Cord's are not touched. ## Limits | Limit | Value | |---|---| | Files per connection | One, which Cord creates when you connect | | Initial fill and **Update now** | The latest 500 documents in each tab | | **Update now** | Up to 3 times every 5 minutes | | Connections per organization | One per provider | | Documents included | Quotes from sent onward and issued invoices; drafts are not | ## Disconnect With **Disconnect** on the card. The file stays in your account with what it had; it simply stops updating. If you connect again, Cord creates a new file. ## Common issues | Message or symptom | What to do | |---|---| | **"The connection to your sheet stopped working"** | Access was revoked or the account password changed. Reconnect from the card. | | **You deleted the file** | Disconnect and connect again; Cord creates and fills a new one. | | **You deleted the first row** | No problem: Cord writes it again on the next update. | | **A row got duplicated** | Check that nobody edited column A; Cord matches by number. | ## Related - [Microsoft Excel](/en/docs/automatizacion/integraciones/excel) - [QuickBooks Online](/en/docs/automatizacion/integraciones/quickbooks) and [Xero](/en/docs/automatizacion/integraciones/xero), if what you want is to take invoices to your accounting. - [Reports and sales performance](/en/docs/gestion/informes): your business numbers without leaving Cord. - [Custom reports and email delivery](/en/docs/gestion/informes-personalizados): if what you want is a periodic summary, every table report exports to CSV and a saved report reaches you every Monday or every 1st with the CSV attached, ready to open in Excel or Google Sheets. Unlike this integration, it's a snapshot of the period, not a sheet that updates itself. --- # Connect HubSpot URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/hubspot Last updated: 2026-10-07 How to connect your HubSpot account with Cord: requirements, requested permissions, what happens when you connect, possible messages, switching accounts and disconnecting. ## What the integration does - **Every Cord client** is created in HubSpot as a **Company** and, if it has an email or contact name, also as a **Contact** associated with that Company. - **Every sent quote** is created as a **Deal** with its amount and currency, associated with the client's Company and Contact. - **The Deal moves on its own**: Cord updates its stage when the client opens the quote, approves it, rejects it, when it expires, is paid or invoiced. - **Contact corrections flow back to Cord**: if you fix the Company name, or the Contact's name, email or phone in HubSpot, they change in Cord too. Field-by-field detail in [What syncs](/en/docs/automatizacion/integraciones/hubspot-sincronizacion). **Cord owns the sale status.** Moving a Deal to another stage in HubSpot does not change the quote in Cord: its status is decided by the client's approval and payment. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to HubSpot** | Every client as a Company and Contact; every sent quote as a Deal, with its amount, currency and stage. | When the client is created or changed, and every time the quote moves forward. | | **From HubSpot to Cord** | Corrections to the Company name, and to the Contact's name, email and phone, only on records already linked to Cord. | When they are saved in HubSpot. | | **From HubSpot to Cord** | Nothing else: moving a Deal to another stage or creating new Companies or Deals in HubSpot changes nothing in Cord. | — | | **From a workflow** | A note on the Deal or the Company, with the **Add a note in HubSpot** action. | When the workflow runs. | Field-by-field detail is in [What syncs](/en/docs/automatizacion/integraciones/hubspot-sincronizacion). ## Before connecting - **In Cord:** you need the **Settings** permission. - **In HubSpot:** you need a user who can install apps in the account. If you do not have one, ask a HubSpot Super Admin to connect. - **One account per organization:** a HubSpot account can only be connected to one Cord organization, and each Cord organization connects to a single HubSpot account. - **Currencies:** if you quote in several currencies, enable them in your HubSpot account's currency settings. A Deal in a currency HubSpot has not enabled cannot be created. ## Connect step by step 1. **Open the app.** Go to **Settings › Integrations** and tap **HubSpot**. 2. **Click Connect HubSpot.** Cord takes you to HubSpot. 3. **Choose the HubSpot account**, if you have several, and **accept the permissions**. You have 10 minutes to complete this; if it takes longer, click Connect again. 4. **Return to Cord.** You see "HubSpot is connected." and the **Connected** status, with the account name. 5. **Review the stages.** In **HubSpot stage for each quote status**, confirm the pipeline and the stage for each status and click **Save stages**. If you use HubSpot's default pipeline, Cord already suggests a stage for each status. See [Pipeline and stages](/en/docs/automatizacion/integraciones/hubspot-etapas). 6. **Send what you already had (optional).** In **Existing data**, click **Send existing data** to send your earlier clients and quotes. See [What syncs](/en/docs/automatizacion/integraciones/hubspot-sincronizacion). From then on, every new or updated client and every quote that moves forward is sent automatically. If the button does not take you to HubSpot or you come back to an error, **click Connect HubSpot again** from Cord. Do not reuse an old authorization link saved in your browser: every attempt creates a one-time link. ## Permissions Cord requests When authorizing, HubSpot shows the permissions Cord requests. Only what this integration needs: | Permission | What for | |---|---| | Read and write **Companies** | Create each client's Company and read name corrections. | | Read and write **Contacts** | Create each client's Contact, find existing ones by email and read corrections. | | Read and write **Deals** | Create each quote's Deal, move its stage and read your pipelines. | Cord does not read your emails, calls, tickets, lists, forms or any other HubSpot object. ## Connection messages | Message | What happened | What to do | |---|---|---| | HubSpot is connected. | All good. | Review the stages. | | You canceled the HubSpot connection. | You closed or declined the authorization in HubSpot. | Click **Connect HubSpot** again whenever you want. | | The connection request expired or is not valid. Try again. | More than 10 minutes passed, an old link was used or it was opened from another session. | Click **Connect HubSpot** again from Cord. | | That HubSpot account is already connected to another Cord organization. | The account is in use in another organization. | Disconnect it there or choose another account. | | Couldn't connect HubSpot. Try again. | HubSpot did not complete the authorization. | Try again; if it persists, write to contacto@cordhq.app. | | You need Settings permission to connect integrations. | Your role lacks the Settings permission. | Ask the account owner to connect or grant you the permission. | ## The connection panel Once connected, the HubSpot page shows: | Item | What it is | |---|---| | **HubSpot account** | The number and domain of the connected account. | | **Last sync** | When something was last sent or received. "Not yet" if nothing has happened. | | **Queued** | Pending sends. | | **Errors (7 days)** | Sends that failed in the last week. | | **Last error** | The most recent error message, if any. | What to do with each error: [HubSpot troubleshooting](/en/docs/automatizacion/integraciones/hubspot-problemas). ## The Cord card inside HubSpot This feature is new and may not be enabled on your account yet. If you do not see it, write to us. With HubSpot connected, every **Deal**, **Company** and **Contact** shows the Cord card in its sidebar: | Record | What it shows | |---|---| | **Deal** | The Cord quote linked to that Deal. | | **Company** or **Contact** | The linked Cord client and their latest 8 quotes. | Each quote shows number, status, amount with its currency, date and the **client link**, to copy or open it without leaving HubSpot. The **Create quote in Cord** button opens the Cord editor with that client already selected. The card **only reads**: creating, editing or sending always happens in Cord, with your session. Cord checks that every request is signed by HubSpot and answers only with the data of the organization connected to that account. If the card does not appear, open a Deal in HubSpot, click **Customize** in the sidebar and add the **Cord** card from **Apps**. ## Switch to another HubSpot account Disconnect the current account and connect the new one. When you connect a **different** account, Cord forgets the links to the previous account and resets the stage settings, because the other account's pipelines do not exist in the new one. Then use **Send existing data** to populate the new account. If you reconnect **the same** account, Cord keeps the links and your stage settings: Companies and Deals are not duplicated. Changes you made in Cord while disconnected were not sent; use **Send existing data** to catch up. ## Disconnect 1. In **Settings › Integrations › HubSpot**, click **Disconnect**. 2. Confirm in **Disconnect HubSpot?**. 3. You see "HubSpot disconnected". When you disconnect: - Cord **stops syncing** and discards queued sends. - Cord **revokes its access** to your HubSpot account. - **What is already in HubSpot is not deleted**: Companies, Contacts, Deals and notes stay as they are. - Workflows with the **Add a note in HubSpot** action start failing with "Connect HubSpot in Settings › Integrations to use this action." ## Limits | Limit | Value | |---|---| | HubSpot accounts per organization | One, and each HubSpot account can only be in one Cord organization | | Time to authorize in HubSpot | 10 minutes from when you click **Connect HubSpot** | | **Send existing data** | Up to 500 clients and 500 sent quotes per run, up to 3 times per hour | | Cord card on a Company or Contact | Its latest 8 quotes | | Notes from workflows | 120 per hour per organization, up to 2,000 characters | | Quotes without a currency or in a status without a stage | Not sent as a Deal: Cord never sends an amount without its currency | ## Related - [What syncs](/en/docs/automatizacion/integraciones/hubspot-sincronizacion) - [Pipeline and stages](/en/docs/automatizacion/integraciones/hubspot-etapas) - [HubSpot troubleshooting](/en/docs/automatizacion/integraciones/hubspot-problemas) - [The invoice goes out when you get paid](/en/docs/automatizacion/workflows/ideas#4-the-invoice-goes-out-when-you-get-paid), a ready-made idea that, with HubSpot connected, leaves the note on the Deal --- # HubSpot pipeline and stages URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/hubspot-etapas Last updated: 2026-09-15 How to choose the HubSpot pipeline and the Deal stage for each Cord quote status, the default setup and what happens when you change it. ## The seven statuses that are sent Cord moves the Deal when the quote changes to one of these statuses. For each one you choose a HubSpot stage: | Status in Cord | When it happens | |---|---| | **Sent** | The quote is sent to the client. This is when the Deal is created. | | **Viewed by client** | The client opens the link. | | **Approved** | The client approves it. | | **Rejected** | The client rejects it. | | **Expired** | The validity date passes without closing. | | **Paid** | Full payment is recorded. | | **Invoiced** | The invoice or CFDI is issued. | Drafts are not sent, so they have no stage. ## Default setup If you change nothing, Cord uses your HubSpot account's **default pipeline** with these stages: | Status in Cord | HubSpot stage | |---|---| | Sent | Presentation scheduled | | Viewed by client | Decision maker bought-in | | Approved | Contract sent | | Rejected | Closed lost | | Expired | Closed lost | | Paid | Closed won | | Invoiced | Closed won | These are the stages HubSpot creates its sales pipeline with. If your account renamed or deleted them, choose yours before sending data. ## Choose another pipeline or change stages 1. Go to **Settings › Integrations › HubSpot**. Cord loads your HubSpot pipelines ("Loading HubSpot pipelines…"). 2. In **Pipeline**, choose the pipeline for your Deals. 3. In **HubSpot stage for each quote status**, choose a stage for each of the seven statuses. 4. Click **Save stages**. You see "Stages saved". When you switch to a pipeline that is not the default, Cord cannot guess your stages: they all show **Choose a stage** until you select them. While any is missing you see "Choose a stage for each status. Quotes in a status without a stage aren't sent to HubSpot." You can reuse a stage for several statuses. For example, Rejected and Expired in the same "lost" stage. ## Close date When a quote reaches a closing status, Cord fills the Deal's **Close date** with the actual close date: | Status | Close date | |---|---| | **Paid** | The payment date. | | **Invoiced** | The payment date or, if no payment was recorded, the approval date. | | **Expired** | The quote's validity date. | | **Rejected** | The day Cord sends the rejection to HubSpot. | Other statuses do not touch the close date. Because it uses the actual date, sending existing data from past months does not leave every Deal closed "today". For HubSpot reports to count won and lost correctly, map Paid and Invoiced to a **won** stage and Rejected and Expired to a **lost** stage. ## What happens if you change the setup later - **Existing Deals do not move when you save.** Each Deal takes the new stage the next time its quote changes. - **Changing pipeline** works the same way: a Deal moves to the new pipeline when its quote changes again. - To move everything at once, click **Send existing data** after saving: among the 500 most recent quotes, those whose Deal does not match the new setup are updated. ## Errors when saving | Message | What to do | |---|---| | That pipeline does not exist in your HubSpot account. | Reload the page: the pipeline was deleted or changed in HubSpot. | | A stage does not belong to the chosen pipeline. | You switched pipelines and a stage from the previous one remained. Choose them again. | | We could not check your HubSpot pipelines. Try again. | HubSpot did not respond. Wait a moment and save again. | | We couldn't read your HubSpot pipelines. Reload the page to try again. | Shows when opening the page if HubSpot did not respond or the connection needs reconnecting. | | Connect HubSpot before configuring it. | The connection was disconnected. Connect again. | ## If you delete a stage in HubSpot If you delete or archive in HubSpot a stage Cord uses, sends of quotes in that status fail with a message saying the configured pipeline or stage no longer exists in HubSpot. Choose another stage, save and use **Send existing data** to resend the ones that failed. ## Next - [What syncs](/en/docs/automatizacion/integraciones/hubspot-sincronizacion) - [HubSpot troubleshooting](/en/docs/automatizacion/integraciones/hubspot-problemas) --- # HubSpot troubleshooting URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/hubspot-problemas Last updated: 2026-09-15 How to read the HubSpot connection panel and what to do with each error: reconnecting, permissions, currencies, stages, duplicate contacts and HubSpot limits. ## Where to see if something fails In **Settings › Integrations › HubSpot**: - **Status:** **Connected** or **Needs reconnecting**. The latter also shows on the directory card. - **Queued:** pending sends. It is normal to see numbers after **Send existing data**; they should go down on their own. - **Errors (7 days):** sends that failed after all their retries. - **Last error:** the most recent error message. Use the tables below to fix it. Sync error messages appear in your account's language. ## How Cord retries - If HubSpot **does not respond** or has a **temporary problem**, Cord retries the same send up to 5 times, with more spacing each time. - If HubSpot **asks to slow down**, Cord pauses sends for as long as HubSpot says and continues, without counting that pause as a failure. - If the connection **lost its authorization**, Cord stops sending and reschedules for later; sends resume when you reconnect. - Data errors (a currency not enabled, a stage that no longer exists) **are not retried**, because they would fail the same way. They are recorded as errors until you fix the cause. After fixing the cause of a data error, click **Send existing data** to resend what failed. ## Messages and what to do ### Connection | Message or status | Cause | What to do | |---|---|---| | **Needs reconnecting** | Someone removed the Cord app in HubSpot, changed permissions or the authorization expired. | Click **Reconnect** and authorize again with the same account. Your links and stages are kept. | | The HubSpot connection is not active. | Same as above. | **Reconnect**. | | HubSpot did not grant permission for this operation. Reconnect the account to accept the permissions. | The authorization is missing a required permission, or your HubSpot user lost access. | Reconnect with a user who can install apps and accept all permissions. | | The HubSpot integration is not available yet. | The integration is not enabled. | Write to contacto@cordhq.app. | ### Data | Message | Cause | What to do | |---|---|---| | HubSpot does not accept this quote's currency. Enable it in your HubSpot account's currency settings. | The quote uses a currency your HubSpot account has not enabled. | Enable the currency in HubSpot's account currency settings. Then **Send existing data**. | | The configured pipeline or stage no longer exists in HubSpot. Check them in Settings › Integrations. | You deleted or archived in HubSpot the pipeline or a stage Cord uses. | Choose another stage in [Pipeline and stages](/en/docs/automatizacion/integraciones/hubspot-etapas), save and resend. | | Two Cord clients use the email … only the first was linked in HubSpot. Fix the duplicate email in Cord. | Two different clients share the same contact email; HubSpot allows only one Contact per email. | Fix the email on one of the two clients in Cord. | | HubSpot rejected the data sent. | HubSpot did not accept a value. | Check that the client's name, email and phone are valid. If it persists, write to us with the quote number or client. | | HubSpot could not find where to create the record. | HubSpot responded that it did not find where to create the record. | Reconnect HubSpot. If it persists, write to us with the quote number or client. | | The client could not be updated with the HubSpot data. | A change coming from HubSpot did not pass Cord's validation. | Fix the data in HubSpot or directly in Cord. | ### Temporary | Message | What happens | |---|---| | HubSpot did not respond in time. | Cord retries on its own. | | HubSpot had a temporary problem. | Cord retries on its own within minutes. | | HubSpot asked to slow down requests. | Cord waits as long as HubSpot says and continues. | | Internal error while syncing with HubSpot. | An unexpected Cord failure. It retries; if it repeats, write to us. | ## Common situations ### "I don't see the Deal for a quote" Check, in order: 1. **Was the quote sent?** Drafts are not sent. 2. **Does its status have a stage?** If you left a status without a stage, quotes in that status are not sent. 3. **Is it queued?** Look at **Queued** in the panel. 4. **Is there an error?** Look at **Last error**; a currency not enabled is the most common cause. 5. **Is it older than the connection?** Earlier data is not sent on its own: use **Send existing data**. ### "Companies got duplicated in HubSpot" Cord creates one Company per client and does not search for existing Companies by name. If you already had those companies in HubSpot before connecting, you see two. You can merge them in HubSpot. Contacts are not duplicated: Cord finds them by email. ### "I moved a Deal in HubSpot and nothing changed in Cord" That is expected. The sale status is decided in Cord by the client's approval and payment, and Deals do not flow back to Cord. The next time the quote changes, Cord moves the Deal to the matching stage. ### "I fixed a phone in HubSpot and Cord still has the old one" Check that the Contact is **linked** to a Cord client (Cord created it or found it by email). Contacts created by hand in HubSpot and not linked do not update anyone. Empty fields are not applied either: clearing a phone in HubSpot does not clear it in Cord. ### "The workflow note went to the Company instead of the Deal" The quote did not have a Deal yet when the workflow ran, usually because its status has no stage or a send failed. Fix the cause; the following notes will go to the Deal. ## Contact If none of this solves it, write to **contacto@cordhq.app** with your organization name, the affected quote number or client, and the text of **Last error**. ## Next - [Connect HubSpot](/en/docs/automatizacion/integraciones/hubspot) - [What syncs](/en/docs/automatizacion/integraciones/hubspot-sincronizacion) --- # What syncs with HubSpot URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/hubspot-sincronizacion Last updated: 2026-09-15 Field by field: how Cord clients and quotes are sent to HubSpot, what comes back from HubSpot to Cord, when it happens, how duplicates are avoided and what does not sync. ## At a glance | In Cord | In HubSpot | Direction | |---|---|---| | Client (company name) | Company | Cord → HubSpot, and the name comes back | | Client (contact, email, phone) | Contact associated with the Company | Cord → HubSpot, and changes come back | | Sent quote | Deal associated with the Company and Contact | Cord → HubSpot only | | Quote status | Deal stage | Cord → HubSpot only | ## Clients → Companies and Contacts ### The Company | Field in Cord | HubSpot property | |---|---| | Company | Company name | Every Cord client creates **its own Company** in HubSpot. Cord does not look for existing Companies by name: if you already had that company in HubSpot before connecting, you may end up with two. Review your Companies after using **Send existing data**. ### The Contact | Field in Cord | HubSpot property | |---|---| | Contact (name) | First name and Last name. The first word goes to First name and the rest to Last name. | | Email | Email | | Phone | Phone number | - The Contact is only created if the client has an **email or contact name**. A client with neither stays as a Company only. - **No duplicate contacts:** before creating a Contact, Cord looks in HubSpot for one with the same email. If it exists, Cord uses it and updates its data instead of creating another. - The Contact is **associated with the client's Company**. - If two Cord clients share the same email, only the first is linked to that Contact, and the panel shows a warning to fix the duplicate email in Cord. ### When they are sent A client is sent to HubSpot when **created** and every time it is **updated** in Cord. It is also sent before its first quote, so the Deal is created already associated. If a change does not touch any field that goes to HubSpot (for example, you changed payment terms), Cord makes no call. ## Quotes → Deals | Data in Cord | Deal property | |---|---| | Number and client | Deal name, like "COT-128 · Northwind" | | Total | Amount | | Sale currency | Currency | | Chosen pipeline | Pipeline | | Quote status | Deal stage, per your [stage settings](/en/docs/automatizacion/integraciones/hubspot-etapas) | | Actual close date | Close date, only when reaching Rejected, Expired, Paid or Invoiced ([details](/en/docs/automatizacion/integraciones/hubspot-etapas)) | - **Drafts are not sent.** The Deal is created when the quote is sent to the client. - On creation, the Deal is **associated with the client's Company and Contact**. - Every status change **moves the Deal** to the matching stage: Sent, Viewed by client, Approved, Rejected, Expired, Paid and Invoiced. - If the total changes (for example, you edit and resend), the Deal amount is updated. - **A status without a stage is not sent.** If you left a status without a stage, quotes in that status do not reach HubSpot until you assign one. ## From HubSpot to Cord When someone corrects data in HubSpot, Cord receives it right away and applies it to the linked client: | If in HubSpot you change | In Cord it changes | |---|---| | Company name of the Company | Company | | First name or Last name of the Contact | Contact | | Email of the Contact | Email | | Phone number of the Contact | Phone | Rules: - **Linked clients only.** Creating a new Company or Contact in HubSpot does **not** create a client in Cord. - **An empty field does not erase anything.** If you clear the phone in HubSpot, Cord keeps the one it had. - **An invalid email is ignored.** - Nothing else comes back: credit, payment terms, tax data and address are edited only in Cord. - The change is recorded in **Settings › Audit log** as coming from HubSpot with the fields that changed, and fires the **A client is updated** event for your workflows and webhooks. **Deals do not come back.** Moving a Deal's stage, changing its amount or deleting it in HubSpot changes nothing in Cord. The sale status is decided by the client's approval and payment in Cord. ## No echoes When a change arrives from HubSpot, Cord applies it but **does not send it back** to HubSpot. And when Cord sends something to HubSpot, it recognizes the notification HubSpot sends back and does not process it as a new change. No data bounces between the two tools. ## Deletions | If you delete… | Then | |---|---| | A client in Cord | Cord forgets its HubSpot link. The Company and Contact **stay in HubSpot**. | | A draft quote in Cord | Nothing; drafts are not sent. | | A Company or Contact in HubSpot | Cord forgets the link. The client stays in Cord; if you edit it again in Cord, it is created again in HubSpot. | | A Deal in HubSpot | Cord detects it on the next change to that quote and creates a new Deal. | Cord never deletes anything in HubSpot. ## When it happens - **Right away.** Every change in Cord is sent as soon as it happens, usually within seconds. - **With retries.** If HubSpot does not respond or asks to slow down, Cord retries automatically, up to 5 times per send, with more spacing each time. - **A daily check** picks up any pending send and clears send history older than 14 days. The panel shows how many sends are **Queued** and how many failed in **Errors (7 days)**. ## Existing data Connecting HubSpot does not send anything from the past on its own. To send what already existed: 1. In **Settings › Integrations › HubSpot**, find **Existing data**. 2. Click **Send existing data**. 3. You see "N records queued for HubSpot". It runs in the background; you can leave the page. What is sent: - Up to **500 clients**, the most recent. - Up to **500 quotes** that are not drafts, the most recent. - Anything already linked and unchanged is not created or updated again, so you can click the button more than once without duplicating. ## What does not sync - Products and catalog. - Quote line items. - Cord Invoicing invoices, payments, CFDI and documents. - Tasks, payment promises and chat conversations. - Notes, except those created by a workflow with the [Add a note in HubSpot](/en/docs/automatizacion/workflows/acciones) action. - HubSpot owners: Deals and Companies are created without an assigned owner. ## Next - [Pipeline and stages](/en/docs/automatizacion/integraciones/hubspot-etapas) - [HubSpot troubleshooting](/en/docs/automatizacion/integraciones/hubspot-problemas) --- # Make URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/make Last updated: 2026-10-07 How to connect the Cord app on Make: requirements, one-click authorization, modules, what flows each way, the monthly API quota per plan, how to disconnect, Webhooks and HTTP as an alternative, duplicates and errors. ## What it does The Cord app for Make has an instant trigger (**Watch Events**), actions to create and change data in Cord, searches with pagination and a universal module for any other API operation. It is authorized with one click on a Cord screen, without keys, and works in every Make zone. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission in the workspace you are connecting. Any plan. | | **Make** | A Make account. To install the app, being an Admin, Owner or App Developer of that Make organization. The operations your scenarios use are billed by Make according to your Make plan. | | **Quota** | Every action or search module uses calls from your Cord plan's monthly API quota. See [Limits](#limits). | ## Connect the Cord app The Cord app for Make is shared by invitation. In **Settings › Integrations › Make** you will find the **Open Cord on Make** button, which takes you straight to the invitation. 1. **Install the app.** Click **Open Cord on Make**, then **Install**, pick your Make organization and confirm. Make only lets Admins, Owners or App Developers of that organization install apps. 2. **Create the connection.** In a scenario add any Cord module and click **Create a connection** › **Save**. 3. **Authorize in Cord.** A Cord screen opens where you pick the workspace and click **Authorize**. There are no keys to create or paste. Whoever authorizes needs access to **Settings** in that workspace. Make renews the access on its own; to cut it, revoke the connection in the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench), where it shows up as Make's **Authorized connection**. | Type | Modules | |---|---| | **Instant trigger** | **Watch Events**: choose the Cord events and the scenario starts as soon as they happen. | | **Actions** | Create a Client, Update a Client, Get a Client, Create a Quote, Get a Quote, Send a Quote, Mark a Quote as Paid and Create a Task. | | **Searches** | Search Clients and Search Quotes, with pagination. | | **Universal** | **Make an API Call**, for any other operation in the Cord API. | Each active **Watch Events** creates its own webhook in Cord, with a limit separate from your plan's endpoints. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to Make** | The event you chose in **Watch Events**, with the object's data. | Instantly, every time it happens in Cord. | | **From Make to Cord** | Whatever the module does: create or update a client, create or send a quote, mark it paid or create a task. | When the scenario runs. | | **Searches and lookups** | Make reads clients or quotes to use them in the next module. It changes nothing. | When the scenario runs. | What a module does in Cord fires the same events as if a person had done it, with **Who caused it: The API**. ## Limits | Limit | Value | |---|---| | API calls per month | Free 100, Starter 1,000, Pro 5,000, Scale 10,000, Developer 50,000 | | When you go over the quota | On Free, calls are rejected until the next month; from Starter they are billed as overage, with a safety cap of 10 times what is included | | Webhooks created by your scenarios | 100 per organization, separate from your plan's webhook endpoints | | Live authorized connections | 25 per app and per organization | - **What uses quota:** every action, search or **Make an API Call** module, and registering or removing the **Watch Events** webhook. Receiving events does not use quota. - **How much you have used:** in **Settings › Plans & subscription › Subscription**, **API calls** row. - Requests with **HTTP › Make a request** and an `sk_live_…` key also use quota; with `sk_test_…` they do not. ## Disconnect **Turn off a scenario:** deactivate it in Make. For Cord to stop sending it events, also delete its webhook in Make's **Webhooks** section: when you delete it, Make removes it from Cord. **Cut Make's access to Cord:** 1. Go to **Settings › Integrations › Make** and click **View authorized connections**. The **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) opens. 2. Find Make's **Authorized connection** row, with the **OAuth** tag. 3. Click **Revoke** and confirm. From that moment Make can no longer call the API with that connection, and the webhooks its scenarios had created stop receiving events. In Make, Cord modules fail with an authorization error until you create the connection again. If you used the Webhooks and HTTP alternative, delete the endpoint in **Webhooks** and revoke the key in **API**. ## Alternative: Webhooks and HTTP If you prefer not to install the app, Make connects with Cord through two modules Make already includes: | Direction | Make module | What you need in Cord | |---|---|---| | **Cord → Make**: a Cord event starts your scenario | **Webhooks › Custom webhook** | A webhook endpoint with the Make URL | | **Make → Cord**: your scenario creates or updates Cord data | **HTTP › Make a request** | A secret API key with write access | Both are set up in the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) (**Webhooks** and **API keys** tabs): if you do not see it, turn on **Developer mode** in **Your account › Preferences**. ## Receive Cord events 1. **Create the webhook in Make.** In your scenario add **Webhooks › Custom webhook**, click **Add**, name it and copy the URL Make gives you. 2. **Register the endpoint in Cord.** Open **Webhooks** in the Developers panel, paste the Make URL and save. Cord shows a signing secret once; Make does not use it, but keep it if you plan to verify signatures later. 3. **Choose the events.** Check only the ones your scenario needs, for example `quote.approved` or `invoice.paid`. 4. **Teach Make the event shape.** In Make click **Redetermine data structure** and, in Cord, click **Test** on the endpoint. Make receives a sample event and learns its fields. 5. **Map and turn on.** Use the fields in the following modules (for example `data.folio`, `data.total`, `data.cliente`) and turn on the scenario. ### What each event contains Each event is JSON with four fields: | Field | What it is | |---|---| | `id` | Unique event identifier. It stays the same if Cord retries the delivery. | | `event` | The event type, for example `quote.paid`. | | `created_at` | When it happened. | | `data` | The object data: for a quote, `id`, `folio`, `status`, `moneda`, `total`, `cliente`, `cliente_id` and the public link. | The full list of events and their fields is in [Webhooks for developers](/en/docs/desarrolladores/herramientas/webhooks). ### One endpoint or several You can register one endpoint per scenario with only its events, or one with several events and a **Router** in Make filtering by `event`. The first is easier to maintain; the second uses fewer endpoints. Endpoints you register by hand count toward your plan's webhook limit: 16 on Free, Starter and Pro; 32 on Scale; 100 on Developer. ### Deliveries and retries Each endpoint keeps a delivery log with the status, response time and Make's response. If Make does not respond, Cord retries the delivery. Since the `id` does not change between retries, add a filter or data store in Make so the same `id` is not processed twice. **Treat the Make webhook URL as a secret.** Make does not verify Cord's signature, so anyone who knows the URL could send fake data to your scenario. Do not share it and, if you think it leaked, delete the endpoint in Cord, create a new webhook in Make and register the new URL. ## Create or update data in Cord 1. **Create a key.** In **API**, in the Developers panel, create a **secret key** with **write** scope. It is shown once; store it in the Make connection, not in a text field of the scenario. 2. **Add HTTP › Make a request** to your scenario. 3. **Configure it:** - **URL:** the endpoint, for example `https://cordhq.app/api/v1/clientes`. - **Method:** `POST` to create, `PATCH` to update, `GET` to search. - **Headers:** `Authorization` with `Bearer` followed by your key, and `Content-Type` with `application/json`. - **Body type:** `Raw`, **Content type** JSON, with the resource fields. - **Parse response:** on, to use the response in the next modules. 4. **Avoid duplicates** with the `Idempotency-Key` header (see below). ### What you can do | You want | Request | |---|---| | Find a client by email before creating it | `GET /api/v1/clientes?email=client@example.com` | | Create a client | `POST /api/v1/clientes` with at least `empresa` | | Update a client's contact details | `PATCH /api/v1/clientes/{id}` with `contacto`, `email`, `telefono`, etc. | | Find a quote by number | `GET /api/v1/cotizaciones?folio=COT-00104` | | Create a quote | `POST /api/v1/cotizaciones` | | Send, approve, reject or mark a quote paid | `POST /api/v1/cotizaciones/{id}` with `action`: `send`, `resend`, `approve`, `reject` or `mark_paid` | | Create a task | `POST /api/v1/tareas` with `titulo` and, optionally, `due_date` and `cotizacion_id` | Fields for each endpoint: [Clients](/en/docs/desarrolladores/funciones/clientes), [Quotes](/en/docs/desarrolladores/funciones/cotizaciones) and [Tasks](/en/docs/desarrolladores/funciones/tareas). ### Avoid duplicates Make can retry a module. So a retry does not create the same client twice, add the `Idempotency-Key` header with a fixed value for that operation, for example the `id` of the event that caused it or the row id of your spreadsheet. If Cord already received that key with the same request, it returns the original result instead of creating another record. ### Test keys With an `sk_test_…` key your scenario works against your account's test environment, isolated from your real data. Use it while building the scenario and switch to the `sk_live_…` key when done. ## Example scenarios - **Quote approved → spreadsheet:** Custom webhook with `quote.approved` → Google Sheets › Add a row with number, client and total. - **Form → client in Cord:** Typeform › Watch responses → HTTP `GET /api/v1/clientes?email=` → if it does not exist, HTTP `POST /api/v1/clientes`. - **Invoice paid → accounting:** Custom webhook with `invoice.paid` → your accounting system. - **Payment on another platform → mark paid in Cord:** your platform's trigger → HTTP `GET /api/v1/cotizaciones?folio=` → HTTP `POST /api/v1/cotizaciones/{id}` with `{"action":"mark_paid"}`. ## Common errors | Cord response | Cause | What to do | |---|---|---| | **401** | The key is missing, mistyped or revoked. | Check the `Authorization: Bearer sk_live_…` header. | | **403** | The key is read-only. | Create a key with write scope. | | **404** | The id does not exist in your organization. | Check that you mapped the right `id`, not the quote number. | | **409** `invalid_state` | The action does not apply to the current status, for example approving a draft. | Check the quote status before the action. | | **422** `idempotency_key_reused` | You used the same `Idempotency-Key` with another request. | Use a different key per operation. | | **429** | You exceeded the per-minute limit or the monthly API quota. | Add a pause between modules or reduce frequency. Check your usage in Settings › Plans & subscription; on Free, wait for the next month or upgrade. | | **"You cannot connect apps here"** when authorizing | Your user does not have the Settings permission in that workspace. | Ask someone who has it to authorize. | More in [API errors](/en/docs/desarrolladores/esenciales/errores). ## Related - [Zapier](/en/docs/automatizacion/integraciones/zapier) - [n8n](/en/docs/automatizacion/integraciones/n8n) - [Integrations and the API quota](/en/docs/automatizacion/integraciones#integrations-and-the-api-quota) - [Developer integrations guide](/en/docs/desarrolladores/herramientas/integraciones) --- # n8n URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/n8n Last updated: 2026-10-10 How to connect n8n with Cord using the n8n-nodes-cord node or the HTTP Request node: requirements, API key credential, the trigger's 41 events, the node's operations, what flows each way, API quota per plan, how to disconnect and common issues. ## What it does n8n connects to Cord in two ways. The **Cord node** (`n8n-nodes-cord`) is the short path: it brings a trigger, **Cord Trigger**, that starts your flow when something happens in Cord, and an actions node, **Cord**, that creates and looks up clients, quotes and tasks. The **HTTP Request node** covers any [API](/en/docs/desarrolladores/empezar/resumen) endpoint the node does not yet include. n8n uses a Cord **API key**, not the one-click authorization of Zapier and Make: each n8n installation has its own return address, and Cord only accepts addresses registered in advance. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission to turn on developer mode and create a secret key with write permission. Any plan. | | **n8n** | Your own n8n 1.x installation and admin rights to install community nodes. On n8n Cloud the node will appear once n8n finishes verifying it. | | **Network** | A public `https` address for your n8n: Cord does not deliver events to `http`, `localhost` or internal or private addresses. | | **Quota** | Every node operation uses calls from your Cord plan's monthly API quota. See [Limits](#limits). | ## Connect with the Cord node 1. In n8n, go to **Settings › Community nodes** and install `n8n-nodes-cord`. 2. In Cord, go to **Settings**, turn on developer mode at the end of the index and open **API**. Create a secret key with write permission; keys starting with `sk_test_` work against your test environment. The key is shown only once. 3. In n8n, create a **Cord API** credential and paste the key. The test button confirms the key works. 4. Add the **Cord Trigger** node, pick the events and activate the flow: n8n registers the webhook in Cord and deletes it when you deactivate the flow. 5. To act on Cord, use the **Cord** node. ## The trigger: Cord Trigger In **Events** you choose one or more of Cord's 41 events. Cord only sends the ones you chose, and the node verifies the `X-Cord-Signature-V1` signature of every delivery with the secret it received when registering the webhook (**Verify Signature**, on by default): a POST that does not come from Cord is rejected. | Category | Event in n8n | Key | When it happens | |---|---|---|---| | Quotes | Quote created | `quote.created` | A quote is created. | | Quotes | Quote sent | `quote.sent` | A quote is sent. | | Quotes | Client opened a quote | `quote.viewed` | The client opens the quote. | | Quotes | Quote approved | `quote.approved` | A quote is approved. | | Quotes | Quote rejected | `quote.rejected` | A quote is rejected. | | Quotes | Quote edited and resent | `quote.updated` | A quote is edited and resent. | | Quotes | Quote expired | `quote.expired` | A quote expires. | | Quotes | Draft deleted | `quote.deleted` | A draft is deleted. | | Quotes | Message posted on a quote | `quote.comment_added` | A message is posted on a quote. | | Approvals | Internal approval requested | `quote.approval_requested` | A quote requests internal approval. | | Approvals | Internal approval decided | `quote.approval_decided` | An internal approval is decided. | | Payments | Quote paid in full | `quote.paid` | A quote is paid in full. | | Payments | Partial payment received | `payment.partial` | A partial payment arrives. | | Payments | Recurring charge failed | `payment.failed` | A recurring charge fails. | | Payments | Dispute opened | `dispute.created` | A dispute is opened. | | Payments | Dispute closed | `dispute.closed` | A dispute is closed. | | Payments | Refund succeeded | `refund.succeeded` | A refund succeeds. | | Payments | Refund failed | `refund.failed` | A refund fails. | | Payments | Payout paid | `payout.paid` | A payout is paid to your bank. | | Payments | Payout failed | `payout.failed` | A payout fails. | | Payments | Payments account updated | `account.updated` | Your payments account changes. | | Invoices | Quote invoiced | `invoice.issued` | A quote is invoiced. | | Invoices | Quote CFDI stamped | `invoice.stamped` | A quote CFDI is stamped. | | Invoices | Invoice issued | `invoice.finalized` | An invoice is issued. | | Invoices | Invoice sent | `invoice.sent` | An invoice is sent. | | Invoices | Invoice paid | `invoice.paid` | An invoice is paid. | | Invoices | Invoice payment failed | `invoice.payment_failed` | An invoice payment fails. | | Invoices | Invoice overdue | `invoice.overdue` | An invoice becomes overdue. | | Invoices | Invoice voided | `invoice.voided` | An invoice is voided. | | Invoices | Invoice marked uncollectible | `invoice.marked_uncollectible` | An invoice is marked uncollectible. | | Clients | Client created | `client.created` | A client is created. | | Clients | Client updated | `client.updated` | A client is updated. | | Clients | Client deleted | `client.deleted` | A client is deleted. | | Products | Product created | `product.created` | A product is created. | | Products | Product updated | `product.updated` | A product is updated. | | Products | Product deleted | `product.deleted` | A product is deleted. | | Tasks | Task created | `task.created` | A task is created. | | Tasks | Task completed | `task.completed` | A task is completed. | | Tasks | Payment promise recorded | `promise.created` | A payment promise is recorded. | | Tasks | Payment promise kept | `promise.kept` | A payment promise is kept. | | Tasks | Payment promise broken | `promise.broken` | A payment promise is broken. | Cord Workflows' time-based triggers (upcoming due dates and invoices past due for days) and the scheduled trigger do not exist in n8n: use n8n's **Schedule Trigger** node and the **Cord** node's searches to build them. The fields each event carries are in [Webhooks for developers](/en/docs/desarrolladores/herramientas/webhooks). If you change the events of a **Cord Trigger** that is already active, the node filters out the ones you removed even if Cord keeps sending them; for Cord to stop sending them, deactivate and activate the flow again. ## The actions: the Cord node | Resource | Operation | Fields | |---|---|---| | **Client** | Create | **Company** (required). Optional: Contact, Email, Phone, Tax ID, Country Code and Payment Terms (Upfront, Net 7, Net 15, Net 30, Net 45, Net 60, or Net 90; Net 7, Net 15, Net 45, and Net 90 from node version 1.2.0). | | **Client** | Update | **Client ID** and the fields you want to change. | | **Client** | Get | **Client ID**. | | **Client** | Search | Text or email to look for. | | **Quote** | Create | **Client ID** and **Items** (Description, Quantity, Unit Price). Optional: Currency, Payment Terms, Valid For (Days), Notes and **Send Now** to send it when it is created. | | **Quote** | Get | **Quote ID**. | | **Quote** | Search | Quote number or client to look for. | | **Quote** | Send | **Quote ID** of a draft. | | **Quote** | Mark as Paid | **Quote ID** and, optionally, **Payment Method**. | | **Task** | Create | **Title**. Optional: Due Date and Quote ID to link it to a quote. | The **Cord** node can also be used as a tool by an AI agent inside n8n. ## With the HTTP Request node 1. To receive events, add a webhook in the **Webhooks** tab of the Workbench with the URL of the n8n **Webhook** node and choose the events. 2. To call the API, use **HTTP Request** against `https://cordhq.app/api/v1/...` with the header `Authorization: Bearer sk_...`. 3. Add the `Idempotency-Key` header with a unique value per operation when you create data, so a retry does not duplicate it. With the generic **Webhook** node you verify the signature yourself; details are in [Webhooks for developers](/en/docs/desarrolladores/herramientas/webhooks). ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to n8n** | The events you chose in **Cord Trigger**, signed, with `id`, `event`, `created_at` and `data`. | Instantly, every time it happens in Cord. If n8n does not respond, Cord retries the delivery. | | **From n8n to Cord** | Whatever the **Cord** node or your **HTTP Request** does: clients, quotes, recorded payments or tasks. | When the flow runs. | What n8n does in Cord fires the same events as if a person had done it, with **Who caused it: The API**. If a flow listens to an event and also causes it, watch out for loops: filter by the field that changed or by the actor. ## Limits | Limit | Value | |---|---| | API calls per month | Free 100, Starter 1,000, Pro 5,000, Scale 10,000, Developer 50,000 | | When you go over the quota | On Free, calls are rejected until the next month; from Starter they are billed as overage, with a safety cap of 10 times what is included | | Active API keys | Free 2, Starter 5, Pro 20, Scale 50, Developer 200 | | Webhooks registered by **Cord Trigger** | 100 per organization, shared with Zapier and Make, separate from your plan's endpoints | | Webhooks you create by hand (HTTP node) | Your plan's: 16 on Free, Starter and Pro; 32 on Scale; 100 on Developer | - **What uses quota:** every **Cord** node operation and every **HTTP Request** call with an `sk_live_…` key, plus registering or removing the webhook when you activate or deactivate a flow with **Cord Trigger**. Receiving events does not use quota, and neither does an `sk_test_…` key. - **How much you have used:** in **Settings › Plans & subscription › Subscription**, **API calls** row. ## Disconnect - **Turn off a flow:** when you deactivate a flow with **Cord Trigger**, n8n deletes the webhook it had registered in Cord. If the webhook no longer existed in Cord, n8n deactivates anyway. - **Cut access completely:** 1. In Cord, open the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). 2. Find the key you pasted into n8n and click **Revoke**. Confirm: it stops working immediately and cannot be undone. 3. In n8n, delete the **Cord API** credential. Once the key is revoked, n8n can no longer call the API with it, and the webhooks that key had registered stop receiving events. - **With the HTTP Request node:** also delete the webhook in the **Webhooks** tab of the Workbench. ## Common issues | Message or symptom | What to do | |---|---| | **The credential test fails** | Paste a secret key (`sk_live_` or `sk_test_`). Publishable keys (`pk_`) do not work here. If the key was revoked, create another one. | | **The flow with Cord Trigger does not activate** | The key needs write permission to register the webhook. Also check that the n8n address is public `https`: Cord rejects `http`, `localhost` and internal or private addresses. | | **Cord says your integrations reached the maximum of 100 subscriptions per organization** | Deactivate the n8n flows, Zaps or scenarios you no longer use to free up space. | | **n8n answers 401 to Cord's deliveries** | The trigger rejects deliveries whose signature does not match the secret it received when registering the webhook. Deactivate and reactivate the flow so it registers a new one. | | **The Cord node returns 429** | You went over the per-minute limit or the monthly API quota. Check your usage; on Free, wait for the next month or upgrade. | | **You cannot create the key** | You reached your plan's maximum of active keys. Revoke one you no longer use. | ## Related - [Zapier](/en/docs/automatizacion/integraciones/zapier) - [Make](/en/docs/automatizacion/integraciones/make) - [API keys](/en/docs/desarrolladores/empezar/apikey) - [Webhooks for developers](/en/docs/desarrolladores/herramientas/webhooks) - [Integrations and the API quota](/en/docs/automatizacion/integraciones#integrations-and-the-api-quota) --- # QuickBooks Online URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/quickbooks Last updated: 2026-10-07 How to connect QuickBooks Online with Cord: what it creates in your accounting (customer, invoice and the Cord service), how payments travel both ways, what it does not do yet, duplicate guarantees and common issues. This feature is new and may not be enabled on your account yet. If you do not see it, write to us. ## How it works Every invoice you issue in Cord shows up in your accounting with its customer, lines and currency. You stop entering the same thing twice. **QuickBooks has no drafts**: what goes in is recorded in your books. That is why Cord only sends invoices that are already **final** on its side. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. Invoices issued in Cord: drafts do not travel. | | **QuickBooks** | A company in **QuickBooks Online** and a user who administers it. QuickBooks Desktop cannot be connected. | | **Taxes** | In your QuickBooks, a tax code for every rate you use in Cord, or automated sales tax in the United States. | ## Connect 1. Go to **Settings › Integrations › QuickBooks Online**. You need the **Settings** permission. 2. Click **Connect QuickBooks** and authorize with the account that manages your company. 3. When you come back you see the connected company's name. From then on, each new invoice travels on its own. 4. If you already had invoices, click **Send the pending invoices** to send the latest 50 missing ones. ## What it creates in your accounting | Record | Detail | |---|---| | **Customer** | If it does not exist. Cord looks it up by email first, then by name, so it does not duplicate it, and remembers the link for later invoices. | | **Invoice** | Date, due date, currency and one line per item with the negotiated price and its discount applied. | | **"Cord" service** | Created once. QuickBooks requires every sales line to hang from a product; Cord uses one instead of filling your catalog. | | **Private note** | Holds the Cord number. The invoice number belongs to your accounting and Cord does not overwrite it. | | **Payment** | One for each payment on an invoice already in QuickBooks. See [Payments](#payments). | ## Payments Payments travel both ways, only for invoices already in QuickBooks: - **From Cord to QuickBooks.** Every payment on an invoice already in QuickBooks is recorded there as a payment against that invoice, in **Undeposited Funds**. It happens when the payment is recorded in Cord, and also when an invoice that already had payments is posted. - **From QuickBooks to Cord.** A payment you record in QuickBooks against a Cord invoice marks it in Cord, with QuickBooks as the method. Cord checks once a day, and also when you click **Send the pending invoices**. If a QuickBooks payment covers several invoices, Cord takes only the part applied to each one. A payment is never recorded twice and never bounces back: what came in from QuickBooks is not sent there again. QuickBooks does not ask for a new permission for this. ## What it does not do yet - **Invoices with withholdings are not sent.** QuickBooks does not record them on a sales invoice; post them by hand. - **It only brings payments from your accounting into Cord.** Customers, products and invoices created in QuickBooks do not come into Cord. ## Taxes Each line enters with the QuickBooks tax code whose rate matches Cord's. In the United States, where QuickBooks computes sales tax itself, Cord sets the invoice's total tax so it is not recalculated. If QuickBooks ends up with a total different from Cord's, the invoice is deleted and the card tells you. ## Guarantees - **An invoice is never sent twice.** Cord remembers which invoice was recorded and does not repeat it, even if the event is retried. - **Only final invoices travel.** Never a quote or a Cord draft. - **Each line amount is computed on the already-rounded price**, so the total matches Cord to the cent. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to QuickBooks** | The customer (if it does not exist), the final invoice with its lines, tax and currency, and the "Cord" service the first time. | When the invoice is issued or sent in Cord, and when you click **Send the pending invoices**. | | **From Cord to QuickBooks** | Every payment on an invoice that is already in QuickBooks, as a payment to **Undeposited Funds**. | When the payment is recorded in Cord. | | **From QuickBooks to Cord** | Payments you record there against a Cord invoice, with QuickBooks as the method. | Once a day and when you click **Send the pending invoices**. | | **From QuickBooks to Cord** | Nothing else: customers, products and invoices created in QuickBooks do not come into Cord. | — | ## Limits | Limit | Value | |---|---| | Companies per organization | One | | **Send the pending invoices** | Up to 50 missing final invoices, and up to 3 times every 5 minutes | | Invoices per Cord document | One, even if the event repeats | | Invoices with withholdings | Not sent | | Payments coming from QuickBooks | Checked once a day | ## Disconnect With **Disconnect** on the card. What was already recorded stays in your accounting. If you connect a different company or organization, Cord starts from scratch with it instead of reusing the previous one. ## Common issues | Message or symptom | What to do | |---|---| | **The card asks you to reconnect** | QuickBooks expired or revoked access. Reconnect; missed invoices go out with **Send the pending invoices**. | | **"0 invoices sent"** | There are no pending final invoices, or they were all already recorded. | | **"Your accounting has no … sales tax rate"** | Create a QuickBooks tax code with that exact rate and click **Send the pending invoices**. In the United States, turn on automated sales tax. | | **"The total did not match"** | QuickBooks computed a different total and Cord deleted the invoice instead of leaving it posted wrong. Check that the rate is the same on both sides. | ## Related - [Xero](/en/docs/automatizacion/integraciones/xero) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Invoicing by country](/en/docs/pagos/facturacion) - [Google Sheets](/en/docs/automatizacion/integraciones/google-sheets), if you only need the list of invoices in a spreadsheet. --- # Shopify URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/shopify Last updated: 2026-10-10 How to connect Shopify with Cord: catalog and customers into Cord, the order back to your store when the quote closes, currencies, inventory, taxes and common issues. ## How it works With Shopify connected, your catalog and customers come into Cord and stay current. You quote wholesale with the prices and SKUs you already have, and when the quote closes, Cord can create the order in your store so fulfillment and inventory live there. **Cord reads your store and writes only what you turn on.** Products and customers come in on their own; orders start switched off. Cord never changes prices or edits your catalog. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan, but the products and customers that come in count against your plan's limit: 50 and 50 on Free, 500 and 500 on Starter, no limit from Pro. | | **Shopify** | A store and a user who can install apps on it. The domain ending in `myshopify.com`. | | **B2B prices** | A store with Shopify B2B, which is available on Shopify Plus. | | **Orders in another currency** | Your store must have that currency enabled in **Shopify › Settings › Markets**. | ## Connect 1. Go to **Settings › Integrations › Shopify**. You need the **Settings** permission. 2. Enter your store domain ending in `myshopify.com` (Shopify › Settings › Domains). 3. Click **Connect Shopify** and authorize the app. Shopify shows the permissions: read products and customers, and create orders when you enable it. 4. When you come back, the first sync takes a few minutes depending on catalog size. ## What comes into Cord | Data | How it arrives | |---|---| | **Products** | Each **variant** is a Cord product, with its own price and SKU. A shirt in three sizes arrives as three products. | | **Status** | Active if the product is active in Shopify. An **out-of-stock product stays active**: it can still be quoted. A draft or archived product arrives inactive. | | **Customers** | The company comes from the customer's company in Shopify; if there is none, from the person's name. An email already in Cord is not duplicated. | | **Deletions** | A product deleted in Shopify is **deactivated** in Cord, not deleted: it may be in a quote already sent. | Changes in Shopify arrive within seconds. **Sync now** rereads the whole catalog. ## The order back to your store On the Shopify card you choose when the order is created. **It starts off**: | Option | What happens | |---|---| | **Do not create orders** | Default. | | **When the quote is approved** | The order is created as a draft in Shopify, ready to fulfill or collect there. | | **When the client pays** | Cord collects and the order enters your store marked as paid. | - Each line with one of your store's products travels as that variant and reduces inventory; a free-form line travels as an item with its price. - The price that travels is the **negotiated** one, with its line discount applied. The [document discount or a coupon](/en/docs/cotizacion/descuentos) does **not** travel to the order: if the quote carries one, the Shopify order ends up above its total, so adjust it in Shopify before fulfilling or collecting from there. - The order carries the `cord` tag and the quote number in a note. - A quote produces **a single order**, even if the event repeats. ### Currencies - If the quote is in your store's currency, the order is created as usual. - If it is in **another currency your store has enabled** in its markets, the order is created in that currency with the quote's exact price. - If your store **does not sell** in that currency, no order is created: the quote says so in its history and tells you to enable it under **Shopify › Settings › Markets**. Cord never makes up an exchange rate. ### Taxes The order's tax is computed by Shopify with your store settings. The tax document that counts is Cord's. ## Stock while quoting This feature is new and may not be enabled on your account yet. If you do not see it, write to us. If your store tracks a product's inventory, Cord brings its stock. In the quote editor, search shows how many are available and, when you add the product, Cord asks your store at that moment. If you quote more than is available, the line says so ("Only 12 in stock"), and an out-of-stock product says **Out of stock**. Quoting more is not blocked: selling something to be restocked is normal. ## B2B prices per client This feature is new and may not be enabled on your account yet. If you do not see it, write to us. If your store uses **Shopify B2B** (available on Shopify Plus), each company buys with its catalog's price list. When you quote a Cord client linked to a Shopify customer who buys for a company, the editor uses **their B2B list as the agreed price** of each product from your store, and the line says so: "Their B2B price list". - It takes precedence over the client's tier discount, product by product. A product without a price in the list keeps the tier discount. - It only applies if the quote is in the list's currency. - You can change any line's price by hand; from then on, what you typed wins. - When you open a saved draft, its prices are not rewritten; the list applies to products you add. ## Invoice your store orders This feature is new and may not be enabled on your account yet. If you do not see it, write to us. On the Shopify card, **Invoice your store orders** starts off. With **Create the draft when the order is paid**, every paid store order creates its draft invoice in Cord: | From the order | In the draft | |---|---| | Customer | The Cord client linked to that Shopify customer; created if it does not exist. | | Products | One line per product with its quantity and the price after the order discount. | | Shipping | One line with its cost, if any. | | Currency | The one the customer paid in. | | Tax | The order's rate if it exists in your tax catalog; otherwise your account's. | You review the draft and issue it: Cord never issues on its own, because issuing is your tax decision and, in Mexico, a stamped CFDI cannot be undone without canceling it with the SAT. An order creates **a single draft**, and orders Cord created from a quote are not invoiced here, since they already have theirs. An order without a customer (guest checkout) is not invoiced. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Shopify to Cord** | Products (one variant, one product, with price, SKU and status) and customers. | When you connect, when you click **Sync now** and within seconds every time they change in Shopify. | | **From Shopify to Cord** | Stock for a product that tracks inventory. | When syncing and when the editor asks for it as you add the product. | | **From Shopify to Cord** | The customer's B2B price list. | When you pick the client in the editor. | | **From Shopify to Cord** | A paid store order, as an **invoice draft**. | When the order is paid, if you turned on **Invoice your store orders**. | | **From Cord to Shopify** | One order per quote, as a draft or as paid. | When the quote is approved or paid, depending on what you chose. It starts off. | | **From Cord to Shopify** | Nothing else. Cord never changes your store's prices, products, customers or inventory directly. | — | What you change in Cord on a product or a customer that came from Shopify does not go back to the store. If that product or customer later changes in Shopify, Shopify's data replaces yours. A customer you delete in Shopify stays in Cord. ## Limits | Limit | Value | |---|---| | Stores per organization | One | | **Sync now** | Up to 3 times per hour | | One full sync | Up to 2,000 products (with up to 100 variants each) and up to 4,000 customers; later changes arrive through Shopify's notifications | | Products and customers in Cord | Your plan's: 50 and 50 on Free, 500 and 500 on Starter, no limit from Pro | | Orders per quote | One, even if the event repeats | | Invoice drafts per order | One; orders without a customer are not invoiced | ## Disconnect With **Disconnect** on the card. Products and customers already in Cord stay and stop updating. If you uninstall the app from Shopify, Cord detects it and marks the connection as disconnected. ## Common issues | Message or symptom | What to do | |---|---| | **"Enter your store domain"** | Use the one ending in `myshopify.com`, not your own domain. | | **"We could not verify the response came from Shopify"** | Start again from Cord, not from a saved link. | | **The card asks you to reconnect** | Someone uninstalled the app or changed its permissions. Connect it again. | | **No order was created** | Check the quote's history: it says whether it was the currency, a missing permission or a Shopify rejection. | ## Related - [Products and pricing](/en/docs/cotizacion/productos) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas): issue the draft created from a store order. - [Integrations](/en/docs/automatizacion/integraciones) --- # Slack URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/slack Last updated: 2026-10-13 How to connect a Slack channel with Cord using Add to Slack or your own webhook, turn on alerts per event, what each message contains, link previews, the /cord command, approval buttons, use Slack in workflows and fix problems. ## How it works Cord posts to Slack through an **Incoming Webhook**: an address Slack generates for a specific channel. With **Add to Slack** you pick the channel in Slack and Cord receives that address on its own. Alerts and workflow messages go only to that channel. When you authorize, Slack shows you the permissions the Cord app asks for: post to the channel you picked, see and complete Cord links pasted in your workspace (for the preview), receive the `/cord` command, and read the name and email of whoever clicks an approval button. None of them lets Cord read your messages. There are two ways to get messages, and you can use both: | | Notification alerts | Workflow action | |---|---|---| | **What it posts** | A standard message per quote event. | The text you write, with event data. | | **When** | On the events you check in Settings › Notifications. | On any of the 48 event triggers or the scheduled trigger, with conditions and waits. | | **Where to set it up** | **Settings › Notifications** | **Workflows** | ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. | | **Slack** | Being able to install apps in your workspace. If your workspace restricts installs, a Slack admin will need to approve the Cord app. | | **Approval buttons** | Internal approvals, which come with the **Scale** plan or higher, and the person clicking the button must use the same email in Slack as in Cord and have the **Approvals** permission. | ## 1. Connect your channel 1. Go to **Settings › Integrations** and tap **Slack**. 2. Click **Add to Slack**. Slack opens: pick the channel for the alerts and click **Allow**. 3. When you come back, the card says **Connected to #your-channel**. Click **Send test**: a message about a test quote "COT-PRUEBA" should appear in the channel. Slack adds an app called **Cord** to your workspace; it is the one that signs the messages. If your workspace restricts app installs, a Slack admin will need to approve it. ### Alternative: your own webhook If you prefer messages to show your own Slack app's name and icon, open **Use your own webhook** on the same card: 1. In **api.slack.com/apps** create an app from scratch, open **Incoming Webhooks**, turn them on and click **Add New Webhook to Workspace** to pick the channel. 2. Copy the URL (it starts with `https://hooks.slack.com/services/`), paste it in Cord and click **Save**. 3. Click **Send test**. The test uses the saved URL, not the one typed in the field. ## 2. Turn on the alerts Connecting Slack **does not turn on any alert by itself**. Go to **Settings › Notifications** and check the Slack column for the events you want: | Event | When it alerts | |---|---| | **Your client viewed the quote** | When the client opens the public link. | | **Quote approved** | The client accepted the proposal. | | **Quote rejected** | The client rejected it. | | **Payment received** | The online payment was recorded. | | **Quote about to expire** | 3 days before the validity date. | | **Overdue payment** | A receivable passed its due date. | **Someone joined the team** is email only; it has no Slack option. ## What each alert contains Each notification alert is a short message with: - The quote **number** and what happened (viewed, approved, rejected, paid, about to expire, overdue). - The **client** and the **total** with its currency. - A link that opens the quote in Cord. Notification alerts are about quotes: an event without a quote number is not posted to Slack. Alerts are written in your account's language (Spanish or English, as set in Settings › General). ## Previews, the /cord command and approvals This feature is new and may not be enabled on your account yet. If you do not see it, write to us. With **Add to Slack**, the Cord app also does this in your workspace: - **Link previews.** A public quote link pasted in Slack opens as a card with the quote number, client, status, total and an **Open in Cord** button. It only happens with quotes from your own organization. - **The `/cord` command.** Type `/cord` and a quote number or a client name, for example `/cord COT-0152`. Only you see the answer, with up to 5 quotes. - **Approval buttons.** When a quote requests internal approval, it reaches the channel with **Approve**, **Reject** and **Open in Cord** buttons. The buttons only work if your Slack account uses the same email as your Cord account and you have the **Approvals** permission; otherwise Slack tells you to decide from Cord. Internal approvals require the **Scale** plan or higher. If you connected Slack before these existed, the card asks you to reconnect: click **Change channel** and authorize again. They are not available with your own webhook. ## Custom messages with workflows With the **Send a Slack message** action in [Cord Workflows](/en/docs/automatizacion/workflows/acciones) you write the message, with event data, and decide when it goes out. Examples: - When a deposit arrives: "`{{cliente}}` paid the deposit for `{{folio}}`: `{{monto}}`. Balance: `{{saldo_pendiente}}`." - When a dispute is opened: "Dispute on `{{folio}}` for `{{monto}}`. Respond before `{{fecha_limite}}`." - When a large sale is approved, only if the total passes a certain amount. This action posts to the same channel and works even if notification alerts are off. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to Slack** | The alerts you check in Notifications: quote number, what happened, client, total with its currency and the **View quote** link. | When the event happens. | | **From Cord to Slack** | The text you write in a workflow's **Send a Slack message** action. | When the workflow runs. | | **From Cord to Slack** | The preview card for a quote link from your organization, and the `/cord` reply, which only the person who typed the command sees. | When someone pastes the link or uses the command. | | **From Slack to Cord** | The decision from the **Approve** or **Reject** buttons on an internal approval request. | When someone with permission clicks the button. | | **From Slack to Cord** | Nothing else. Cord does not read the messages in your channels. | — | ## Limits | Limit | Value | |---|---| | Channels per organization | One at a time, the one you picked when connecting | | Messages from workflows | 120 per hour per organization | | Length of a workflow message | 1,000 characters | | `/cord` results | Up to 5 quotes | | Link previews | Only quotes from your own organization | | Notifications alerts | Only quote events with a quote number | ## Change channel or disconnect - **Change channel:** click **Change channel** on the card and pick another one in Slack. With your own webhook, create another one in Slack and paste the new URL. - **Disconnect:** click **Disconnect** on the card (with your own webhook, clear the URL and save). Cord stops posting and the status goes back to **Not connected**. Workflows with the Slack action will start failing with a message asking you to connect Slack. - **Revoke from Slack:** if you delete the webhook or the app in Slack, the URL stops working immediately, even if it is still saved in Cord. Cord can post to **one channel** at a time. For alerts in several channels, one option is [Make](/en/docs/automatizacion/integraciones/make) with Cord webhooks. ## Problems | Message | Cause | What to do | |---|---|---| | The URL must be from hooks.slack.com | You pasted another URL, such as the channel or app URL. | Copy the Incoming Webhook URL, the one starting with `https://hooks.slack.com/`. | | There is no Slack webhook connected. Paste the URL and save first. | You clicked **Send test** without saving. | Click **Save**, then test. | | Slack did not accept the message. Check the webhook URL. | Slack rejected the message: the webhook was deleted, the app removed or the URL is incomplete. | Create a new webhook and paste the full URL. | | Could not send | Network error while testing. | Try again. | | The test arrives but alerts do not | The events do not have Slack checked. | Check **Settings › Notifications**. | Treat the webhook URL like a password: anyone who has it can post to your channel. If you think it leaked, delete it in Slack and create a new one. ## Related - [Microsoft Teams](/en/docs/automatizacion/integraciones/teams) - [Notifications](/en/docs/gestion/notificaciones) - [Workflow actions](/en/docs/automatizacion/workflows/acciones) - [Ready-made ideas](/en/docs/automatizacion/workflows/ideas): with Slack connected, their team alerts go out through Slack. --- # Microsoft Teams URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/teams Last updated: 2026-10-07 How to connect Microsoft Teams with Cord by signing in with Microsoft or with a Power Automate flow: requirements, what flows and in which direction, alerts per event, Teams in workflows, approval requests, limits, how to disconnect and common issues. ## What it does Cord posts a card to the Teams channel you choose when a quote moves forward, when a quote requests internal approval and when one of your workflows says so. There are two ways to connect it, and only one can be active at a time: | | Connect with Microsoft | Power Automate flow | |---|---|---| | **How** | Sign in with your work account and pick team and channel from the lists. | Create a flow in the channel and paste its URL. | | **Who posts** | The card is posted as whoever connected; Cord's card says so ("Alerts are posted as…"). | The channel's flow. | | **Requirement** | A Microsoft 365 work or school account (channels do not exist in personal accounts). | Being able to create flows in the channel. | | **Status** | New feature | Available | ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. | | **Microsoft 365** | A work or school account with Teams. Personal Microsoft accounts have no channels. | | **Teams** | With **Connect with Microsoft**, being a member of the team and channel to post to. With Power Automate, being able to create flows in that channel. | | **Your Microsoft organization** | If it does not let each person authorize apps on their own, a Microsoft 365 administrator will need to approve the Cord app. | ## Connect with Microsoft This feature is new and may not be enabled on your account yet. If you do not see it, write to us. 1. Go to **Settings › Integrations › Microsoft Teams**. 2. Click **Connect with Microsoft** and sign in with your work account. 3. Pick the **team** and **channel** from the lists and click **Use this channel**. 4. Click **Send test**: a sample card appears in the channel. Cord asks to read your profile, the teams and channels you belong to, and to send channel messages. It does not ask to read the channel's messages. Microsoft may show a notice that the app's publisher is unverified while Microsoft finishes that verification. ## With a Power Automate flow Teams' old connectors (Office 365 "Incoming Webhook") are retired; the URL comes from a flow. 1. In the channel, open **Workflows** from the three-dot menu. 2. Use the template **"Post to a channel when a webhook request is received"** and pick team and channel. 3. Copy the flow URL (it starts with `https://prod-` and ends in `logic.azure.com`). 4. In Cord, open **Use a Power Automate flow** on the Teams card, paste the URL, click **Save** and then **Send test**. The URL is a credential: anyone who has it can post to your channel. If it leaks, delete the flow and create another. ## What flows and in which direction Teams is an **outbound** integration: Cord posts to your channel and reads nothing from Teams. | Direction | What flows | When | |---|---|---| | **From Cord to Teams** | One card per alert you check in Notifications: quote number, client, total with its currency and a link to the quote. | When the event happens. | | **From Cord to Teams** | The card of an internal approval request, with the **Decide in Cord** button. | When the approval is requested. | | **From Cord to Teams** | The text you write in a workflow's **Send a Teams message** action. | When the workflow runs. | | **From Teams to Cord** | Nothing. Replying in the channel or reacting to the card changes nothing in Cord. | — | ## Turn on alerts Connecting turns on no alerts. In **Settings › Notifications**, check the **Teams** column for the events you want: | Event | When it fires | |---|---| | **Your client viewed the quote** | When the client opens the public link. | | **Quote approved** | The client accepted the proposal. | | **Quote rejected** | The client rejected it. | | **Payment received** | An online payment was recorded. | | **Quote expiring** | 3 days before the valid-until date. | | **Payment overdue** | A receivable passed its due date. | Email, Slack and Teams are checked separately: you can have one event in Teams and another only by email. ## Teams in a workflow The **Send a Teams message** action in [Cord Workflows](/en/docs/automatizacion/workflows/acciones) posts your own text with event data (`{{cliente}}`, `{{folio}}`, `{{total}}`), even if alerts are off. Use it to post only in some cases (a large sale, a deposit, a dispute) or with your own text. With Teams connected (and Slack not), the [ready-made ideas](/en/docs/automatizacion/workflows/ideas) alert the team through Teams instead of by email. ## Approval requests When a quote requests internal approval, Cord posts a card in the connected channel with the quote number, client, total and a **Decide in Cord** button. The decision is made in Cord: the Teams card has no buttons to approve or reject. Internal approvals require the **Scale** plan or higher. ## Limits | Limit | Value | |---|---| | Destinations per organization | One channel at a time. Picking a channel with Microsoft clears the flow URL, and saving a flow disconnects the Microsoft account. | | Messages from workflows | 120 per hour per organization | | Length of a workflow message | 1,000 characters | | Tests from Settings | 10 per minute | | Posted as | With **Connect with Microsoft**, always the person who connected. If they leave the company or lose access to the channel, someone else must reconnect. | If you want alerts in several channels, one option is to use [Make](/en/docs/automatizacion/integraciones/make) or [Zapier](/en/docs/automatizacion/integraciones/zapier) with Cord's events. ## Disconnect **If you connected with Microsoft:** 1. In **Settings › Integrations › Microsoft Teams**, click **Disconnect**. 2. Cord deletes its access to your account and stops posting. 3. If you also want to remove the Cord app from your Microsoft account, do it at myapps.microsoft.com: Microsoft does not allow revoking a single access from outside. **If you use a Power Automate flow:** open **Use a Power Automate flow**, clear the URL and click **Save**. To cut access completely, turn off or delete the flow in Teams. Once disconnected, Teams alerts from Notifications stop and workflows with the Teams action fail with "Connect Microsoft Teams in Settings › Integrations to use this action." until you connect again. ## Common issues | Message or symptom | What to do | |---|---| | **"Microsoft no longer accepts the connection"** | Access expired or was revoked. Click **Reconnect**. | | **"Your account is not a member of any team"** | Your account is not in any Teams team, or it is a personal account. Sign in with your work account. | | **"That channel is no longer available in your account. Pick another one."** | The channel was deleted or you are no longer a member. Click **Change channel**. | | **Microsoft asks for an administrator's approval** | Your organization does not let each person authorize apps. Ask a Microsoft 365 administrator to approve it, or use a Power Automate flow. | | **"The Teams URL must be the one from the channel's Power Automate flow"** | You pasted another address; it must end in a `logic.azure.com` domain. | | **"Teams did not accept the card"** | The flow was turned off or deleted, or the channel no longer exists. Turn it on in Teams Workflows, paste a new URL or pick another channel. | | **The test arrives but alerts do not** | The events do not have Teams checked. Check **Settings › Notifications**. | ## Related - [Slack](/en/docs/automatizacion/integraciones/slack) - [Microsoft Excel](/en/docs/automatizacion/integraciones/excel): uses the same Microsoft sign-in, with its own permission. - [Notifications](/en/docs/gestion/notificaciones) - [Workflow actions](/en/docs/automatizacion/workflows/acciones) --- # WhatsApp Business URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/whatsapp Last updated: 2026-10-13 How to connect your WhatsApp Business number with Cord: Meta requirements (app, sending number, approved template and token), connecting step by step, variables with event data, outbound-only direction, limits, how to disconnect and common issues. ## What it does With WhatsApp connected, the **Send the client a WhatsApp** action in [Cord Workflows](/en/docs/automatizacion/workflows/acciones) sends your approved template to the phone of the document's client, with event data in its variables: a payment reminder before the due date, a heads-up that a quote is about to expire, a deposit confirmation. Cord sends WhatsApp through **Meta's Cloud API** and with **your** account: messages come from your number and Meta charges the conversation to your account, not Cord. Meta does not allow starting a conversation with free text, only with an **approved template**. That is why Cord asks for your template's name and fills in its variables; there is no free-text message field because Meta would reject it. Without connecting anything, **Collections** (the **Remind via WhatsApp** button) and each client's page have a button that opens WhatsApp on your phone or computer with the message ready, for you to send. That button does not use this integration: this page is for Cord to send the message on its own, from a workflow. The ready message from **Collections** comes out in each client's document language. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. | | **Meta for Developers** | An app with the **WhatsApp** product and your sending number added. That is where the **phone number ID** (digits only) comes from. | | **WhatsApp Manager** | A **message template approved** by Meta, with up to 4 variables (`{{1}}` to `{{4}}`). Note its exact name and language. | | **Token** | A **permanent access token** from your Meta account with permission to send messages from that number. A token that expires stops working and messages start failing. | | **Your clients** | A phone number saved **with its country code** (`+52 55 1234 5678`). Cord does not guess the country: the same number exists in several. | | **Cost** | Meta charges each template-initiated conversation to your Meta account, based on the recipient's country. Cord does not charge for messages. | ## Connect 1. In [Meta for Developers](https://developers.facebook.com), create a **WhatsApp Business** app and add your sending number. 2. In **WhatsApp Manager**, create a template and submit it for approval. Example: `Hi {{1}}, your invoice {{2}} for {{3}} is due on {{4}}. You can pay it from the link we emailed you.` 3. Copy the **phone number ID** (digits only) and generate a **permanent access token**. 4. In Cord, go to **Settings › Integrations › WhatsApp Business** and fill in **Phone number ID**, **Access token**, **Template name** (lowercase, without spaces or accents, as it appears in Meta) and **Template language** (for example `es_MX` or `en_US`). 5. Click **Save** and then **Send test** to your own number, with the country code. The token is stored encrypted and never shown again; the card only says "A token is saved". To change the template, leave the token field empty and save: Cord keeps the one it already had. ## Use it in a workflow The **Send the client a WhatsApp** step has up to **4 variables**, up to 200 characters each. Each variable fills `{{1}}`, `{{2}}`… of your template in order, and accepts event data: `{{cliente}}`, `{{folio}}`, `{{numero}}`, `{{total}}`, `{{saldo}}`, `{{vence}}`. Line breaks inside a variable become spaces. The template arrives in the language Meta approved it in, the same for all your clients: your organization uses a single template, so it doesn't follow each client's [document language](/en/docs/gestion/clientes#document-language). If your clients speak several languages, the **Email the client** action does send the email in each one's language. With the example template, in a workflow with the **An invoice is about to be due** trigger: | Step variable | Value | Arrives as | |---|---|---| | Variable 1 | `{{cliente}}` | Lone Star Supply | | Variable 2 | `{{numero}}` | F-00231 | | Variable 3 | `{{saldo}}` | $12,500.00 | | Variable 4 | `{{vence}}` | 2026-10-10 | The phone number comes from the document's client, never from a field in the step: a workflow cannot message a number that is not your client's. ## What flows and in which direction WhatsApp is an **outbound-only** integration. | Direction | What flows | When | |---|---|---| | **From Cord to the client** | Your approved template, with the variables filled in, from your number. | When the workflow step runs. | | **From the client to Cord** | Nothing. If the client replies, the reply reaches your number in Meta's tools; Cord does not read or store it. | — | That is why the template should send the client where they can act (the document link they already received by email) and your team should handle replies from the business's WhatsApp account. ## Limits | Limit | Value | |---|---| | Messages from workflows | 60 per hour per organization | | Tests from Settings | 5 per hour | | Variables per message | 4, up to 200 characters | | Sending numbers per organization | 1 | | Templates per organization | 1 (the one saved on the card) | | Cost per conversation | Charged by Meta to your account, by country | ## Disconnect 1. Go to **Settings › Integrations › WhatsApp Business**. 2. Click **Disconnect**. You will see "WhatsApp disconnected". Cord deletes the phone number ID, the token and the template, and stops sending messages. Workflows with the WhatsApp action will fail with "Connect WhatsApp in Settings › Integrations to use this action." until you connect again. Disconnecting in Cord does not revoke the token in Meta. If you want to invalidate it, also do it from your Meta account. ## Common issues | Message or symptom | What to do | |---|---| | **"The client has no phone with a country code on file."** | Edit the client and save the number with `+` and its country code. Then click **Retry** on the run. | | **"WhatsApp did not accept your template"** | Check that it is approved, that the name and language match, and that the step has the same number of variables as the template. | | **"WhatsApp did not accept the message"** | Usually the token expired or the sending number was deactivated in Meta. In a workflow, Cord retries on its own; for the test, check the token and the sending number. | | **"Connect WhatsApp in Settings › Integrations to use this action"** | The phone number ID, the token or the template name is missing. Fill them in and save. | | **"The phone number ID is digits only..."** | You pasted the phone number instead of the ID. Copy it from Meta's WhatsApp panel. | | **"The template name goes in lowercase, without spaces or accents"** | Type the name exactly as it appears in Meta, for example `payment_reminder`. | | **"The template language goes as es_MX or en_US"** | Use the language code the template was approved with. | | **The test fails but the template is approved** | **Send test** fills only `{{1}}` with the word "test". If your template does not have exactly one variable, Meta may reject the test even though the workflow works: test from a workflow with every variable. | | **A variable's text lands in another spot** | If you leave a middle variable empty (for example 2) and fill the next one, Cord does not send the empty one and the following ones shift: 3 fills `{{2}}`. Fill the variables in order, with no gaps. | ## Related - [Workflow actions](/en/docs/automatizacion/workflows/acciones) - [Ready-made ideas](/en/docs/automatizacion/workflows/ideas): in "Payment reminder 3 days before the due date", add a WhatsApp to the client next to the email reminder, or use it instead. - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones#whatsapp) - [Receivables and operating collections](/en/docs/pagos/cartera-cobranza) --- # Xero URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/xero Last updated: 2026-10-07 How to connect Xero with Cord: invoices as drafts for your accountant to approve, contacts without duplicates, tax-exclusive amounts, payments both ways and common issues. ## How it works Every invoice you issue in Cord shows up in your Xero with its contact, lines and currency. **It arrives as a draft and you approve it.** An outside system should not post to anyone's books on its own: Cord prepares the invoice and your accountant reviews it before approving. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission. Any plan. Invoices issued in Cord: drafts do not travel. | | **Xero** | An organization in Xero and a user who can give an app access to it. If you have several organizations, you pick one when authorizing. | | **Payments** | An active bank account in Xero, which you pick on the card as the **Bank account for payments**. | | **Taxes** | In your Xero, a tax rate for every rate you use in Cord. | ## Connect 1. Go to **Settings › Integrations › Xero**. You need the **Settings** permission. 2. Click **Connect Xero** and authorize. Xero asks which organization to grant access to: choose your company's. 3. When you come back you see the organization's name. From then on, each new invoice travels on its own. 4. If you already had invoices, click **Send the pending invoices** to send the latest 50 missing ones. ## What it creates in your accounting | Record | Detail | |---|---| | **Contact** | If it does not exist, looked up by email first. Cord remembers the link. | | **Sales invoice** | Type `ACCREC`, in **draft** status, with date, due date, currency, the Cord number as the reference and one line per item. | | **Amounts** | Tax exclusive (`Exclusive`), and each line with the Xero rate that matches Cord's and the tax Cord already computed. | | **Payment** | One for each payment on an invoice approved in Xero, in the bank account you choose. See [Payments](#payments). | Cord asks for Xero's granular permissions for invoices, contacts and payments (`accounting.invoices`, `accounting.contacts` and `accounting.payments`), plus reading your accounting settings (`accounting.settings.read`) to read your tax rates and bank accounts. It does not ask for bank transactions or manual journals. ## Payments This feature is new and may not be enabled on your account yet. If you do not see it, write to us. Payments travel both ways, only for invoices already in Xero: - **From Cord to Xero.** Every payment on an invoice **approved** in Xero is recorded there as a payment against that invoice, in the bank account you choose on the card (**Bank account for payments**). While the invoice is still a draft, the payment waits and goes out on the next pass, once you have approved it. - **From Xero to Cord.** A payment you record in Xero against a Cord invoice marks it in Cord, with Xero as the method. Cord checks once a day, and also when you click **Send the pending invoices**. A payment is never recorded twice and never bounces back: what came in from Xero is not sent there again. **If you connected Xero before Cord synced payments**, the card says "To sync payments, Xero needs one more permission." Click **Reconnect** and then choose the bank account. Until then, invoices keep traveling, but payments do not. ## What it does not do yet - **It does not approve the invoice.** That is deliberate: you approve it in Xero. - **Your tax arrives with its rate.** Each line carries the tax rate in your accounting that exactly matches Cord's. If that rate does not exist there, the invoice is not sent and the card tells you which one is missing: create it and click **Send the pending invoices**. - **Invoices with withholdings are not sent.** Your accounting does not record them on a sales invoice; post them by hand. - **It only brings payments from your accounting into Cord.** Contacts, products and invoices created in Xero do not come into Cord. ## Guarantees - **An invoice is never sent twice.** Cord remembers which invoice was recorded and does not repeat it, even if the event is retried. - **Only final invoices travel.** Never a quote or a Cord draft. - **Each line amount is computed on the already-rounded price**, so the total matches Cord to the cent. ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to Xero** | The contact (if it does not exist) and the final invoice, as a **draft**, with its lines, tax and currency. | When the invoice is issued or sent in Cord, and when you click **Send the pending invoices**. | | **From Cord to Xero** | Every payment on an invoice **approved** in Xero, as a payment to the chosen bank account. | When the payment is recorded in Cord; if the invoice is still a draft, once you approve it. | | **From Xero to Cord** | Payments you record there against a Cord invoice, with Xero as the method. | Once a day and when you click **Send the pending invoices**. | | **From Xero to Cord** | Nothing else: contacts, products and invoices created in Xero do not come into Cord, and approving the invoice in Xero changes nothing in Cord. | — | ## Limits | Limit | Value | |---|---| | Xero organizations per Cord organization | One | | **Send the pending invoices** | Up to 50 missing final invoices, and up to 3 times every 5 minutes | | Invoices per Cord document | One, even if the event repeats | | Invoices with withholdings | Not sent | | Payments coming from Xero | Checked once a day | | Payments to Xero | Only for invoices approved there | ## Disconnect With **Disconnect** on the card. What was already recorded stays in your accounting. If you connect a different company or organization, Cord starts from scratch with it instead of reusing the previous one. ## Common issues | Message or symptom | What to do | |---|---| | **The card asks you to reconnect** | Xero renews access every 30 minutes and revokes the previous one; if renewal fails, reconnect. | | **I cannot see the invoice** | Look for it in Xero under **Drafts**: it stays there until you approve it. | | **"To sync payments, Xero needs one more permission."** | Click **Reconnect** and authorize again. | | **"Your Xero has no active bank accounts."** | Create a bank account in Xero and come back to the card to choose it. | | **A Cord payment does not show up in Xero** | Check that the invoice is approved in Xero and that you chose the bank account for payments. | ## Related - [QuickBooks Online](/en/docs/automatizacion/integraciones/quickbooks) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Invoicing by country](/en/docs/pagos/facturacion) - [Google Sheets](/en/docs/automatizacion/integraciones/google-sheets), if you only need the list of invoices in a spreadsheet. --- # Zapier URL: https://docs.cordhq.app/en/docs/automatizacion/integraciones/zapier Last updated: 2026-10-07 How to connect the Cord app on Zapier: requirements, one-click authorization, triggers, actions and searches, what flows each way, the monthly API quota per plan, how to disconnect, Webhooks by Zapier as an alternative and common problems. ## What it does The Cord app for Zapier has **instant triggers** (a Zap starts as soon as something happens in Cord), **actions** (the Zap creates or changes data in Cord) and **searches** (the Zap finds a client or a quote before acting). It is authorized with one click on a Cord screen: you do not create or paste any key. ## Requirements | Where | What you need | |---|---| | **Cord** | The **Settings** permission in the workspace you are connecting. Any plan. | | **Zapier** | A Zapier account. What you can build (how many Zaps, how many steps) depends on your Zapier plan. | | **Quota** | Every action and search uses calls from your Cord plan's monthly API quota. See [Limits](#limits). | ## Connect the Cord app The Cord app for Zapier is shared by invitation. In **Settings › Integrations › Zapier** there is an **Open Cord on Zapier** button that goes straight to the invitation. 1. **Accept the invitation.** Click **Open Cord on Zapier** and accept. Zapier adds Cord to your apps. 2. **Create a Zap.** Choose Cord as the trigger or as an action and click **Connect**. 3. **Authorize in Cord.** A Cord screen opens where you pick the workspace and click **Authorize**. The screen says what Zapier will and will not be able to do: it cannot see passwords or card details, change your plan or manage your team. 4. **Test the Zap.** Zapier brings in a sample event so you can map the fields in the following steps. Zapier renews the access on its own. The connection shows up in Cord as Zapier's **Authorized connection**, in the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). ## What the app includes | Type | What you can do | |---|---| | **Instant triggers** | Quote created, sent, opened by the client, approved, rejected or paid; partial payment received; invoice paid; new client; or **New Event**, to pick any of Cord's 41 events. | | **Actions** | Create client, update client, create quote (with line items, currency, terms, validity and the option to send it right away), send quote, mark quote as paid and create task. | | **Searches** | Client by exact email or by name, and quote by number. | The list of the 41 events is in [Triggers](/en/docs/automatizacion/workflows/disparadores#the-same-events-outside-workflows) and in [Webhooks for developers](/en/docs/desarrolladores/herramientas/webhooks). ## What flows and in which direction | Direction | What flows | When | |---|---|---| | **From Cord to Zapier** | The event you chose, with the object's data: number, client, total, currency, status and the public link for a quote. | Instantly, every time it happens in Cord. | | **From Zapier to Cord** | Whatever the action does: a new or updated client, a new or sent quote, a recorded payment or a task. | When the Zap runs. | | **Searches** | Zapier reads a client or a quote to use it in the next step. It changes nothing. | When the Zap runs. | What an action does in Cord fires the same events as if a person had done it, with **Who caused it: The API**. If you have workflows or Zaps listening to those events, they run too. ## Limits | Limit | Value | |---|---| | API calls per month | Free 100, Starter 1,000, Pro 5,000, Scale 10,000, Developer 50,000 | | When you go over the quota | On Free, calls are rejected until the next month; from Starter they are billed as overage, with a safety cap of 10 times what is included | | Webhooks created by your Zaps | 100 per organization, separate from your plan's webhook endpoints | | Live authorized connections | 25 per app and per organization | - **What uses quota:** every action and every search (at least one call; some actions read the quote after changing it) and registering or removing the webhook when you turn a Zap on or off. Receiving events does not use quota. - **How much you have used:** in **Settings › Plans & subscription › Subscription**, **API calls** row. - Every active Zap with a Cord trigger creates its own webhook in Cord; when you turn the Zap off, Zapier removes it. ## Disconnect There are two levels, depending on whether you want to turn off one Zap or cut Zapier's access completely. **Turn off one Zap:** turn it off or delete it in Zapier. Zapier removes the webhook that Zap had created in Cord; the other Zaps keep working. **Cut Zapier's access to Cord:** 1. Go to **Settings › Integrations › Zapier** and click **View authorized connections**. The **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) opens. 2. Find Zapier's **Authorized connection** row, with the **OAuth** tag. 3. Click **Revoke** and confirm. From that moment Zapier can no longer call the API with that connection, and the webhooks its Zaps had created stop receiving events. In Zapier, Cord Zaps fail with an authorization error until you connect the account again. If you also want to remove the account from Zapier, delete it in Zapier's **My Apps**. ## Alternative: Webhooks by Zapier If you prefer not to install the app, you can connect Zapier with the generic modules. Webhooks by Zapier is a Zapier app available on its paid plans. 1. **Create the Zap.** In Zapier, choose **Webhooks by Zapier › Catch Hook** as the trigger and copy the URL it gives you. 2. **Register the endpoint in Cord.** Turn on **Developer mode** (**Your account › Preferences**), open the Workbench's **Webhooks** tab, paste the Zapier URL and save. 3. **Choose the events**, for example `quote.approved`. 4. **Send a test event.** Click **Test** on the Cord endpoint and, in Zapier, **Test trigger**. Zapier shows the fields: `event`, `data__folio`, `data__total`, `data__cliente`, and so on. 5. **Add the Zap's actions** and turn it on. Each event carries `id`, `event`, `created_at` and `data`. If you register several events on one endpoint, add a **Filter by Zapier** or **Paths** step on the `event` field. Zapier does not verify Cord's signature. Treat the Catch Hook URL as a secret; if you think it leaked, delete the endpoint in Cord and create a new Zap. Endpoints you register this way count toward your plan's webhook limit: 16 on Free, Starter and Pro; 32 on Scale; 100 on Developer. 1. In **API**, in the Developers panel, create a **secret key** with **write** scope. 2. In your Zap add **Webhooks by Zapier › Custom Request**. 3. Set **Method** (`POST`, `PATCH` or `GET`), **URL** (for example `https://cordhq.app/api/v1/clientes`), **Data** as JSON and the **Headers** `Authorization: Bearer` + your key and `Content-Type: application/json`. 4. Add the `Idempotency-Key` header with a unique value per operation (for example the ID of the record that started the Zap) so a retry does not duplicate data. The available requests are the same as in [Make](/en/docs/automatizacion/integraciones/make#what-you-can-do): find and create clients, create quotes, send, approve or mark them paid, and create tasks. The fields are in the [developer documentation](/en/docs/desarrolladores/funciones/clientes). These requests also use the monthly API quota. ## Examples - **Quote paid → Google Sheets:** **Quote Paid** trigger → Google Sheets › Create Spreadsheet Row. (If you only want the spreadsheet, the [direct Google Sheets integration](/en/docs/automatizacion/integraciones/google-sheets) does not use quota.) - **New lead in your form → client in Cord:** your form app → **Find Client** by email → if it does not exist, **Create Client**. - **Quote approved → new project:** **Quote Approved** trigger → Asana, Trello or ClickUp › Create task. ## Common problems | Message or symptom | What to do | |---|---| | **"You cannot connect apps here"** when authorizing | Your user does not have the Settings permission in that workspace. Ask someone who has it to authorize, or sign in with another account. | | **"The return address of this request does not match..."** | Start the connection again from Zapier, not from a saved link. | | **The Zap fails with an authorization error** | The connection was revoked in Cord. Connect the Cord account again in Zapier. | | **The Zap fails with 429** | You went over the per-minute limit or the monthly API quota. Check your usage in Settings › Plans & subscription; on Free, wait for the next month or upgrade. | | **Cord says your integrations reached the maximum of 100 subscriptions per organization** | Turn off the Zaps, scenarios or n8n flows you no longer use to free up space. | | **The trigger receives no events** | Check that the Zap is on and that the event happens after turning it on: a Zap does not receive earlier events. To test, cause the real event, for example by sending a quote to your own email. | ## Related - [Make](/en/docs/automatizacion/integraciones/make) - [n8n](/en/docs/automatizacion/integraciones/n8n) - [Integrations and the API quota](/en/docs/automatizacion/integraciones#integrations-and-the-api-quota) - [Cord OAuth for developers](/en/docs/desarrolladores/herramientas/oauth) --- # Cord Workflows URL: https://docs.cordhq.app/en/docs/automatizacion/workflows Last updated: 2026-10-14 What Cord Workflows is, how a workflow works inside (trigger, conditions, waits, lookups and actions), how many you can have active on each plan and where to find the guide for each piece. ## What a workflow is A workflow is a rule that watches your Cord account. When a specific event happens (a client opens a quote, a deposit arrives, an invoice becomes overdue, a dispute is opened), the workflow runs the steps you defined, in order: create a task, email your team, write to your client with your branding or on WhatsApp, close a quote that expired, approve an internal request, void an invoice, send the data to the URL you use in another tool, post to Slack or Teams, or add a note in HubSpot. The point is that follow-up does not depend on someone remembering. If your team checks by hand which quotes nobody opened, who paid the deposit or which invoices are overdue, a workflow does it for you and leaves the task ready for the right person. ## Where to find it Open **Workflows** in the app sidebar. The list shows each workflow as a card with its name, the event that starts it, its status (**Draft**, **Active** or **Paused**), how many times it ran in the last 30 days and how many of those runs failed. At the top you see how many active workflows you have against your plan limit, and the **How your automations are doing** panel with the last 30 days. Cord Workflows is for admins. You need the **Settings** permission to view, create, edit or publish workflows. People without it see "Cord Workflows is for admins" and can ask the account owner for access. ## The pieces of a workflow Each workflow reads top to bottom in the editor, in two blocks: **When this happens** (the trigger) and **Do this** (the steps). | Piece | What it does | Guide | |---|---|---| | **Trigger** | What starts the workflow: one of Cord's 48 events, or a **fixed schedule** ("every Monday at 9"). Each workflow has exactly one. | [Triggers](/en/docs/automatizacion/workflows/disparadores) | | **Condition** | Splits the flow into two branches, **If the condition is met** and **If the condition isn't met**, based on the event data. Up to 10 rules per condition, joined with "And" and "Or". | [Conditions](/en/docs/automatizacion/workflows/condiciones) | | **Multiple branches** | Follows the first of up to 5 branches whose conditions are met, or **Otherwise**. | [Conditions](/en/docs/automatizacion/workflows/condiciones#multiple-branches) | | **Wait** | Pauses the flow for some days, some hours or until a time of day (in business days or counting from a date on the document) and then continues. | [Waits](/en/docs/automatizacion/workflows/esperas) | | **Wait until...** | Waits for something to happen (the client opens, approves or pays) with a time limit of 1 to 30 days, then continues through **If it happens** or **If the time runs out**. | [Waits](/en/docs/automatizacion/workflows/esperas#wait-until-something-happens) | | **Lookup** | Brings a number from your account to use in the following steps: overdue receivables, open pipeline, what was collected, what is about to be due or the client's balance. It only reads; it never changes anything. | [Lookups](/en/docs/automatizacion/workflows/consultas) | | **For each** | Goes through a list of charges (each overdue charge, the client's, or what is due soon) and runs its steps once for each one, on its document. | [For each](/en/docs/automatizacion/workflows/por-cada) | | **Ask for approval** | Waits for a person on the team to approve or reject; they get an email and decide in Cord. Continues through **If approved** or **If rejected or time runs out**. | [Ask for approval](/en/docs/automatizacion/workflows/aprobaciones) | | **Action** | Something Cord does for you, among 16 actions: create a task, email the team or one person, email the client, remind them to pay, pause their reminders, send the client a WhatsApp, expire or invoice a quote, record a payment promise, approve an internal request, void an invoice, send the data to a URL, post to Slack, post to Teams or add a note in HubSpot. | [Actions](/en/docs/automatizacion/workflows/acciones) | | **Event data** | Values like `{{cliente}}`, `{{folio}}` or `{{total}}` that you put in your texts and that are filled in when the workflow runs, plus your business data (`{{negocio}}`, `{{hoy}}`). | [Event data](/en/docs/automatizacion/workflows/datos-del-evento) | ## How a workflow runs inside 1. **The event happens.** Someone sends a quote, the client pays, a scheduled workflow's time comes. Each event is recorded only once. 2. **Cord creates a run** for every **active** workflow whose trigger matches, with a copy of the version published at that moment. Ten quotes sent are ten independent runs. 3. **The steps run in order.** Conditions pick a branch, lookups keep their result for the following steps, and actions run with the event data already written into your texts. 4. **A wait saves the run** and resumes it when it ends. A plain wait continues during the day it ends; a **wait until...** continues as soon as what it waits for happens to the workflow's document, or when the time runs out. 5. **If an action fails**, Cord retries it on a schedule that goes from seconds to hours, never repeating an effect that already happened. If it can't, the run is **Failed** and you can retry it by hand from its history. Statuses, retries and error messages are covered in [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones). ## A complete example "Don’t let a quote go cold" is one of the ready-made ideas in Cord. It reads like this: 1. **When this happens:** a quote is sent. 2. **Wait until** the client opens or approves it, with a 2-day limit. 3. **If it happens:** create the task "Call `{{cliente}}` while `{{folio}}` is warm". 4. **If the time runs out:** email the client asking if they have questions, and wait 5 more days for a decision. 5. **If there is still no decision:** look up the client's balance and alert you with what they already owe you. Every quote you send starts its own run of this workflow, and each one checks its own quote: the one the client opened within the hour goes one way, the one nobody touched goes the other. ## How many workflows you can have | Plan | Active workflows | Drafts and paused | Runs | |---|---|---|---| | **Free** | 1 | No limit | No limit | | **Starter** | 5 | No limit | No limit | | **Pro** | No limit | No limit | No limit | | **Scale** | No limit | No limit | No limit | | **Developer** | No limit | No limit | No limit | Only **Active** workflows take up a slot. Some actions depend on more than the workflows plan: - **Email the client** uses your plan's sending quota (5 a month on Free, no limit on the other plans). - **Approve the internal request** needs internal approvals, which come with the **Scale** plan or higher. - **Slack**, **Teams**, **WhatsApp** and **HubSpot** need that app connected in **Settings › Integrations**. Maximum workflow size, hourly caps per action and what happens when you downgrade: [Limits](/en/docs/automatizacion/workflows/limites). ## Draft, published version and runs - **Draft:** what you edit. You can change it as many times as you want without affecting anything. - **Published version:** what runs. It only changes when you press **Publish** or **Publish changes**, and every publish is a new version. - **Run:** every time the event happens, Cord creates a run with a copy of the version published at that moment. If you publish changes later, runs already in progress finish with the version they started with. Before publishing you can press **Test**: it runs the draft against the latest real event for its trigger and shows what each step would have done, without sending anything. All of this is covered in [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar) and [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones). ## Ideas to get started Cord comes with nine ready-made workflows and orders them using what you answered when you created your account: your industry, what you will use Cord for and your role. Each card says why we suggest it, and each idea alerts the team through the channel you have connected. They are created as drafts so you can review them before publishing: | Idea | Starts when | What for | |---|---|---| | Don’t let a quote go cold | A quote is sent | So no quote gets lost in silence. | | Payment reminder 3 days before the due date | An invoice is about to be due | Collect before the date. | | Collections that step up | An invoice has been past due for days | Chase the money in stages, with multiple branches. | | The invoice goes out when you get paid | A quote is paid in full | So no paid sale is left without an invoice. | | Your Monday: collected, overdue and who to call | On a fixed schedule | Start the week with the number and the day's calls. | | Push an invoice to get paid | You run it from an invoice | Press for a payment when you decide to. | | Last call and quote close-out | A quote is about to expire | Close the loop instead of leaving quotes open forever. | | Start the work when the deposit arrives | A partial payment arrives | So work starts as soon as the money comes in. | | Large quotes go to the owner for approval | A quote requests internal approval | Small ones are approved on their own; large ones go through the owner. | Each idea, step by step, and which business it suits: [Ready-made ideas](/en/docs/automatizacion/workflows/ideas). ## What a workflow never does A workflow **does not charge, does not record payments and does not approve or reject a quote on behalf of your client.** Those decisions still belong to a person or to the client. What it does do to your documents is narrow and explicit: email or WhatsApp the document's client (never an address or number typed into the step) and remind them to pay, pause their reminders, record a payment promise, expire a quote that is past its validity, invoice an approved or paid quote (one invoice per quote and, in Mexico, stamped with the SAT), approve an internal approval request, and void an invoice that has no payments yet. Each of those actions is only offered when the trigger brings the document or client it acts on; otherwise the workflow cannot be published. And every one of them runs with the permissions of the person who published the workflow: if that person could not approve a request by hand, their workflow cannot either. It cannot create infinite loops either: a workflow is never triggered by events it caused itself, and a chain of workflows triggering each other is cut after three levels. Details in [Limits](/en/docs/automatizacion/workflows/limites). ## Workflows or integrations A workflow runs inside Cord and needs nothing connected to create tasks, email your team or write to the client. When the next step lives in another tool: - To **post to Slack or Teams, send a WhatsApp or add a note in HubSpot**, connect the app and use its action in the workflow. - To **take the event to any other app**, use the **Send the data to a URL** action with the address Zapier, Make or n8n gives you, or connect those apps directly with their Cord triggers. See [Integrations](/en/docs/automatizacion/integraciones). ## Cord Workflows guides - [Create your first workflow](/en/docs/automatizacion/workflows/primer-workflow): the editor, step by step. - [Ready-made ideas](/en/docs/automatizacion/workflows/ideas): the 9 ideas that come with Cord, how they are ordered for your business and how to adapt them. - [Triggers](/en/docs/automatizacion/workflows/disparadores): the 48 events, the scheduled trigger and the data each one brings. - [Conditions](/en/docs/automatizacion/workflows/condiciones): branches, comparisons, current status and changes. - [Waits](/en/docs/automatizacion/workflows/esperas): waits by days and waits until something happens. - [Lookups](/en/docs/automatizacion/workflows/consultas): bring a number in before deciding. - [For each](/en/docs/automatizacion/workflows/por-cada): go through a list of charges, with steps for each one. - [Ask for approval](/en/docs/automatizacion/workflows/aprobaciones): have a person decide before continuing. - [Actions](/en/docs/automatizacion/workflows/acciones): tasks, emails to the team and the client, WhatsApp to the client, document actions, POST to a URL, Slack, Teams and HubSpot. - [Event data](/en/docs/automatizacion/workflows/datos-del-evento): variables in your texts. - [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar): versions, testing without publishing and lifecycle. - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones): how to read the history, retries and failures. - [Limits](/en/docs/automatizacion/workflows/limites): plans, size and hourly caps. --- # Actions URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/acciones Last updated: 2026-10-14 The sixteen Cord Workflows actions in detail: task, email to the team or to one person, email and payment reminder to the client, WhatsApp to the client, pause reminders, expire or invoice a quote, payment promise, approve internal request, void invoice, POST to a URL, Slack, Teams and HubSpot. ## Summary | Action | What it does | Needs | Publisher's permission | |---|---|---|---| | **Create a task** | Adds a follow-up task in **Tasks**, linked to the event's quote or invoice. | Nothing | Quotes, Collections or Clients | | **Email the team** | Emails the account owner or the whole team. | Nothing | None extra | | **Send a Slack message** | Posts a message to your Slack channel. | Slack connected | None extra | | **Add a note in HubSpot** | Adds a note to the quote's Deal or the client's Company. | HubSpot connected | None extra | | **Email the client** | Sends a branded email to the client's contact, with the button to view and pay the document. | A quote or invoice trigger, and a client with an email | Quotes | | **Expire the quote** | Marks the quote as expired so the client can no longer approve it. | A quote trigger | Quotes | | **Approve the internal request** | Approves the pending internal approval and sends the quote to the client. | A quote trigger and internal approvals in your plan (Scale or higher) | Approvals | | **Void the invoice** | Voids the invoice if it has no payments applied. | An invoice trigger | Collections | | **Send the data to a URL** | Sends a signed POST with the data you choose to the URL you paste. | A public https URL | Settings | | **Send a Teams message** | Posts a card to your Microsoft Teams channel. | Teams connected | None extra | | **Send the client a WhatsApp** | Sends your approved WhatsApp template to the client's phone. | WhatsApp connected and a client with a phone | Quotes | | **Notify a team member** | Emails the team member you choose. | That they are still active on the team | None extra | | **Remind the client to pay** | Sends Cord's payment reminder with what they owe, when it is due and the button to pay. | A quote or invoice trigger, and a client with an email | Collections | | **Pause the client's reminders** | Pauses or resumes the client's automatic payment reminders. | A trigger with a client | Collections | | **Invoice the quote** | Issues the invoice for the approved or paid quote, the same as by hand. | A quote trigger | Quotes | | **Record a payment promise** | Records the date the client promises to pay the quote balance. | A quote trigger | Collections | A workflow acts **with the permissions of the person who published it**: each action asks for the same permission as doing it by hand in the app. If you lack it, you cannot publish that step, and if the publisher loses it later, the workflow is paused. See [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar). To add an action, click **Add a step › Action or lookup**: a finder opens with every action and every [lookup](/en/docs/automatizacion/workflows/consultas), filtered by family (your team, your client, the document, other tools). Pick one and fill in its fields in the panel. Every text field accepts [event data](/en/docs/automatizacion/workflows/datos-del-evento) like `{{cliente}}`. Step error messages appear in your account's language. This page lists each one with what to do. ## Create a task Adds a task for your team in **Tasks**, just as if you had created it by hand. | Field | Required | Detail | |---|---|---| | **Task title** | Yes | Up to 200 characters. Accepts event data. Line breaks become spaces. | | **Due in (days)** | No | 0 to 365. **0** means due today; **1**, tomorrow. Leave empty for a task without a date. | | **Assignee** | No | An active team member. If they later leave the team, the step fails with "The chosen person is no longer active on the team: choose someone else in the step." | **What it is linked to:** - If the trigger is about a quote (sent, approved, paid, partial payment, invoiced, etc.), the task is linked to that quote: in **Tasks** it shows the quote number and client as a link to the quote. - If the event carries a related quote, the task is also linked to it: a dispute or refund on a quote, an invoice created from a quote, a payment promise, or a task linked to a quote. - On **A draft is deleted** it is not linked, because the quote no longer exists. - If the trigger is about an invoice (issued, sent, paid, payment fails, about to be due, overdue, past due for days, voided, or marked uncollectible), the task is linked to that invoice: in **Tasks** it shows the invoice number and client as a link to the invoice. If the invoice came from a quote, it's linked to both. - In every other case (clients, products, payouts, scheduled triggers, standalone tasks) the task is standalone. **Assignee:** if you choose one, the task is created assigned to that person; if not, unassigned. Either way it is created with normal priority, which you change from **Tasks**. While it has no assignee, the [email reminder](/en/docs/gestion/tareas#email-reminder) goes to the account owner. **When it fails:** - "The task title came out empty.": the title only had event data and all of it arrived empty. Add fixed text, for example "Follow-up: `{{cliente}}`". - "Workflows reached their hourly limit of tasks.": your workflows created 120 tasks in the last hour. See [Limits](/en/docs/automatizacion/workflows/limites). - "The task could not be created.": Cord rejected the task, for example because the quote or invoice it was going to be linked to no longer exists. Creating a task is also an event. If you have a workflow with the **A task is created** trigger, it will react to tasks created by your other workflows. Use the condition "Who caused it is not Another workflow" if you do not want that. ## Email the team Sends an email to people in your organization. **It never writes to the client.** | Field | Required | Detail | |---|---|---| | **To** | Yes | **The account owner**, or **The whole team**: the active members of your organization, up to 25. Pending invitations do not receive it. | | **Subject** | Yes | Up to 150 characters. Accepts event data. If it ends up empty when running, the workflow name is used. | | **Message** | Yes | Up to 2,000 characters. Accepts event data and line breaks. | **What the email looks like:** your message exactly as you wrote it, and at the bottom a line "Sent by the *Name* workflow in Cord." linking to the workflow. The footer uses your account's language. Event data is inserted as text: if a client's name contains symbols or tags, they are shown literally and do not alter the email. Each person receives their own email; nobody sees the others' addresses. **When it fails:** - "There is nobody to send the email to": you chose **The account owner** and the account has no owner with an email, or there are no active members. - "Email is not available right now": it could not be delivered to anyone. It is retried automatically. - "Hourly email limit for workflows reached": your workflows sent 30 emails in the last hour. ## Email the client Emails the contact of the client on the event's document, with the business's branding and the button to the public link: approve, if the event is about a quote; pay, if it is about an invoice. | Field | Required | Detail | |---|---|---| | **Subject** | Yes | Up to 150 characters. Accepts event data. | | **Message** | Yes | Up to 2,000 characters. Accepts event data and line breaks. Your client reads this. | **Who receives it:** the email of the document's client, never an address typed into the step. If the client has no email on file, the step fails and says so. **What Cord adds:** your logo and brand color, the button to the document, the link in plain text in case the button does not open, and your business footer. In the test environment the subject is marked as a test. **Language:** the button and the text Cord adds appear in the document's language: the one the quote or invoice took when sent or issued or, if it doesn't have one yet, the client record's or your account's. Your subject and message go out exactly as you wrote them: Cord doesn't translate them. **It counts against your plan:** each client email uses one send from your plan's monthly quota, the same as sending a quote by hand. If the quota is gone, the step fails and nothing is sent. **It never arrives twice:** every attempt carries the step's key. If a send is cut off without a response, Cord retries with the same key and the email service doesn't send your client a second one; an attempt that didn't go out returns its send to the quota. If you send from your Gmail, which doesn't know that key, the step stops so you can check whether it arrived. See [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones). Cord already sends its own invoice reminders on the schedule set in **Settings › Invoicing › Reminders**. If you also build a workflow that emails the client, check that two notices do not land on the same day for the same money. ## Expire the quote Marks a quote that is still sent or viewed as **Expired**. The client can no longer approve or reject it from the link, the event is recorded in its history, and **A quote expires** fires for the rest of your automations. It only works with triggers that carry a quote; if the quote was already approved, rejected or expired, the step fails with "The quote is no longer in a state that allows this action". ## Approve the internal request Approves the quote's pending internal approval request and sends the quote to the client, exactly as if someone approved it in the app. Use it behind a condition — a total below a certain amount, for example — so small approvals do not wait on a person. It only works with triggers that carry a quote and requires internal approvals in your plan: they come with **Scale** or higher. **When it fails:** - "Your current plan does not include internal approvals.": your plan has no approvals. - "This quote no longer has a pending approval request.": someone already decided it or it was withdrawn. Nothing changes. ## Void the invoice Voids the event's invoice. It follows the same rules as voiding by hand from **Invoices**: an invoice with payments applied is **not** voided — that is what the credit note is for — and in Mexico canceling a CFDI with the SAT may stay pending a response. When it cannot be voided, the step fails with "This invoice cannot be voided: review it in Invoices." and the invoice stays as it was. | Field | Required | Detail | |---|---|---| | **Reason** | No | Up to 200 characters. It is kept in the invoice history. | ## Send the data to a URL Sends a signed `POST` to the address you paste: a Zapier Zap, a Make scenario, an n8n flow or your own server. Only the data you check is sent. | Field | Required | Detail | |---|---|---| | **Destination URL** | Yes | It must be `https` and on a public server. Cord rejects internal addresses both when publishing and when running. | | **Data to send** | No | Check what your destination needs; anything you leave unchecked never leaves Cord. An amount always travels with its currency, even if you don't check it. | | **Message** | No | Up to 1,000 characters. Accepts event data; it travels in the `mensaje` field. | | **Response data** | No | Up to 5 data fields Cord takes from the response for the next steps. See **Use the response**. | The body looks like this: ```json { "workflow": "Large deal alert", "workflow_id": "…", "evento": "quote.approved", "objeto": "quote", "objeto_id": "…", "enviado_en": "2026-09-20T18:00:00.000Z", "mensaje": "ACME approved COT-7", "datos": { "folio": "COT-7", "total": 150000, "moneda": "MXN" } } ``` The data travels the way a machine reads it: unformatted numbers and codes instead of labels. In the run history, the step shows the URL, the data that was sent and the names of the custom headers, never their values. ### Use the response If your destination replies with JSON (the ID of the order it created, a tracking number, a calculated total), take it in **Response data** and use it in the next steps like any other data. | Column | Detail | |---|---| | **Data name** | How you see it among the variables. The variable is built from it: "Order ID" reads as `{{respuesta_order_id}}`. | | **Path in the response** | Names separated by dots, and the position in a list as a number starting at 0: `data.id`, `items.0.total`. | | **Type** | **Text** or **Number**. A number that arrives as text (`"120.5"`) is converted; if it is not a number, it stays empty. | - Each step holds up to 5 data fields, and Cord reads up to 64 KB of the response. - Anything missing from the response, or a response that is not JSON, stays empty: the request did arrive and the step does not fail. - The data exists from the step that brings it: an earlier step that uses it cannot be published, and neither can two data fields that read the same in one workflow. - In the run history, the step shows what it read. - **Test** sends nothing, so in a test these data fields are empty. ### Request signing Every request carries two signatures made with the workflow's secret: Cord's and the [Standard Webhooks](https://www.standardwebhooks.com) one. To see the secret, open the step and click **Reveal secret**. Only people with the Settings permission can see it, and it is recorded in the audit log. | Header | Content | |---|---| | `webhook-id` | The same on every retry of the step; it also travels as `Idempotency-Key`. Use it to avoid processing the same request twice. | | `webhook-timestamp` | When this attempt was signed, in unix seconds. | | `webhook-signature` | `v1,`. During a roll it carries two, separated by a space. | | `X-Cord-Signature-V1` | `t=,v1=`, the same format as [webhooks](/en/docs/desarrolladores/herramientas/webhooks). | | `X-Cord-Workflow-Id` and `X-Cord-Event` | The workflow and the event that triggered it. | With any Standard Webhooks library, verifying takes one line. In Node: ```ts import { Webhook } from 'standardwebhooks'; const body = new Webhook(process.env.CORD_WORKFLOW_SECRET!).verify(await req.text(), Object.fromEntries(req.headers)); ``` Verify the raw body exactly as it arrived: if you turn it into an object and serialize it again, the signature no longer matches. **Rolling the secret:** click **Roll** and choose how long the old one keeps signing: 1, 24 or 72 hours, or **Revoke the old one now** if it leaked. While the overlap lasts, every request carries both signatures and your server accepts either, so you change the secret without losing a single request. ### Custom headers For the key that Zapier, Make or your server asks for, such as `Authorization: Bearer …`, add it under the step's **Custom headers**. A step can have up to 5. The value is stored encrypted and never shown again; to change it, save it again with the same name. You can't use the names Cord sets: `Content-Type`, `User-Agent`, `Idempotency-Key` and anything starting with `X-Cord-` or `webhook-`. Don't put a key in the **Message**: it travels in the body and stays in the run history. Duplicating a workflow doesn't copy its secret or headers, and deleting it erases them. **When it fails:** - "The destination URL is not valid or points to an internal server.": fix the URL; it is not retried. - "The destination URL did not accept the request.": if the destination didn't respond, or responded with 408, 429 or a 5xx error, it is retried on the schedule in [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones), always with the same `webhook-id` and `Idempotency-Key` so your destination recognizes the retry. Any other 4xx is not retried: your destination rejected the request and repeating it changes nothing. - "We couldn't read a saved header on this step. Enter its value again.": save the header again; the step sends nothing without it. - "Workflows reached their hourly limit of posts to a URL.": 120 posts in the last hour. ## Send a Slack message Posts a message to the channel you connected in **Settings › Integrations › Slack**. | Field | Required | Detail | |---|---|---| | **Message** | Yes | Up to 1,000 characters. Accepts event data and line breaks. | **What it looks like:** the text appears in the channel with the name and icon of the webhook's Slack app. Event data is inserted as plain text; a `<` or `&` in a client's name does not break the message formatting. This message is independent from the **Settings › Notifications** alerts: a workflow posts even if those alerts are off, and with the text you write. **When it fails:** - "Connect Slack in Settings › Integrations to use this action": no Slack URL is saved. - "Slack did not accept the message. Check the connection in Settings › Integrations": Slack rejected it, usually because the webhook was deleted or the app was removed from the channel. Create a new webhook and paste the URL. Meanwhile, Cord retries. - "The message ended up empty": the message only had event data and it arrived empty. - "Hourly message limit for workflows reached": 120 messages in the last hour. How to connect Slack: [Slack](/en/docs/automatizacion/integraciones/slack). ## Send a Teams message Posts a card to the channel you connected in **Settings › Integrations › Microsoft Teams**, through either connection method: - **Connect with Microsoft:** the card goes to the team and channel you picked, in the name of whoever connected. - **Power Automate flow:** the card goes through the flow whose URL you pasted. | Field | Required | Detail | |---|---|---| | **Message** | Yes | Up to 1,000 characters. Accepts event data and line breaks. | **How it looks:** a card with your text in the channel. Teams does not use Slack's formatting, so asterisks and `` links show up literally; write plain text. It is independent from **Settings › Notifications**: the workflow posts even when those notices are off. **When it fails:** - "Connect Microsoft Teams in Settings › Integrations to use this action.": Teams is not connected either way. - "Microsoft no longer accepts the Teams connection. Reconnect it in Settings › Integrations.": with **Connect with Microsoft**, access expired or was revoked. Click **Reconnect** on the card. - "Teams did not accept the message. Check that the channel or the flow is still active.": the channel no longer exists or you lost access to it, or the Power Automate flow was turned off or deleted. Pick another channel, or create a new flow and paste the new URL. Meanwhile, Cord retries. - "The message came out empty.": the message only had event data and it came out empty. - "Workflows reached their hourly limit of Teams messages.": 120 messages in the last hour. How to connect Teams: [Microsoft Teams](/en/docs/automatizacion/integraciones/teams). ## Send the client a WhatsApp Sends the template you set up in **Settings › Integrations › WhatsApp Business** to the phone of the document's client. | Field | Required | Detail | |---|---|---| | **Variable 1 to 4** | No | Fill `{{1}}`, `{{2}}`… of your template, in order. They accept event data. | **Why variables and not a message:** Meta does not allow starting a conversation with free text, only with an approved template. A free-text field here would promise something the provider rejects. **The phone comes from the client**, never from a field in the step, and it must carry a country code. Cord does not guess the country: the same number exists in several. **Language:** your template's, the one Meta approved, the same for all your clients; it doesn't follow each client's document language. **When it fails:** - "The client has no phone with a country code on file.": edit the client and save the number with `+`. - "Connect WhatsApp in Settings › Integrations to use this action.": WhatsApp is not connected. - "WhatsApp did not accept your template. Check it in Settings › Integrations: it must be approved and have the same number of variables.": it is not approved, the name does not match, or the number of variables differs. - "WhatsApp did not accept the message. It retries on its own.": a temporary rejection; Cord retries. - "Workflows reached their hourly limit of WhatsApp messages.": 60 messages in the last hour. How to connect it: [WhatsApp Business](/en/docs/automatizacion/integraciones/whatsapp). ## Add a note in HubSpot Adds a note in HubSpot so your sales team sees what happened in Cord. | Field | Required | Detail | |---|---|---| | **Note** | Yes | Up to 2,000 characters. Accepts event data and line breaks. | **Where the note goes:** 1. On the **Deal** of the event's quote, if that quote is already in HubSpot. 2. If there is no Deal, on the client's **Company**, if the client is already in HubSpot. 3. If neither is in HubSpot yet, the step waits and retries: usually the sync finishes within moments. The note is timestamped when created and appears on the record's timeline in HubSpot. **Which triggers have somewhere to put the note:** quote triggers, quote payments, disputes, refunds and client triggers. On triggers without a quote or client (for example **A payout is paid to your bank** or **A product is created**) the note has no record to attach to: the step retries and the run ends as **Failed** with "HubSpot did not accept this step's data. Check the setup in Settings › Integrations." Use this action only with triggers that have a quote or client. **When it fails:** - "HubSpot needs to be reconnected in Settings › Integrations.": the connection lost its authorization. - "HubSpot did not accept this step's data. Check the setup in Settings › Integrations.": HubSpot is not connected or needs reconnecting; the record is not in HubSpot yet (see point 3 above; if it persists, check that the pipeline and stages are complete, because quotes in a status without a stage are not sent to HubSpot); or the Deal or Company was deleted in HubSpot. - "HubSpot did not respond. It retries on its own.": a temporary HubSpot failure. - "The note came out empty.": the note only had event data and it came out empty. - "Workflows reached their hourly limit of HubSpot notes.": 120 notes in the last hour. How to connect HubSpot: [HubSpot](/en/docs/automatizacion/integraciones/hubspot). ## Notify a team member Emails the team member you choose, with the link to the workflow at the bottom. Use it so the notice reaches whoever handles the account or the project, not the whole team. | Field | Required | Details | |---|---|---| | **To** | Yes | An active team member. If they later leave the team, the step fails with "The chosen person is no longer active on the team: choose someone else in the step." | | **Subject** | Yes | Up to 150 characters. Accepts event data. If it ends up empty when running, the workflow name is used. | | **Message** | Yes | Up to 2,000 characters. Accepts event data and line breaks. | It shares the hourly email limit with **Email the team**. ## Remind the client to pay Sends the same payment reminder as the automatic reminders in **Settings › Invoicing › Reminders**: what they owe, when it is due and the button to pay. If the event carries an invoice, it reminds about the invoice; otherwise, the quote. It also works inside a [For each](/en/docs/automatizacion/workflows/por-cada), with each item's document. - **It does not send it** if the document has no balance left or if the reminders for the client or that document are paused. The step does not fail: **Runs** says why it was not sent. - On an invoice, the reminder stays in its history. - It shares the hourly limit of client emails with **Email the client**. **When it fails:** "The reminder was not sent: the document is no longer open or the client has no email." ## Pause the client's reminders Pauses or resumes the automatic payment reminders for the event's client, the same as from **Settings › Invoicing › Reminders**. While they are paused, **Remind the client to pay** does not send either. | Field | Required | Details | |---|---|---| | **What to do** | Yes | **Pause** or **Resume**. Resuming removes any pause on the client, including the ones set by AI collections. | It only works with triggers that carry a client. ## Invoice the quote Issues the invoice for the event's quote, the same as the **Invoice** action on the quote's detail: with your country's tax rules and, in Mexico, stamped with the SAT. It counts as an invoice issued on your plan. - It only invoices an **approved** or **paid** quote. If it is already invoiced, it does not issue another one: the step fails with "The quote is no longer in a state that allows this action." - If issuing does not respond, Cord tries again without duplicating it: a quote has a single invoice. **When it fails:** - "Your plan does not include issuing this invoice." - "Data is missing to issue the invoice: check the business and client tax details." ## Record a payment promise Records that the client promises to pay the quote balance within the days you choose, the same as recording it in **Collections**, where it shows up like one entered by hand. | Field | Required | Details | |---|---|---| | **Promises to pay within (days)** | Yes | Between 0 and 90, counted from today in your business's time zone. | | **Note** | No | Up to 400 characters. Accepts event data. | It only works with quote triggers. If it is unknown whether the promise was saved, the run goes to **Needs attention** instead of recording it twice. ## Several actions in a row Actions at the same level run in order, one after another. If one fails, the following ones do not run until it is resolved: the run is retried **from the step that failed**, without repeating the ones already done. So a task is not created twice because the Slack message after it failed. ## Next - [Conditions](/en/docs/automatizacion/workflows/condiciones) - [Event data](/en/docs/automatizacion/workflows/datos-del-evento) - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones) --- # Ask for approval URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/aprobaciones Last updated: 2026-10-14 How to make a workflow wait for a person's decision: who can approve, how the notice reaches them by email, in Cord or in Slack, and what happens if they reject it or nobody decides. ## What it is for Some steps should not run on their own: voiding an invoice, sending a reminder to an important client or telling the team about a discounted sale. **Ask for approval** puts a person in the middle: the workflow asks them and waits for their answer. ## How to add it 1. Click **Add a step › Ask for approval**. 2. Under **Who decides**, choose **The account owner**, **The owner or an admin** or **Anyone on the team**. 3. Under **What you are asking**, write what they should review. You can use variables like `{{folio}}` or `{{total}}`. 4. Set the **Time to decide** in days, from 1 to 30. 5. If you want, check **Also notify in Slack**. 6. On the canvas, build what happens under **If approved** and under **If rejected or time runs out**. ## How it reaches the person deciding - **By email:** each person in the group gets an email, in their language, with what is being asked and the **Review and decide** button. - **In Cord:** the **Approvals** page gathers everything waiting for their decision. It opens from the email button or from the notice in the **Workflows** list that says how many they have pending. - **In Slack:** if you checked the option and the account has Slack connected, the channel gets the notice with a link to the approval. Without Slack connected, the notice only goes by email and in Cord. The person deciding does not need the **Settings** permission: belonging to the chosen group is enough. The account owner can always decide. ## Deciding On **Approvals**, each one shows the workflow, the document that started it, what is being asked and until when there is time to decide. Click **Approve** or **Reject**; you can leave a comment. The first decision is the one that counts. It cannot be changed afterwards, and the workflow continues right away through the matching branch. ## If nobody decides When time runs out, the approval closes on its own and the workflow continues through **If rejected or time runs out**: the same branch as a rejection. **Runs** shows which of the two it was. ## Where you see what happened In **Runs**, the step says who was asked and what was asked. While it waits, it shows until when; once decided, it shows **Approved by**, **Rejected by** or **Time ran out with no decision**, and the comment if there was one. **Test** does not ask anyone: it shows what would happen if it were approved. ## Limits | Limit | Value | |---|---| | Time to decide | 1 to 30 days | | Length of what is asked | 2,000 characters | | Length of the comment | 500 characters | | Inside a "For each" | Not allowed | ## Next - [Waits](/en/docs/automatizacion/workflows/esperas) - [Conditions](/en/docs/automatizacion/workflows/condiciones) - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones) --- # Conditions URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/condiciones Last updated: 2026-10-14 How to split a workflow into two branches based on event data: rules joined with And and Or, comparisons by data type, status at the event versus current status, and nested conditions. ## What it looks like On the canvas, a condition shows as a diamond with two outputs: - **If the condition is met:** the steps that run when the condition is true. - **If the condition isn't met:** the steps that run when it is false. Either branch can be empty. An empty branch means "do nothing in this case". When the chosen branch ends, the flow continues with the step **after** the condition, if there is one. ## Set up a condition 1. Click **Add a step › Add condition**. **Edit condition** opens. 2. Click **Add a condition**. The field search opens: type part of the name or browse the list, where each field carries the icon of its type (text, number, amount, options, yes or no, date). Fields marked "checked at run time" are read when the condition is evaluated, not from the event. 3. Choose the **Comparison** from its menu; the selected one has a check mark. 4. Type or choose the **Value**. For an amount you also choose the **Currency**. 5. To add another rule click **Add another condition** and choose **And** or **Or**. To remove one, click the X on its card. Up to 10 rules. 6. Click **Done**. Each rule is a card. The first one says **If**; the ones you add with **And** say **And**, and a rule added with **Or** starts a new group, separated by a line that says **Or**. ### And, Or and groups | Join | Met when | Example | |---|---|---| | **And** | Both rules are true. | Total is at least 50,000 USD **and** Payment type is Deposit. | | **Or** | One complete group being met is enough. | Payment type is Deposit **or** Payment type is Installment. | **And** binds tighter than **Or**: rules joined with **And** form a group, and the condition is met when **any complete group** is met. "If Total is greater than 100,000 MXN **and** Payment type is Deposit, **or** if Client contains ACME" is met by a large deposit sale or by any sale to ACME. For "A and (B or C)", repeat A in each group: "If A and B, or if A and C". You can also put a condition inside a branch of another one. ## Comparisons by data type The editor only offers comparisons that make sense for each field. ### Text Number, Client, Currency, Reason, Message, Email, Country and similar. | Comparison | Met when | |---|---| | is | The text is exactly the value. | | is not | The text is different from the value. | | contains | The value appears anywhere in the text. | | does not contain | The value does not appear in the text. | | is empty | The item has no content. | | is not empty | The item has content. | Text comparisons **are not case-sensitive**: "acme" is "ACME". ### Number Days past due, Days until it expires, Overdue documents, Pending verification items, Hour and similar. | Comparison | Met when | |---|---| | is at least | The number is equal to or greater than the value. | | is greater than | The number is greater than the value. | | is at most | The number is equal to or less than the value. | | is less than | The number is less than the value. | | equals | The number is exactly the value. | | does not equal | The number is different from the value. | Type the value as a number, without separators: `30`, not `30 days`. If the event does not carry the number, no numeric comparison is met and the flow goes down **If the condition isn't met**. ### Amount Total, Balance due, Amount paid, Promised amount, Disputed amount, Refunded amount, Payout amount, List price and the totals from [lookups](/en/docs/automatizacion/workflows/consultas). An amount is compared **with its currency**. Besides the value you choose the **Currency**, and the rule reads "Total is less than MX$50,000.00". A new rule starts in your business's currency and you can change it. | Comparison | Met when | |---|---| | is at least, is greater than, is at most, is less than, equals | The amount is in the rule's currency and meets the comparison. | | does not equal | The amount is different, or is in another currency. | Cord does not convert between currencies to decide: a quote of 49,000 USD is not "less than 50,000 MXN", because they are amounts in different currencies, so that rule is not met. If you sell in several currencies, add one rule per currency joined with **Or**: "Total is less than 50,000 MXN" or "Total is less than 2,500 USD". Type the value as a number, without symbol or separators: `50000`, not `$50,000`. Without a currency the rule cannot be published: "Choose the currency for "Total"." The totals from lookups are in your business's currency. ### Options Status at the event, Current status, Payment type, Decision, Dispute outcome, Who caused it, Who wrote it and Payment terms. | Comparison | Met when | |---|---| | is | The item has the chosen option. | | is not | The item has any other option. | The value is picked from a list, so there are no typos. ### Yes or no Active (products), Can accept online payments and Can receive payouts. | Comparison | Met when | |---|---| | is yes | The item is true. | | is no | The item is false. | ## Status at the event versus current status Quotes and invoices have two status items, and the difference matters: | Item | Value | |---|---| | **Status at the event** | The document's status at the moment the event happened. It never changes. | | **Current quote status** / **Current invoice status** | The document's status **when the condition is evaluated**. In the editor it is marked "checked at run time". | Right after the event both match. The difference appears **after a wait**: if a workflow waits 3 days after sending a quote, "Status at the event" still says **Sent**, but "Current status" says **Viewed**, **Approved** or whatever happened in those days. Rule of thumb: after a wait, always use the **current status**. That is what lets you ask "is it still unopened?" or "is it still unpaid?". Possible quote statuses: Draft, Sent, Viewed, Approved, Rejected, Expired, Paid and Invoiced. Invoice statuses: Draft, Open, Paid, Void and Uncollectible. ## What changed, not just what it is Three events also carry the **previous** value, so a condition can ask about the change and not only about the current value: | Trigger | Fields with a previous value | |---|---| | **A quote is edited and resent** | Total | | **A client is updated** | Company, Email, Payment terms | | **A product is updated** | List price, Active | On those fields the editor offers two more operators: **changed** and **did not change**. You also get the previous value as its own field (**Previous total**, **Previous list price**, and so on), usable both in conditions and in your text. Example: "when a quote is resent, if the **Total** changed and the **Total** is lower than the **Previous total**, tell the owner" — a last-minute discount, which a plain condition on the total cannot tell apart from a deal that was always worth that. If the event does not carry the previous value, **changed** and **did not change** both answer no: an event from before this capability would answer "changed" to everything, and that is worse than not answering. ## Multiple branches When there are more than two paths, use **Add a step › Multiple branches** instead of nesting conditions. Each branch has its name and its conditions, and after all of them comes **Otherwise**. - Cord checks the branches **in order** and follows the first one that is met, even if another one is also met. Put the strictest first: "Large" (Total is greater than $200,000.00 MXN) before "Medium" (Total is greater than $100,000.00 MXN). - If none is met, it follows **Otherwise**, which can stay empty. - Up to 5 branches fit. Reorder them with **Move up** and **Move down** in the panel. - Each branch needs at least one condition to publish. - In **Runs**, the step says which way it went: "Followed: Large". ## Nested conditions You can put a condition inside a branch of another one, up to 4 levels deep. Example with two levels, triggered by **A quote is approved**: 1. Condition: Total is at least 100,000. - **If met:** condition: Currency is USD. - **If met:** email the whole team. - **If not met:** email the account owner. - **If not met:** create a normal follow-up task. All steps, in every branch, count toward the maximum of 30 steps per workflow. ## Common publishing errors | Message | What to do | |---|---| | Add at least one condition. | The condition has no rules. Add one or delete the step. | | A condition uses a field that does not exist for this event. | You changed the trigger and the new one does not carry that item. Choose another field. | | Choose how to compare "Total". | The comparison is missing. | | Fill in the value for "Total". | The value is missing. | | "Total" needs a number. | You typed text in a numeric field. Remove symbols and separators. | | Choose a valid value for "Payment type". | The chosen option does not exist for this field. Pick it again. | ## In the history Each evaluated condition appears in the run as **Met** or **Not met**, so you know which branch it took. See [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones). ## Next - [Waits](/en/docs/automatizacion/workflows/esperas) - [Event data](/en/docs/automatizacion/workflows/datos-del-evento) --- # Lookups URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/consultas Last updated: 2026-10-13 How to bring a number from your account into a workflow: overdue receivables, open pipeline, what was collected, what is about to be due, and a client's balance. ## What it is for A workflow only knows what the event carried. "Quote COT-7 for 150,000 was approved" says nothing about how much that client owes you or how your receivables are doing, so an alert could not include it and a condition could not decide on it. A lookup closes that gap: you place it earlier, Cord runs it, and its results become variables for the rest of the workflow. A lookup only **reads**. It never changes anything in your account, so you can use it as often as you want. ## How to add one 1. Click **Add a step › Action or lookup**. 2. In the finder, filter by **Lookup** or type what you are after ("overdue", "pipeline", "balance"). 3. Pick the lookup. If it has a days parameter, set it. 4. The panel shows **Makes available**: those are the variables you can use afterwards. ## The lookups | Lookup | What it brings | Variables | |---|---|---| | **Overdue receivables** | How much you are owed past the due date. | `{{vencido_total}}`, `{{vencido_cantidad}}`, `{{vencido_dias_max}}` | | **Open pipeline** | How much sits in sent or viewed quotes that are undecided. | `{{pipeline_total}}`, `{{pipeline_cantidad}}` | | **What was collected** | How much you were paid over the last days you choose (1 to 90): quote payments and invoice payments, minus what was refunded. `{{cobrado_cantidad}}` counts the payments received. | `{{cobrado_total}}`, `{{cobrado_cantidad}}` | | **What is about to be due** | How much is due over the next days you choose (1 to 90). | `{{por_vencer_total}}`, `{{por_vencer_cantidad}}` | | **Client balance** | How much the event's client owes and how much is overdue. | `{{cliente_saldo}}`, `{{cliente_vencido}}`, `{{cliente_documentos}}` | Amounts come out **in your business's currency**: what you sold in another currency is converted the same way as in **Reports**, with the rate frozen on the document or the one published that day, and what was collected is the same figure you see there. If a currency has no rate available at all, its amount is left out of the total; a rate is never made up. ## Order matters A lookup variable exists **from the step that brings it onward**. If you use it before, the workflow will not publish and the editor says so: "The variable `{{vencido_total}}` comes from a lookup that runs after this step." The same applies inside a branch: what the **If met** branch looks up does not exist in the **If not met** branch. If both need it, put the lookup **before** the condition. ## Client balance needs a client **Client balance** uses the event's client, so it only works with triggers that carry one: quotes, invoices, payments and clients. A scheduled or payout trigger has no client to ask about, and the workflow cannot be published with that lookup. ## A full example "Your Monday: collected, overdue and who to call", one of the ideas Cord ships with: 1. **When this happens:** every Monday at 9. 2. **Lookup:** what was collected in the last 7 days. 3. **Lookup:** overdue receivables. 4. **Lookup:** the open pipeline. 5. **Action:** alert the account owner, with the subject "Your week in Cord (`{{fecha}}`)" and the message "Collected in the last 7 days: `{{cobrado_total}}` across `{{cobrado_cantidad}}` payments. Overdue: `{{vencido_total}}` across `{{vencido_cantidad}}` documents, the oldest `{{vencido_dias_max}}` days past due. Left to close: `{{pipeline_total}}` across `{{pipeline_cantidad}}` quotes." With Slack or Teams connected, the alert goes out there. You can extend it: add the lookup for what is about to be due, or change the recipient to the whole team. ## Limits Each lookup is a step, so it counts toward the 30-step maximum per workflow. They have no hourly cap of their own: they only read. ## Next - [Conditions](/en/docs/automatizacion/workflows/condiciones) - [Triggers](/en/docs/automatizacion/workflows/disparadores) - [Event data](/en/docs/automatizacion/workflows/datos-del-evento) --- # Event data URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/datos-del-evento Last updated: 2026-10-13 How to insert event data into workflow texts with double braces, how it looks when it runs, and the full list of data available per trigger. ## How to write it Event data is written in double braces with its name: `{{cliente}}`, `{{folio}}`, `{{total}}`. Names are the same in every language. You can combine them with free text: > Call `{{cliente}}` about `{{folio}}`: `{{total}}` When quote COT-128 from Northwind for 48,500 USD triggers the workflow, that title becomes: > Call Northwind about COT-128: $48,500.00 ## Insert it without typing In each action panel, below the text fields, you see **Event data**. Place the cursor where you want the item and tap its name: Cord inserts the braces for you. Only the data carried by the trigger you chose is shown. You can also type `{{` in the field: **Search data** opens, with the icon of each item's type and the value carried by the latest event of that trigger in your account (for example, "Northwind" next to **Client**), so you recognize each item by what it holds. Pick one and Cord completes the braces. If the trigger hasn't happened yet, you see the variable instead of the value; data read at run time says so. It works in: the task title, the email subject and message (to the team or to the client), the WhatsApp variables, the Slack message, the Teams message, the HubSpot note, the message of the POST to a URL, and the void reason. The POST's destination URL does not accept it. ## How it looks when it runs | Data type | How it appears | Example | |---|---|---| | Text | As is. | Northwind | | Number | With thousands separators for your account's language and up to 2 decimals. | 1,250 | | Amount | With the symbol and decimals of its own currency, in your account's format. An amount in yen comes out without decimals. | $48,500.00 | | Option | By its name, in your account's language. | Approved, Deposit, The client | | Yes or no | Yes or No. | Yes | | Empty | Nothing appears. | | An amount already comes out with its currency symbol. Use `{{moneda}}` when you want the code on its own, for example "MXN" in a note. If an item arrives empty, it is inserted empty: "Call `{{cliente}}`" with a client without a name becomes "Call ". That is why each text should also have fixed words. Data is inserted as **text**. If a client's name or a message contains symbols like `<`, `>` or `&`, they are shown literally and do not alter the formatting of the email, Slack or HubSpot. ## Current status: checked at run time Items marked "checked at run time" (**Current quote status** and **Current invoice status**) are not stored with the event: Cord reads them when the step runs. In an email sent after a 5-day wait, `{{estado_actual}}` shows that day's status, not the one from 5 days before. ## If the item does not exist for the trigger When publishing, Cord checks every text. If you used data that trigger does not carry, you see: > The variable `{{saldo}}` does not exist for this event. It usually happens when changing the trigger of a workflow you already built, or when typing the name by hand with a typo. Fix it or insert it from **Event data**. ## Your business data These five variables exist on **every** trigger, because they come from your account (Settings › General), not from the event: | Variable | What it brings | |---|---| | `{{negocio}}` | Your business name. | | `{{negocio_correo}}` | Your contact email. | | `{{negocio_telefono}}` | Your phone. | | `{{negocio_moneda}}` | Your account's currency. | | `{{hoy}}` | Today's date in your time zone, like `2026-09-20`. | They are mostly for signing an email to the client without typing your name by hand in every workflow: if the business changes its name or phone, the workflows come out right without being touched. `{{hoy}}` is today in **your** time zone, not the server's. A business in Tokyo saw the date off by one day when the universal date was used. ## Full list ### Quotes, approvals and quote payments | Item | Name | Type | |---|---|---| | Number | `{{folio}}` | Text | | Client | `{{cliente}}` | Text | | Total | `{{total}}` | Amount | | Currency | `{{moneda}}` | Text | | Status at the event | `{{status}}` | Option | | Current quote status | `{{estado_actual}}` | Option, checked at run time | | Who caused it | `{{actor_tipo}}` | Option | Plus, depending on the trigger: | Trigger | Item | Name | Type | |---|---|---|---| | A message is posted on a quote | Who wrote it | `{{autor}}` | Option | | A message is posted on a quote | Message | `{{mensaje}}` | Text | | A quote requests internal approval | Reason | `{{motivo}}` | Text | | An internal approval is decided | Decision | `{{decision}}` | Option | | A partial payment arrives | Amount paid | `{{monto}}` | Amount | | A partial payment arrives | Balance due | `{{saldo_pendiente}}` | Amount | | A partial payment arrives | Payment type | `{{tipo}}` | Option | | A quote is edited and resent | Previous total | `{{total_anterior}}` | Amount | | A quote is about to expire | Days until it expires | `{{dias_para_vencer}}` | Number | | A quote is about to expire | Expiration date | `{{vence}}` | Text | **A draft is deleted** carries everything in the first table except current status. ### Cord Invoicing invoices Applies to issued, sent, paid, payment fails, overdue, about to be due, past due for days, voided and marked uncollectible. | Item | Name | Type | |---|---|---| | Number | `{{numero}}` | Text | | Client | `{{cliente}}` | Text | | Total | `{{total}}` | Amount | | Balance due | `{{saldo}}` | Amount | | Currency | `{{moneda}}` | Text | | Country | `{{pais}}` | Text | | Status at the event | `{{estado}}` | Option | | Current invoice status | `{{estado_actual}}` | Option, checked at run time | | Who caused it | `{{actor_tipo}}` | Option | Plus, depending on the trigger: | Trigger | Item | Name | Type | |---|---|---|---| | An invoice is about to be due | Days until due | `{{dias_para_vencer}}` | Number | | An invoice is about to be due | Due date | `{{vence}}` | Text | | An invoice has been past due for days | Days past due | `{{dias_vencida}}` | Number | | An invoice has been past due for days | Due date | `{{vence}}` | Text | "A quote is invoiced" and "A quote CFDI is stamped" use quote data, not these. ### Disputes and refunds | Item | Name | Type | Triggers | |---|---|---|---| | Quote number | `{{folio}}` | Text | All | | Client | `{{cliente}}` | Text | All | | Disputed amount | `{{monto}}` | Amount | Disputes | | Refunded amount | `{{monto}}` | Amount | Refunds | | Currency | `{{moneda}}` | Text | All | | Reason | `{{motivo}}` | Text | All | | Response deadline | `{{fecha_limite}}` | Text | Disputes | | Outcome | `{{estado}}` | Option | A dispute is closed | | Failure reason | `{{motivo_falla}}` | Text | A refund fails | ### Payouts | Item | Name | Type | Triggers | |---|---|---|---| | Payout amount | `{{monto}}` | Amount | Both | | Currency | `{{moneda}}` | Text | Both | | Arrival date | `{{llegada}}` | Text | Both | | Failure reason | `{{motivo_falla}}` | Text | A payout fails | ### Payments account | Item | Name | Type | |---|---|---| | Can accept online payments | `{{puede_cobrar}}` | Yes or no | | Can receive payouts | `{{puede_depositar}}` | Yes or no | | Pending verification items | `{{pendientes}}` | Number | | Restriction reason | `{{motivo_bloqueo}}` | Text | ### Clients | Item | Name | Type | |---|---|---| | Company | `{{empresa}}` | Text | | Email | `{{email}}` | Text | | Country | `{{country_code}}` | Text | | Payment terms | `{{terminos}}` | Option (Due on receipt, Net 7, Net 15, Net 30, Net 45, Net 60 or Net 90) | | Who caused it | `{{actor_tipo}}` | Option | **A client is updated** also carries the previous value of three items: Previous company `{{empresa_anterior}}`, Previous email `{{email_anterior}}` and Previous payment terms `{{terminos_anterior}}`. **A client is deleted** only carries Company and Who caused it. ### Products | Item | Name | Type | |---|---|---| | Name | `{{nombre}}` | Text | | List price | `{{precio_lista}}` | Amount | | Active | `{{activo}}` | Yes or no | | Who caused it | `{{actor_tipo}}` | Option | **A product is updated** also carries Previous list price `{{precio_lista_anterior}}` and Active before `{{activo_anterior}}`. **A product is deleted** only carries Name and Who caused it. ### Tasks and promises | Trigger | Data | |---|---| | A task is created, A task is completed | Title `{{titulo}}`, Who caused it `{{actor_tipo}}` | | A payment promise is recorded | Promised amount `{{monto}}`, Currency `{{moneda}}`, Promised date `{{fecha_promesa}}`, Who caused it `{{actor_tipo}}` | | A payment promise is kept / broken | Promised amount `{{monto}}`, Currency `{{moneda}}`, Who caused it `{{actor_tipo}}` | ### Scheduled trigger | Item | Name | Type | |---|---|---| | Date | `{{fecha}}` | Text | | Day of the week | `{{dia_semana}}` | Text | | Day of the month | `{{dia_mes}}` | Number | | Hour | `{{hora}}` | Number | ## Next - [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar) - [Actions](/en/docs/automatizacion/workflows/acciones) --- # Triggers URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/disparadores Last updated: 2026-10-14 Cord's 48 events and the scheduled trigger that can start a workflow in Cord, grouped by category, with when they happen and the data each one carries. ## How they work - **One per workflow.** To react to two different events, create two workflows. Use **Duplicate** so you do not start from scratch. - **One run per event.** Every time the event happens, an independent run is created. Ten quotes sent are ten runs. - **Forward only.** A workflow reacts to events that happen after it is published, not earlier ones. - **Whoever causes it.** The event counts whether it came from a team member, the client from their link, the API, an AI agent through MCP or another workflow. If the origin matters, use **Who caused it** in a condition. In the editor, click **Add a trigger** and use **Find a trigger** or the categories: **You run it**, **Scheduled**, **Quotes**, **Approvals**, **Payments**, **Invoices**, **Clients**, **Products**, **Tasks and promises** and **Automations**. Before you type anything, the **Suggested** ones come first (the two **You run it** triggers and the scheduled one, which don't depend on something happening in your account) and the rest follow, grouped by category. ## Data they carry Most triggers for the same kind of object share data. To avoid repeating it in every table, these are the groups: | Group | Data | |---|---| | **Quote data** | Number, Client, Total, Currency, Status at the event, Current quote status, Who caused it | | **Invoice data** | Number, Client, Total, Balance due, Currency, Due date, Country, Status at the event, Current invoice status, Who caused it | | **Client data** | Company, Email, Country, Payment terms, Who caused it | | **Product data** | Name, List price, Active, Who caused it | In addition, **every** trigger carries your business data: name, contact email, phone, currency and today's date in your time zone. The exact name of each item for your texts (for example `{{saldo_pendiente}}`) is in [Event data](/en/docs/automatizacion/workflows/datos-del-evento). ## Only when: filter the trigger In the trigger panel, **Add a filter** sets the conditions the event has to meet for the workflow to run, for example "Total is greater than $200,000.00 MXN" or "Number contains MAY". - An event that does not meet it **does not create a run**: it does not appear in **Runs**. That is the difference from putting a condition as the first step, which leaves a run for every event. - The filter reads the data the event carries. What Cord reads live from the document, such as **Current quote status**, cannot be used here: use it in a condition or a wait. - You can require all the conditions or just one, as in a condition. - On the canvas, the trigger says "Only when" with the first condition. - **Test** uses the latest event that meets the filter, among the 20 most recent of that trigger. - The scheduled trigger has no filter: it brings no event to filter. ## How often it enters So the same thing is not repeated, the trigger panel has **How often it enters**: | Option | What it does | |---|---| | **Every time it happens** | Each event creates its run. This is the usual setting. | | **Once per document** | A quote or invoice that already entered does not create another run, even if the event happens again. | | **Once per client** | Counts by client: if a client already entered with one quote, another quote from the same client does not enter again. It only appears on triggers that carry a client. | With **Can enter again after (days)**, the document or client enters again once that many days have passed since the last time; left empty, it never enters again. For example, "Once per client" with 30 days sends a collections reminder at most once a month to each client. - Entering is what counts, not the result: a run that fails also counts. - If the event does not carry that client, the run is created like any other instead of being lost. - It works with the filter: an event that does not pass the filter does not count as an entry. ## You run it Two triggers are started by a person, not by an event: **You run it from a quote** and **You run it from an invoice**. Use them for what has no fixed moment, like asking for a deposit, sending a collections sequence or telling the team about a special sale. | Trigger | When it happens | Data | |---|---|---| | **You run it from a quote** | Someone runs it on one or more quotes. | The same as any quote | | **You run it from an invoice** | Someone runs it on one or more invoices. | The same as any invoice | - **From the document:** on a quote or invoice detail, the **Workflows** section shows the active workflows for that type; click one to run it on that document. - **In bulk:** in the workflow editor, **Run now** opens the list of recent documents; choose up to 50 and each one starts its own run. - **Which version:** always the published one. If the workflow is a draft or paused, it is not offered. - **Who can run it:** whoever has the **Quotes** permission for a quote and **Collections** for an invoice. Actions run with the permissions of whoever published the workflow, as always. - The **Only when…** filter and **How often it enters** apply the same way: a document that does not meet them does not run, and Cord says so. - **Who caused it** is **A team member**; from your own system, with `POST /v1/workflows/{id}/invoke` in the [API](/en/docs/desarrolladores/empezar/resumen) or the `correr_workflow` MCP tool, it is **The API** or **An AI agent (MCP)**. ## Scheduled A workflow does not always react to something: it can also run on a fixed schedule. It is the only trigger you configure yourself. | Field | Detail | |---|---| | **How often** | Every day, every week or every month. | | **Day** | Of the week (Monday to Sunday) or of the month (1 to 28). | | **Time** | On the hour, in **your account's time zone** (Settings › General). It runs in Cord's first check after that time; Cord checks every 5 minutes. | It carries the tick's own data: **Date**, **Day of the week**, **Day of the month** and **Hour**, usable in your text as `{{fecha}}`. The day of the month caps at **28** on purpose: a "31" would silently skip February, and a monthly cut that never goes out is worse than one that goes out three days early. A scheduled trigger carries no quote or invoice, so actions that act on a document — expire, void, email the client — cannot be used there, and the editor says so when you publish. What does fit: [lookups](/en/docs/automatizacion/workflows/consultas) plus an alert to the team, to Slack or to Teams. When you pause a scheduled workflow its next tick is cleared; resuming recalculates it from that moment, so it does not fire the ticks it missed while paused. ## Quotes | Trigger | When it happens | Data | |---|---|---| | **A quote is created** | A new quote is saved, from the app, the API or an agent. | Quote data | | **A quote is sent** | The quote is sent to the client and its link becomes active. | Quote data | | **The client opens the quote** | The client opens the public link. It does not count when someone on your team opens the link to review it. | Quote data | | **A quote is approved** | The quote becomes approved. | Quote data | | **A quote is rejected** | The quote becomes rejected. | Quote data | | **A quote is edited and resent** | A quote that was sent, viewed or expired is sent to the client again, usually after editing it. | Quote data plus **Previous total** | | **A quote expires** | The validity date passes without the quote closing. Cord checks validity once a day. | Quote data | | **A quote is about to expire** | Every day, while the expiration date is 1 to 30 days away and the quote is still sent or viewed. It carries **Days until it expires** and **Expiration date**: a condition picks the exact day you want to act on. | Quote data plus the two date fields | | **A draft is deleted** | A draft quote is deleted. | Quote data, without current status (the quote no longer exists) | | **A message is posted on a quote** | Someone writes in the quote chat. | Quote data, **Who wrote it** (The client or The team) and **Message** | ## Approvals | Trigger | When it happens | Data | |---|---|---| | **A quote requests internal approval** | A quote is created that, under your approval rules, needs sign-off from someone on your team before it is sent. | Quote data and **Reason** | | **An internal approval is decided** | The approver decides. | Quote data and **Decision** (Approved or Rejected) | ## Payments | Trigger | When it happens | Data | |---|---|---| | **A quote is paid in full** | The quote is fully paid. | Quote data | | **A partial payment arrives** | A payment that does not cover the total: a deposit, a balance or an installment. | Quote data, **Amount paid**, **Balance due** and **Payment type** (Deposit, Balance or Installment) | | **A recurring charge fails** | A recurring charge on a quote could not be collected. | Quote data | | **A dispute is opened** | The client's bank opens a dispute on an online payment. | Quote number, Client, **Disputed amount**, Currency, **Reason** and **Response deadline** | | **A dispute is closed** | The dispute is resolved. | Same as the dispute plus **Outcome** (Won, Lost or Closed without dispute) | | **A refund succeeds** | A refund reaches the client. | Quote number, Client, **Refunded amount**, Currency and **Reason** | | **A refund fails** | The refund could not be completed. | Same as the refund plus **Failure reason** | | **A payout is paid to your bank** | Cord Payments deposits your collections in your bank account. | **Payout amount**, Currency and **Arrival date** | | **A payout fails** | Your bank rejects the payout. | Same as the payout plus **Failure reason** | | **Your payments account changes** | What your Cord Payments account can do changes: accept payments, receive payouts, or whether it is missing information. | **Can accept online payments**, **Can receive payouts**, **Pending verification items** and **Restriction reason** | Dispute, refund, payout and payments account events come from Cord Payments, so they only happen if you collect online with Cord. Each one is recorded only once even if the payment processor notifies several times. The quote number and the client come through when the movement belongs to a quote payment; a refund of an invoice payment brings them empty. ## Invoices | Trigger | When it happens | Data | |---|---|---| | **A quote is invoiced** | The quote is marked invoiced with a document that is not a CFDI, for example a commercial invoice outside Mexico or a proforma. | Quote data | | **A quote CFDI is stamped** | The quote is marked invoiced with a CFDI stamped with the SAT. Mexico only. | Quote data | | **An invoice is issued** | A Cord Invoicing invoice is issued and receives its number. | Invoice data | | **An invoice is sent** | The invoice is sent to the client. | Invoice data | | **An invoice is paid** | The invoice becomes paid. | Invoice data | | **An invoice payment fails** | A payment attempt on the invoice did not go through. | Invoice data | | **An invoice becomes overdue** | The due date passes with a balance due. Cord checks this once a day. | Invoice data | | **An invoice is about to be due** | Every day, while the due date is 1 to 30 days away and the invoice is still open with a balance. It carries **Days until due** and **Due date**. | Invoice data plus the two date fields | | **An invoice has been past due for days** | Every day, from the day after the due date and up to 90 days later, while the invoice is still open with a balance. It carries **Days past due**. | Invoice data plus the two date fields | | **An invoice is voided** | The invoice is voided. | Invoice data | | **An invoice is marked uncollectible** | Someone marks the invoice as uncollectible. | Invoice data | ## Clients | Trigger | When it happens | Data | |---|---|---| | **A client is created** | A new client is added. | Client data | | **A client is updated** | A client's data changes, including changes coming from HubSpot. | Client data plus the previous value of Company, Email and Payment terms | | **A client is deleted** | A client is deleted. | Company and Who caused it | ## Products | Trigger | When it happens | Data | |---|---|---| | **A product is created** | A product is added to the catalog. | Product data | | **A product is updated** | A product's data changes. | Product data plus the previous value of List price and Active | | **A product is deleted** | A product is removed from the catalog. | Name and Who caused it | ## Tasks and promises | Trigger | When it happens | Data | |---|---|---| | **A task is created** | A task is added by hand, by another workflow, the API, or MCP. Tasks Cord creates on its own (chargeback, SPEI refund) don't trigger it. | **Title** and Who caused it | | **A task is completed** | A task is marked complete. | Title and Who caused it | | **A payment promise is recorded** | You record that a client promised to pay. | **Promised amount**, **Promised date** and Who caused it | | **A payment promise is kept** | The promise is marked kept. | Promised amount and Who caused it | | **A payment promise is broken** | The promise is marked broken. | Promised amount and Who caused it | ## Automations They tell you how your own workflows end: use them to hear on Slack, Teams or email when an automation needs a person, without checking the **Runs** tab. | Trigger | When it happens | Data | |---|---|---| | **A workflow run fails or needs attention** | A run of another workflow ends **Failed** or stops at **Needs attention**. | **Workflow**, **Document**, **Status**, **Reason** and **Link to its runs** | | **A workflow run completes** | A run of another workflow ends without errors. | Workflow, Document and Link to its runs | - **A workflow is not triggered by its own runs**: the one that reports failures does not report itself when it fails. - To listen to just one, add the condition "Workflow is equal to" with its name. - **Document** is the number or name of what triggered the run, if it has one; for a scheduled workflow it is empty. ## Time-based triggers Three triggers are not caused by a person but by the calendar: **A quote is about to expire**, **An invoice is about to be due** and **An invoice has been past due for days**. Cord checks them once a day and emits them **once per document per day**, with the distance in days as data (**Days until it expires**, **Days until due** or **Days past due**). - **You pick the exact day** with a condition, for example "Days until due equals 3". Without a condition, the workflow would run every day of the period. - **They are only generated if an active workflow listens to them.** If none of your active workflows uses that trigger, Cord does not emit it. - **They are not sent to webhooks, Zapier, Make or n8n**: a subscriber would get the same notice every day. They are exclusive to Cord Workflows, like the scheduled trigger. ## The same events outside Workflows 41 of the 48 events can also be received outside Cord: in your [webhooks](/en/docs/desarrolladores/herramientas/webhooks) and in the [Zapier](/en/docs/automatizacion/integraciones/zapier), [Make](/en/docs/automatizacion/integraciones/make) and [n8n](/en/docs/automatizacion/integraciones/n8n) triggers. The only ones that exist just inside Workflows are the three time-based triggers, the scheduled one, the two about workflow runs and the two you run yourself. | Trigger | In Workflows | In webhooks, Zapier, Make and n8n | |---|---|---| | The 41 quote, approval, payment, invoice, client, product, task and promise events | Yes | Yes, with their technical name (for example `quote.approved`) | | A quote is about to expire | Yes | No | | An invoice is about to be due | Yes | No | | An invoice has been past due for days | Yes | No | | On a fixed schedule | Yes | No | | A workflow run fails or needs attention | Yes | No | | A workflow run completes | Yes | No | | You run it from a quote | Yes | No | | You run it from an invoice | Yes | No | ## Who caused it Quote, approval, quote payment, invoice, client, product, task and promise triggers carry **Who caused it**, with these values: | Value | Meaning | |---|---| | The client | Your client did it from their link: open, approve, reject, pay or write. | | A team member | A person in your organization, from the app. | | The API | An integration using your API key, for example Zapier or Make. | | An AI agent (MCP) | An AI assistant connected through MCP. | | Another workflow | One of your other workflows. | | Cord automatically | A Cord process, such as the daily due-date check, or a change that came from HubSpot. | A typical use: on **A task is created**, add the condition "Who caused it is not Another workflow" so you do not react to tasks created by your own workflows. ## Related - [Conditions](/en/docs/automatizacion/workflows/condiciones): pick the exact day or the case you care about. - [Actions](/en/docs/automatizacion/workflows/acciones): which actions fit each trigger. - [Event data](/en/docs/automatizacion/workflows/datos-del-evento): the exact name of each piece of data. - [Ready-made ideas](/en/docs/automatizacion/workflows/ideas): triggers in use, end to end. --- # Runs and errors URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/ejecuciones Last updated: 2026-10-14 How to read a workflow's Runs tab: statuses, the result of each step, automatic retries and when they happen, retrying by hand with the original version, canceling, and what to do with each error message. ## Where to see them - In the **workflow list**, each card shows the runs from the last 30 days and, if any, how many failed ("N failed"). - Inside the editor, the **Runs** tab shows the 50 most recent, newest first. Click **Refresh** to load the latest. Each row shows the status, the event that started it and when it happened. Tap it to see the detail, and click **View on canvas** to see its path over the flow: with the version it ran with even if the draft has changed, each step with its result (done, with an error or waiting), the branch each decision took and what didn't run dimmed. **Back to editing** returns to the draft. ## Run statuses | Status | Meaning | |---|---| | **Queued** | Created and about to run, or a step failed and it is waiting for its next attempt. The detail shows "Resumes" with the time of that attempt. | | **Running** | Running right now. | | **Waiting** | Reached a wait step. The detail shows "Resumes" with the date. | | **Completed** | Finished every step it had to run. | | **Failed** | A step failed with no attempts left. The following steps did not run. | | **Needs attention** | A send to the client or to another system was cut off without a response, and repeating it could duplicate it. The run stops until someone checks the destination: **It arrived: continue** goes on without repeating it; **It didn't arrive: retry** sends it again. | | **Canceled** | Someone canceled it, or the workflow fell outside the plan or its event stopped existing before it finished. Pausing the workflow cancels nothing: whatever was in progress waits until you resume it. | ## Result of each step In the detail, every evaluated step shows its result: | Result | Meaning | |---|---| | **Done** | The action completed. | | **Error** | The action failed. The reason appears below. | | **Unconfirmed** | The send was cut off without a response: it is not known whether it arrived. See **No effect happens twice**. | | **In progress** | The action is running right now. | | **Met** | The condition was true and the flow took the "met" branch. | | **Not met** | The condition was false and the flow took the "not met" branch. | | **Waiting** | The run reached a wait. | | **Deadline passed** | A **Wait until...** step reached its time limit without the condition being met and continued through "If the time runs out". | Below each step you see what it sent or what it found, exactly as it was recorded: the subject and message of an email, the values a condition compared, what a lookup returned. If an action needed more than one attempt, you also see which one it is on, for example "Attempt 2 of 6". The first line of the detail shows which version of the workflow it ran with. Steps in the branch that was not taken do not appear, because they did not run. ## Automatic retries When an action fails, Cord tells apart what happened: - **It was not done and may go through later.** The destination responded with a temporary error (Slack or HubSpot down, an hourly limit used up). Cord retries it on the schedule below. - **It will not change on its own.** A connection is missing, the client has no email, the URL is not valid. The run becomes **Failed** on the first attempt: fix the cause and click **Retry**. - **It is not known whether it arrived.** The send was cut off without a response. What can be repeated without duplicating is retried; the rest stops. See **No effect happens twice**. Each step has its own attempts, and every attempt continues **from the step that failed**: steps already done are not repeated. If the task was created and the Slack message after it failed, the retry only sends the Slack message. | Attempt | When it runs | Status while it waits | |---|---|---| | 1 | When the event happens | Running | | 2 | About 2 seconds later, in the same run | Running | | 3 | About 15 seconds later, in the same run | Running | | 4 | About an hour later | Queued | | 5 | About 4 hours later | Queued | | 6 | About 12 hours later | Queued | | No more attempts | The run becomes **Failed** with the last error message | Failed | The waits vary a little on purpose, so that many runs do not retry in the same second, and Cord checks the queue every 5 minutes and whenever something happens in your account, so a queued attempt runs in the first check after the time shown. ## No effect happens twice Before performing an action, Cord records in the history that it is about to try it. If something is cut off halfway, Cord knows that step may have happened and does not repeat it blindly: | Action | If the send is cut off without a response | |---|---| | Create a task | It is repeated: the task carries the step's mark, and repeating it does not create another one. | | Send the data to a URL | It is repeated with the same `Idempotency-Key` header, so your destination recognizes the retry and does not process it twice. | | Expire the quote, Approve the internal request, Void the invoice | It is repeated: if the previous attempt already did it, the document is already in that state and nothing else happens. | | Email the team, Slack and Teams | It is repeated: your team may get the alert twice, but it is not lost. | | Email the client | It is repeated with the step's key, which travels with the email: the service Cord sends through remembers it for 24 hours and, meanwhile, a second attempt doesn't reach the client. If your account sends from your Gmail, Gmail doesn't know that key and the step stays **Unconfirmed**, like the WhatsApp. | | Send the client a WhatsApp and Add a note in HubSpot | It is not repeated: what your client sees or another system stores is never sent twice blindly. The step stays **Unconfirmed** and the run **Needs attention** until you say whether it arrived. | A step that was already confirmed is never done again, even if the run is retried. ## Retry by hand On a **Failed** run, click **Retry**. It goes back to **Queued** with the step's attempts reset, continues from the failed step and runs right away. Use it after fixing the cause, for example after reconnecting HubSpot. Retry uses the **published version**: if the cause was in the workflow itself (an empty text, a wrong URL, the WhatsApp variables), fix it, publish and retry; the run continues from the same step even if you moved it. If the run ran with another version, you can also click **With the original version (vN)** to retry it exactly as it started. If the step where it failed no longer exists in the published version, you see "The step where this run failed no longer exists in the published version. Retry it with the original version." In a run that **Needs attention**, check the destination first. If it arrived, click **It arrived: continue**: the step counts as done and the run goes on without repeating it. If it didn't arrive, click **It didn't arrive: retry**: Cord does it again. If you no longer want it to continue, click **Cancel**. Only failed runs or runs that need attention can be retried; otherwise you see "Only failed runs or runs that need attention can be retried." ## Run it again There is no button to repeat a run that already finished (**Completed** or **Canceled**): repeating it could send the same email to the client twice or create the same task twice. Depending on what you need: - **See what it would do with a real event**, without sending anything: use **Test** in the editor. See [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar#test-before-publishing). - **Make it really run again**: cause the event again, for example by resending the quote. Every new event creates its own run. - **Recover a failed run**: **Retry**, as explained above. ## Cancel On a **Queued** or **Waiting** run, click **Cancel**. It becomes **Canceled** and no more steps run. What it already did is not undone. ## Automatic pause If a workflow's last **5 finished runs** failed or ended in **Needs attention**, Cord pauses it so it does not keep failing with every event: - Nothing in progress is lost: it waits at its step, as in any pause. - The person who published it and the account owner get an email, and the editor and the workflow list say why it is paused. - A run that succeeds in between restarts the count. Review its runs, fix what is failing and click **Resume**. To hear about every failure as it happens, not only the pause, create another workflow with the **A workflow run fails or needs attention** [trigger](/en/docs/automatizacion/workflows/disparadores) that notifies Slack, Teams or the team. ## Error messages and what to do Messages appear in your account's language. ### Tasks | Message | Cause | What to do | |---|---|---| | The task title came out empty. | The title only had event data and it arrived empty. | Add fixed text to the title. | | The task could not be created. | Cord rejected the task; for example, the quote it was going to be linked to no longer exists. | If the quote was deleted, retrying won't help. Otherwise, click **Retry** and, if it persists, write to us. | | Workflows reached their hourly limit of tasks. | Your workflows created 120 tasks in one hour. | Check whether a workflow triggers more than expected; retry later. | ### Team email | Message | Cause | What to do | |---|---|---| | There is nobody to send the email to. | The account has no owner with an email, or no active members. | Check **Settings › Team & roles** or change **To**. | | Email is not available right now. | It could not be delivered to anyone. | Cord retries on its own. If it persists, write to contacto@cordhq.app. | | Workflows reached their hourly limit of emails. | 30 emails in one hour. | Consider Slack or Teams for frequent alerts. | ### Client email | Message | Cause | What to do | |---|---|---| | This event does not carry a quote to act on. | The trigger carries no quote, or the quote no longer exists. | Use a quote or invoice trigger. | | This event does not carry an invoice to act on. | The event's invoice no longer exists. | Nothing to retry for that document. | | The client has no email on file. | The document's client has no email. | Add the email to the client and click **Retry**. | | The message came out empty. | The message only had empty data. | Add fixed text. | | You reached your plan's sending limit for this month. | The monthly sending quota ran out (5 on the Free plan). | Wait for next month or upgrade. | | The email to the client could not be sent. | The email service rejected it, usually because the client's address isn't valid, or it stayed overloaded after every retry. A rejection isn't retried: repeating it changes nothing. | Check the client's email and click **Retry**. | | Workflows reached their hourly limit of emails to clients. | 60 client emails in one hour. | Retry later. | ### WhatsApp | Message | Cause | What to do | |---|---|---| | Connect WhatsApp in Settings › Integrations to use this action. | WhatsApp is not connected. | [Connect WhatsApp](/en/docs/automatizacion/integraciones/whatsapp) and click **Retry**. | | The client has no phone with a country code on file. | The client has no phone, or it does not start with `+` and the country code. | Edit the client, save the number with `+` and retry. | | WhatsApp did not accept your template. Check it in Settings › Integrations: it must be approved and have the same number of variables. | The template is not approved, the name does not match, or the number of variables differs. | If the problem is the template, fix it in Meta or in Settings › Integrations and retry. If it is the step's variables, fix them and publish: it applies to new events. | | WhatsApp did not accept the message. It retries on its own. | A temporary rejection. | Nothing; Cord retries. | | Workflows reached their hourly limit of WhatsApp messages. | 60 messages in one hour. | Retry later. | ### Slack | Message | Cause | What to do | |---|---|---| | Connect Slack in Settings › Integrations to use this action. | No Slack URL saved. | [Connect Slack](/en/docs/automatizacion/integraciones/slack) and click **Retry**. | | Slack did not accept the message. Check the connection in Settings › Integrations. | The webhook was deleted or the app was removed from the channel. | Create a new webhook in Slack, paste the URL and retry. | | The message came out empty. | The message only had empty data. | Add fixed text. | | Workflows reached their hourly limit of Slack messages. | 120 messages in one hour. | Retry later. | ### Teams | Message | Cause | What to do | |---|---|---| | Connect Microsoft Teams in Settings › Integrations to use this action. | Teams is not connected. | [Connect Teams](/en/docs/automatizacion/integraciones/teams) and click **Retry**. | | Microsoft no longer accepts the Teams connection. Reconnect it in Settings › Integrations. | With **Connect with Microsoft**, access expired or was revoked. | Click **Reconnect** on the card and retry. | | Teams did not accept the message. Check that the channel or the flow is still active. | The channel no longer exists, you lost access to it, or the Power Automate flow was turned off or deleted. | Pick another channel or paste a new flow URL, and retry. | | The message came out empty. | The message only had empty data. | Add fixed text. | | Workflows reached their hourly limit of Teams messages. | 120 messages in one hour. | Retry later. | ### HubSpot | Message | Cause | What to do | |---|---|---| | HubSpot needs to be reconnected in Settings › Integrations. | Cord's access was revoked. | Click **Reconnect** and retry. | | HubSpot did not accept this step's data. Check the setup in Settings › Integrations. | HubSpot is not connected or needs reconnecting; the quote or client has not reached HubSpot yet, or the trigger has no quote or client; or the Deal or Company was deleted in HubSpot. | Check the connection. If the record has not arrived, wait; if it ends Failed, check that stages are complete and that the trigger is about a quote or client. | | HubSpot did not respond. It retries on its own. | A temporary HubSpot failure. | Nothing; Cord retries. | | The note came out empty. | The note only had empty data. | Add fixed text. | | Workflows reached their hourly limit of HubSpot notes. | 120 notes in one hour. | Retry later. | ### Send the data to a URL | Message | Cause | What to do | |---|---|---| | The destination URL is not valid or points to an internal server. | The URL is not `https` or not on a public server. | Fix the URL and publish. The fix applies to new events; this run keeps the previous URL. | | The destination URL did not accept the request. | The destination responded with an error or did not respond in time. | Check the destination; Cord retries on the schedule above. | | Workflows reached their hourly limit of posts to a URL. | 120 posts in one hour. | Retry later. | ### Document actions | Message | Cause | What to do | |---|---|---| | This event does not carry a quote to act on. | **Expire the quote** or **Approve the internal request** with an event that has no quote. | Use a quote trigger. | | The quote is no longer in a state that allows this action. | When expiring: the quote was already approved, rejected or expired. | Nothing to retry. | | Your current plan does not include internal approvals. | **Approve the internal request** without approvals in your plan. | Internal approvals require the Scale plan or higher. | | This quote no longer has a pending approval request. | Someone already decided it or it was withdrawn. | Nothing to retry. | | This event does not carry an invoice to act on. | **Void the invoice** with an event that has no invoice. | Use an invoice trigger. | | This invoice cannot be voided: review it in Invoices. | It has payments applied (it needs a credit note) or another rule prevents voiding it. | Review it in **Invoices**. | | Workflows reached their hourly limit of changes to quotes. | The hourly cap of workflows for this change. | Check whether a workflow fires more than expected; it retries on its own. | | Workflows reached their hourly limit of voided invoices. | The hourly cap of workflows for this change. | Check whether a workflow fires more than expected; it retries on its own. | ### General | Message | Cause | What to do | |---|---|---| | The workflow was deleted before this run finished. | It was deleted while the run was in progress. | Nothing to retry. | | The send was cut off without a response and we don’t know whether it arrived. So that no one gets it twice, Cord did not retry it: check at the destination and tell us whether it arrived. | An email or WhatsApp to the client, or a note in HubSpot, was cut off without a response. The run is left in **Needs attention**. | Check whether it arrived and click **It arrived: continue** or **It didn't arrive: retry**. | | The person who published this workflow is no longer on the team, so it was paused. Publish it again so it acts with your permissions. | The person who published it left the team or their access was deactivated. No step runs on their behalf. | Publish it again; from then on it acts with your permissions. | | The person who published this workflow no longer has the permission this step needs, so it was paused. Someone who has it needs to publish it again. | The person who published it had that step's permission removed. | Have someone with that permission publish it. See [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar). | | Your current plan does not include this active workflow. | You downgraded and this workflow fell outside the limit. | Pause other workflows or upgrade. See [Limits](/en/docs/automatizacion/workflows/limites). | | The event that started this run no longer exists. | The event record was removed. | Nothing to do. | | The workflow went over the allowed number of steps. | The run went past the maximum number of steps. | Split the rule into two workflows. | | This action is no longer available. | The run used an action Cord retired. | Edit the workflow and publish again. | | This lookup is no longer available. | The run used a lookup Cord retired. | Edit the workflow and publish again. | | Internal error while running the action. | An unexpected Cord failure. | It retries on its own. If it ends Failed, click **Retry** or write to us. | ## The health panel Above the **Workflows** list there is a summary of the last 30 days: how many runs there were, how many completed, how many failed, how many need attention and how many are still running or waiting. In the list, each workflow with runs that need attention says so under its run count. Below it, **Why they failed**: the five most frequent causes, with how many times each one happened, in which workflow it last happened and when. That is the difference between "something is failing" and "Slack disconnected on Tuesday": if one cause has 40 failures and the rest have none, you already know what to fix. The panel shows up as soon as there are runs. If nothing failed in the period, it says so instead of showing an empty list. ## Related - [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar): versions and testing without publishing. - [Limits](/en/docs/automatizacion/workflows/limites): hourly caps that can make a step fail. - [Actions](/en/docs/automatizacion/workflows/acciones): what each action needs to work. --- # Waits URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/esperas Last updated: 2026-10-14 How to pause a workflow for days, business days or hours, also counting from a date on the document, how to wait until something happens with a time limit, and what happens if you pause or edit it while waiting. ## Set up a wait 1. Click **Add a step › Add wait**. **Edit wait** opens. 2. Enter the **Days** (0 to 30) and, if needed, the **Hours**. The other options are explained below. 3. Click **Done**. On the canvas the step reads "Wait 1 day" or "Wait N days". You can add several waits to the same workflow, at the main level or inside a branch. For example: notify at 3 days and again at 7. ## When it continues Days are counted from the moment the run reaches the wait. Once they have passed, the next step runs in Cord's next check. Cord checks every 5 minutes and also whenever something happens in your account (a quote is sent, a payment comes in). Example: a quote is sent on Monday at 16:00 and the workflow waits 3 days. The 3 days are up on Thursday at 16:00, and the next step runs in the first check after that time. Meanwhile the run shows as **Waiting** in the **Runs** tab, with the date it resumes ("Resumes …"). If you need something right away, do not use a wait: put the action directly after the trigger. Actions without a wait run as soon as the event happens. ## Business days, hours and document dates A wait has more options than days: | Option | What it does | |---|---| | **Days** and **Hours** | They add up: "1 day and 4 hours". With 0 days you can wait only hours. | | **Business days only (Monday to Friday)** | Days count Monday to Friday: 1 business day from a Friday lands on Monday. Holidays are not skipped. | | **Continue at a set time** | It continues at that time in your account's time zone, for example "the next business day at 09:00". When a time is chosen, hours are not added. | | **Counts from** | It starts from a date on the document instead of the moment the run reaches the step, before or after it: "3 days before Due date". If you do not choose a time, it continues at 09:00. | The dates you can use are the ones the trigger carries: **Due date** on invoice triggers, **Expiration date** on "A quote is about to expire", **Response deadline** on dispute triggers and **Promised date** on "A payment promise is recorded". - If the calculated moment has already passed (for example, the invoice was sent two days before its due date and the wait is 3 days before), there is nothing to wait for: the run continues right away. - If the document does not have that date, the step fails with "The document does not have the date the wait counts from, so there is no way to know when to continue." ## Wait plus condition: the follow-up pattern A wait is almost always followed by a condition that asks whether something is still the same. That is what the **current status** is for: it is read when the condition is evaluated, not when the event happened. | You want | Trigger | Wait | Condition | |---|---|---|---| | Call if the quote was not opened | A quote is sent | 3 days | Current quote status **is** Sent | | Nudge if approved but not paid | A quote is approved | 5 days | Current quote status **is** Approved | | Escalate an overdue invoice | An invoice becomes overdue | 7 days | Current invoice status **is** Open | If you used **Status at the event** instead of current status, the condition would always answer with the status from days ago, and the follow-up would happen even if the client had already responded. More in [Conditions](/en/docs/automatizacion/workflows/condiciones). ## What happens if something changes during the wait | If while waiting you… | Then | |---|---| | **Publish changes** to the workflow | The run continues with the version it started with. Changes apply to new runs. | | **Pause** the workflow | The run does not move forward while the workflow is paused: it stays on its step and continues when you resume it. If its wait ended in the meantime, it continues as soon as you resume it. | | **Delete** the workflow | The run is canceled. Its history is kept. | | **Downgrade** and the workflow falls outside the limit | If it is still outside the limit when the wait ends, the run is canceled with "Your current plan does not include this active workflow." | | **The quote or invoice changes** | Nothing is interrupted. The following condition reads the new status if it uses the current status. | ## Cancel a waiting run In **Runs**, open the waiting run and click **Cancel**. It becomes **Canceled** and no more steps run. Only **Queued** or **Waiting** runs can be canceled. ## Wait until something happens A plain wait counts days. **Wait until...** counts days *and* watches a condition: the moment it is met, the workflow continues without sitting out the rest of the limit. 1. Click **Add a step › Wait until...**. 2. Define the condition just like a regular one: for example, **Current quote status** is **Viewed**. 3. Set the **Time limit** in days (1 to 30). The step has two branches: | Branch | When it is taken | |---|---| | **If it happens** | The condition was met before the limit ran out. | | **If the time runs out** | The days passed without it being met. | If what you are waiting for happens to the workflow's document (the client opens or approves the quote, the invoice payment comes in), the step continues the moment it happens. Otherwise, Cord checks again as often as it checks waits. The limit is set the first time the run reaches the step and does not move: checking does not push it forward. Example, the "Don’t let a quote go cold" idea: after sending, it waits until the client opens it, with a 2-day limit. If they open it, it creates the task to call while the deal is warm; if not, it emails them and waits another 5 days for a decision. Use **Current status** in these conditions, not **Status at the event**: the status at the event never changes, so a condition on it would always answer the same and the wait would burn the whole limit for nothing. ## End early: the goal A sequence of reminders should not keep going once the client has paid. In the trigger panel, **Add a goal** sets the conditions under which the workflow considers its job done, for example "Current invoice status is Paid". - Cord checks the goal **before each step**, with the data at that moment: if it is met, the run ends as **Completed** without doing what was left, and its details say "Ended early: the workflow's goal was met." - If the run is in a wait of days, an event about its document checks it right away: when the invoice is paid, it ends there instead of waiting for the wait to run out. If something that does not meet the goal wakes it, it goes back to waiting until the same deadline. - Unlike the filter, the goal can read what Cord reads live, such as the current status. - **Test** checks it too: if the document of the latest event already meets it, the test says the run would end early. ## Next - [Event data](/en/docs/automatizacion/workflows/datos-del-evento) - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones) --- # Ready-made ideas URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/ideas Last updated: 2026-10-14 The 9 example workflows Cord ships with, ordered for your business using what you answered when you created your account: which event starts them, what each step does, who they suit, what they need and how to adapt them. ## How to use an idea There are three ways: - In the **Workflows** list, under **Ideas to get started**, click **Use** on the idea. - Inside the editor of an empty workflow, in **Start with an example**, click **Customize this workflow**. If the draft already had steps, Cord asks **Replace what you have?** before replacing them. - With Slack, Teams or HubSpot connected, its page in **Settings › Integrations** shows the ideas that use it. Every way creates a **draft** with the idea's name, trigger and steps, with the texts in your account's language. Nothing runs until you click **Publish**, and before that you can click **Test** to see what it would do with the latest real event. Change whatever you want: amounts, days, texts or recipients. ## Ideas for your business Ideas are ordered using what you answered when you created your account: 1. First, the ones for your **industry**: for example, "Start the work when the deposit arrives" if you are in construction, manufacturing or services. 2. Then, the ones for the **goals** you chose (quote faster, collect payments online, issue invoices, follow up on quotes, control margins or automate collections), in the order that matters to your **role**: Finance gets invoicing and collecting first; Sales, quoting and following up. 3. Then the ones for your role, and finally the rest. Each card says why we suggest it, for example "You chose “collect payments online”", "Because you work in Finance / Admin" or "For your industry: construction". If you did not answer those questions, you see all nine in the order of this page. Each idea is also built for your account when you use it: - **Team alerts** go out through Slack if you have it connected; if not, through Teams; and if not, by email to the account owner. - **With HubSpot connected**, "The invoice goes out when you get paid" also leaves the note on the Deal. - **"Large quotes go to the owner for approval"** only appears if your plan includes internal approvals and you do not work alone: without a team there is nobody to ask. ## At a glance | Idea | Trigger | Needs | Suggested first if | |---|---|---|---| | [Don’t let a quote go cold](#1-dont-let-a-quote-go-cold) | A quote is sent | Client with an email | You chose "follow up on quotes" or "quote faster", or you work in Sales | | [Reminder 3 days before](#2-payment-reminder-3-days-before-the-due-date) | An invoice is about to be due | Invoices with a due date, client with an email | You chose "collect payments online" or "automate collections", or you work in Finance | | [Collections that step up](#3-collections-that-step-up) | An invoice has been past due for days | Invoices with a due date, client with an email | You chose "automate collections" or "collect payments online", or you work in Finance | | [The invoice goes out when you get paid](#4-the-invoice-goes-out-when-you-get-paid) | A quote is paid in full | Nothing extra | You chose "issue invoices", or you work in Finance | | [Your Monday](#5-your-monday-collected-overdue-and-who-to-call) | On a fixed schedule | Nothing extra | You run the business or work in Finance | | [Push an invoice to get paid](#6-push-an-invoice-to-get-paid) | You run it from an invoice | Client with an email | You chose "collect payments online", or you work in Sales or Finance | | [Last call and close-out](#7-last-call-and-quote-close-out) | A quote is about to expire | Quotes with a validity date, client with an email | You chose "quote faster", or you are in distribution or manufacturing | | [Start on the deposit](#8-start-the-work-when-the-deposit-arrives) | A partial payment arrives | Quotes with a deposit | You are in construction, manufacturing or services | | [Owner approval](#9-large-quotes-go-to-the-owner-for-approval) | A quote requests internal approval | Scale plan or higher and a team | You chose "control margins" or you run the business | ## 1. Don’t let a quote go cold So no quote gets lost in silence. **Which business:** agencies, firms, industrial suppliers or any team that sends many quotes a week and has no time to check one by one who opened them. 1. **Trigger:** a quote is sent. 2. **Wait until** the **Current quote status** is **Viewed** or **Approved** (two rules joined with Or), with a **2-day** limit. 3. **If it happens:** create the task "Call `{{cliente}}` while `{{folio}}` is warm", due in 1 day. The client has seen it: it is time to call. 4. **If the time runs out:** email the client with the subject "Any questions about `{{folio}}`?" and the message "Hi, we are following up on quote `{{folio}}` for `{{total}}`. If anything needs adjusting, reply to this email and we will sort it out." 5. **Then wait until** the status is **Approved** or **Rejected**, with a **5-day** limit. If the client decides, the run ends there. 6. **If there is still no decision:** look up the client's balance and alert you: "`{{folio}}` went a week without a decision", with the open balance with you (`{{cliente_saldo}}`, of which `{{cliente_vencido}}` is overdue). - **Needs:** the client with an email on file. The email to the client uses your plan's sending quota. - **Adapt it:** change the time limits, or remove the client email if you want the follow-up to stay within the team. ## 2. Payment reminder 3 days before the due date To collect before the date, not after. **Which business:** recurring services, retainers and any business with receivables where the client pays on time if reminded. 1. **Trigger:** an invoice is about to be due. It happens every day while there are 1 to 30 days left and the invoice is still open with a balance. 2. **Condition:** **Days until due** equals **3**. 3. **If the condition is met:** **Remind the client to pay**, Cord's reminder with what they owe, when it is due and the button to pay. If there is no balance left or their reminders are paused, it is not sent. - **Needs:** invoices with a due date and the client with an email. - **Adapt it:** change the 3 to the days you want, or add a second condition to also remind them on the due date. ## 3. Collections that step up To chase the money with judgment, not with a single email. **Which business:** distributors, wholesalers and services that invoice on 30 or 60-day credit and need an even collections process. 1. **Trigger:** an invoice has been past due for days. It happens every day while it stays open with a balance, for up to 90 days. 2. **Multiple branches**, one per stage, by **Days past due**: - **Day 3:** **Remind the client to pay**, with the button to pay. - **Day 10:** email the client more firmly, with the subject "Invoice `{{numero}}` is 10 days past due", asking them to confirm when they will pay and offering to review the invoice if anything needs correcting. - **Day 20:** look up everything the client owes you, alert you with "`{{cliente}}`: 20 days past due" (the total open, the overdue amount and across how many documents) and leave you the task "Call `{{cliente}}` about invoice `{{numero}}` (`{{saldo}}`)". 3. **Otherwise** it does nothing: on the other days the run ends with no steps. - **Needs:** invoices with a due date and the client with an email. - **Adapt it:** change the day of each branch, or add a fourth one at 30 with an approval to decide whether to stop credit. More in [Multiple branches](/en/docs/automatizacion/workflows/condiciones#multiple-branches). ## 4. The invoice goes out when you get paid So no paid sale is left without an invoice. **Which business:** any business that invoices when it gets paid, and in Mexico anyone who issues the CFDI as soon as the client pays. 1. **Trigger:** a quote is paid in full. 2. **Action:** **Invoice the quote**, the same as clicking **Invoice**, with your country's rules. If the quote was already invoiced, it does not issue another one. 3. **With HubSpot connected:** **Add a note in HubSpot** with "`{{cliente}}` paid `{{folio}}` for `{{total}}`. The invoice was issued in Cord." - **Needs:** nothing extra; in Mexico, your invoicing setup ready to stamp. - **Adapt it:** add a team alert or a delivery task after invoicing. ## 5. Your Monday: collected, overdue and who to call To start the week knowing how much came in, how much is still owed and whom to call. **Which business:** owners and finance leads who want the week's number without opening the app. 1. **Trigger:** on a fixed schedule, every week, on Monday at 9 (in your account's time zone). 2. **Look up** what was collected in the last 7 days, overdue receivables and the open pipeline. 3. **Alert you** with "Your week in Cord (`{{fecha}}`)": what was collected and across how many payments, what is overdue and how many days the oldest one is past due, and what is left to close in quotes. 4. **For each** overdue charge, up to 20: if **Days overdue** is between **30 and 36**, leave you the task "Call `{{item_cliente}}` about `{{item_folio}}`: `{{item_saldo}}`, `{{item_dias_vencido}}` days overdue". That way each charge asks you for a call only once, on the Monday of the week it crosses 30 days. - **Needs:** nothing extra. - **Adapt it:** make it monthly on day 1, or change the 30 days to whatever your credit policy says. More in [For each](/en/docs/automatizacion/workflows/por-cada). ## 6. Push an invoice to get paid For when you decide an invoice can no longer wait. **Which business:** anyone who sells on credit and prefers to decide case by case whom to press, without building an automatic sequence for every invoice. 1. **Trigger:** you run it from an invoice, or from several at once. See [You run it](/en/docs/automatizacion/workflows/disparadores#you-run-it). 2. **Ends early if…** the **Current invoice status** is **Paid**: as soon as the client pays, the run ends. 3. **Action:** **Remind the client to pay**. 4. **Wait** 3 days, business days only. 5. **Action:** leave you the task "Call `{{cliente}}`: `{{numero}}` is still unpaid (`{{saldo}}`)", due that same day. - **Needs:** the client with an email. Running it requires the **Collections** permission. - **Adapt it:** change the days of the wait, or add a second reminder before the task. More about the goal in [End early: the goal](/en/docs/automatizacion/workflows/esperas#end-early-the-goal). ## 7. Last call and quote close-out To close the loop instead of leaving quotes open forever. **Which business:** anyone quoting prices that change (materials, imports, exchange rates, seasons) who cannot honor an old quote. 1. **Trigger:** a quote is about to expire. It happens every day while there are 1 to 30 days left and the quote is still sent or viewed. 2. **Condition:** **Days until it expires** equals **2**. 3. **If the condition is met:** email the client with the subject "Quote `{{folio}}` expires on `{{vence}}`" inviting them to approve it from the link. 4. **Wait until** the status is **Approved** or **Rejected**, with a **2-day** limit. 5. **If the time runs out:** expire the quote (the client can no longer approve it from the link) and alert you: "`{{folio}}` expired without an answer". - **Needs:** quotes with a validity date and the client with an email. - **Adapt it:** remove the **Expire the quote** step if you prefer to close it by hand. ## 8. Start the work when the deposit arrives So nobody starts without money, and nobody is left waiting once it has arrived. **Which business:** construction, workshops, made-to-order manufacturing, events or consulting: anything that charges a deposit before starting. 1. **Trigger:** a partial payment arrives. 2. **Condition:** the **Payment type** is **Deposit**. 3. **If the condition is met:** create the task "Start the work for `{{folio}}` (`{{cliente}}`)" due in 1 day, and alert you: "A deposit of `{{monto}}` arrived. Remaining balance: `{{saldo_pendiente}}`." - **Needs:** quotes with a deposit. See [Deposits](/en/docs/pagos/anticipos). - **Adapt it:** assign the task to whoever starts the work in **Assignee**. ## 9. Large quotes go to the owner for approval So a small approval waits for nobody, and a large one does not go out without the owner's sign-off. **Which business:** sales teams where a discount or a large amount needs the owner's sign-off, but most requests are small. 1. **Trigger:** a quote requests internal approval. 2. **Condition:** the **Total** is less than the amount you choose, in your business's currency. 3. **If the condition is met:** **Approve the internal request**; the quote goes out to the client. 4. **If the condition isn't met:** **Ask for approval** from the account owner, with one day to decide and the message "`{{folio}}` for `{{cliente}}` (`{{total}}`) needs approval. Reason: `{{motivo}}`". With Slack connected, they are also notified there. 5. **If approved:** approve the internal request. **If rejected or time runs out:** tell the team that `{{folio}}` was not approved and that it stays pending on the quote for someone to review. - **Needs:** internal approvals, which come with the **Scale** plan or higher, the **Approvals** permission to publish it, and someone else on the team. - **Adapt it:** the amount is your business's decision, so the idea arrives with the value empty and cannot be published until you type it. If you sell in several currencies, add one rule per currency joined with **Or**. More in [Ask for approval](/en/docs/automatizacion/workflows/aprobaciones). ## Combining ideas An idea is a starting point, not a limit. For example, you can add to "Collections that step up" a branch at 30 days that asks the owner for approval and, if they give it, pauses that client's reminders; or add to "Your Monday" a condition so it alerts you only when the overdue amount goes over a set amount. Whatever shares a trigger fits in a single workflow, and on the Free and Starter plans that also saves active-workflow slots. ## Related - [Create your first workflow](/en/docs/automatizacion/workflows/primer-workflow) - [Triggers](/en/docs/automatizacion/workflows/disparadores) - [Actions](/en/docs/automatizacion/workflows/acciones) - [Publish, pause and delete](/en/docs/automatizacion/workflows/publicar) --- # Limits URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/limites Last updated: 2026-10-14 Cord Workflows limits: active workflows per plan, what happens when you downgrade, workflow size, hourly caps per action and loop protection. ## Active workflows per plan | Plan | Active workflows | |---|---| | Free | 1 | | Starter | 5 | | Pro | Unlimited | | Scale | Unlimited | | Developer | Unlimited | - Only **Active** workflows count. Drafts and paused workflows take no slot, and you can have as many as you want. - **Runs are unlimited**: an active workflow runs every time its event happens. - The workflow list shows your usage: "N of M active workflows on your plan". If you reach the limit and want to publish or resume another one, you see "Your plan allows N active workflows. Pause one or upgrade to publish this one." ## What happens if you downgrade Your workflows are not deleted or paused automatically. Cord keeps running **the oldest ones** that fit in your new plan, in the order they were created. The rest stay marked active, but their events no longer create runs, and runs that were queued or waiting are canceled when they continue, with "Your current plan does not include this active workflow." To choose which ones keep running, pause the ones you do not need. When you upgrade again, the ones left out start running again with new events. Example: you had 4 active workflows on Starter and move to Free. Only the first one you created keeps running; the other 3 stop firing until you pause the first or go back to Starter. ## Workflow size | Limit | Value | |---|---| | Triggers per workflow | 1 | | Steps per workflow, across all branches | 30 | | Step levels (the main level and branches inside branches) | 4, meaning up to 3 conditions nested inside each other | | Rules per condition | 5 | | Days per wait | 0 to 30, plus hours or a time of day | | Time limit on a conditional wait | 1 to 30 days | | Branches in a multi-branch step | Up to 5, plus "Otherwise" | | Items a "For each" goes through in a run | 1 to 50 | | Time to decide an approval | 1 to 30 days | | Day of the month on a scheduled trigger | 1 to 28 | | Workflow name | 120 characters | Lookups, conditional waits and "For each" steps count as steps, the same as an action; steps inside a branch or a "For each" count too. At 30, the editor no longer lets you add or duplicate steps. If you need more, split the rule into two workflows with different triggers. ## Text length | Field | Maximum | |---|---| | Task title | 200 characters | | Due in (days) | 0 to 365 | | Email subject | 150 characters | | Email message | 2,000 characters | | Slack message | 1,000 characters | | Teams message | 1,000 characters | | WhatsApp variables | Up to 4, 200 characters each | | HubSpot note | 2,000 characters | | Client email subject | 150 characters | | Client email message | 2,000 characters | | POST destination URL | 300 characters | | POST message | 1,000 characters | | Void reason | 200 characters | | Recipients with "The whole team" | The first 25 active members | ## Hourly caps So a configuration mistake does not flood your team, each organization has an hourly maximum for what **all** its workflows do together: | Action | Maximum per hour | |---|---| | Create a task | 120 | | Email the team | 30 | | Send a Slack message | 120 | | Send a Teams message | 120 | | Send the client a WhatsApp | 60 | | Add a note in HubSpot | 120 | | Email the client | 60 (and it uses your plan's sending quota: 5 a month on Free, no cap on the other plans) | | Send the data to a URL | 120 | | Expire the quote and Approve the internal request, combined | 120 | | Void the invoice | 30 | When exceeded, the step fails with a message like "Workflows reached their hourly limit of tasks." and the step is retried later, on the schedule in [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones). If you see these often, check whether a workflow fires on an event more frequent than you thought, such as **A client is updated** or **The client opens the quote**. ## Loop protection A workflow can cause events: creating a task fires **A task is created**. So that never becomes an infinite loop: - **A workflow is not triggered by its own events.** If your "New tasks" workflow creates a task, that task does not trigger "New tasks" again. - **Chains stop at 3 levels.** Workflow A can trigger B, and B can trigger C, but what C causes no longer triggers workflows. Two workflows that trigger each other stop on their own. To know in a condition whether an event came from another workflow, use **Who caused it is Another workflow**. ## Next - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones) - [Integrations](/en/docs/automatizacion/integraciones) --- # For each URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/por-cada Last updated: 2026-10-14 How to go through a list of charges inside a workflow: each overdue charge, a client's overdue charges or what is due soon, with every action working on its item's document. ## What it is for A [lookup](/en/docs/automatizacion/workflows/consultas) brings a total: "you are owed 125,000 across 4 documents". That is enough to notify yourself, but not to email each client about their invoice. **For each** goes through the documents one by one. Every action inside works on the item's document, as if the event had been about that document. ## How to add it 1. Click **Add a step › For each**. 2. In the panel, choose the list under **Goes through**. If the list has days, adjust them. 3. Set **Up to how many items**: from 1 to 50, and 20 if you leave it. 4. On the canvas, add the steps inside the **For each item** frame. ## The lists | List | What it goes through | Order | |---|---|---| | **Each overdue charge** | Invoices and quotes with a balance past their due date. | From the most overdue to the most recent. | | **Each of the client's overdue charges** | What the event's client has overdue. | From the most overdue to the most recent. | | **Each charge about to be due** | What is due over the next days you choose (1 to 30). | From the soonest to the latest. | The items are taken **when the step starts**: what it goes through does not change halfway, even if someone pays in the meantime. **Each of the client's overdue charges** uses the event's client, so it only works with triggers that carry one: quotes, invoices, payments and clients. With a scheduled trigger, the workflow cannot be published with that list. ## What each round reads | Variable | What it is | |---|---| | `{{item_folio}}` | The invoice or quote number. | | `{{item_cliente}}` | The client's name. | | `{{item_saldo}}` | What is left to pay, in the document's currency. | | `{{item_moneda}}` | The document's currency. | | `{{item_vence}}` | The due date. | | `{{item_dias_vencido}}` | How many days it has been overdue. For what is not due yet it is zero or a negative number. | | `{{item_origen}}` | Whether it is an invoice or a quote. | These variables only exist **inside** the step. If you use them outside, the workflow is not published and the editor says so: "The variable `{{item_folio}}` belongs to each item: it only exists inside "For each"." Conditions inside can read them too, for example "Days overdue is at least 7". ## Which document each action works on Inside **For each**, **Email the client**, **Send the client a WhatsApp**, **Create a task** and **Add a note in HubSpot** use the item's document and client, not the event's. **Send the data to a URL** sends the type and id of the item's document. ## What cannot go inside - **Waits**: every round runs right away, one after another. If you want to space the messages out, schedule the workflow; for example, every Monday. - **Another For each**. - **Actions for a single type of document**: **Expire the quote**, **Approve the internal request** and **Void the invoice**. A list mixes invoices and quotes. ## If something fails halfway Each round leaves its own record under **Runs**: "Round 1", "Round 2" and so on. The **For each** step says how many items it went through. If a step is retrying in round 3, it picks up in that round when it resumes. What already went out in rounds 1 and 2 is not repeated, and each client gets their email only once. ## A complete example "Your Monday: collected, overdue and who to call", one of the ideas Cord includes, ends with a "For each": 1. **When this happens:** every Monday at 9, after the weekly summary. 2. **For each:** each overdue charge, up to 20. 3. **Condition, inside:** "Days overdue is at least 30" and "Days overdue is at most 36": only the ones that crossed 30 days that week. 4. **Action, if the condition is met:** create the task "Call `{{item_cliente}}` about `{{item_folio}}`: `{{item_saldo}}`, `{{item_dias_vencido}}` days overdue". Each charge asks for its call only once. ## Limits | Limit | Value | |---|---| | Items per run | From 1 to 50; 20 if you leave it | | For each inside another | Not allowed | | Waits inside | Not allowed | The step and the ones inside count toward the maximum of 30 steps per workflow. Each action's hourly limits still apply: if client emails reach their limit, that step is retried later. ## Next - [Lookups](/en/docs/automatizacion/workflows/consultas) - [Conditions](/en/docs/automatizacion/workflows/condiciones) - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones) --- # Create your first workflow URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/primer-workflow Last updated: 2026-10-07 A complete walkthrough of the Cord Workflows editor: create, choose the trigger, add steps, save, publish and check that it works. ## Before you start - You need the **Settings** permission in your organization. - Put the rule in one sentence: "when **this happens**, **do this**". For example: "when the client rejects a quote, create a task to call them tomorrow". - If your rule uses Slack, Teams, WhatsApp or HubSpot, connect them first in **Settings › Integrations**. You can build the workflow without them, but those steps will fail when they run. ## 1. Create the workflow 1. **Open Workflows** in the sidebar and click **New workflow**. 2. **Choose how to start.** While the workflow is empty, Cord opens **Start with an example**: a gallery of ready-made ideas. Click **Customize this workflow** on the one closest to what you want, or close the gallery to start from scratch. 3. **Name it.** Click the title in the top bar ("Untitled workflow") and type something that explains the rule, for example "Win back rejected quotes". Up to 120 characters; it cannot be empty. **Describe it and Cord builds it.** In the same gallery, write the rule in a sentence or two (for example "when an invoice is 7 days overdue, email the client; if it is still unpaid at 14, notify me") and click **Build with AI**. Cord builds a draft with a trigger and steps using only what it can do, and loads it in the editor for you to review. Anything left to fill in (a person to notify, an amount, a text) is flagged. AI never publishes: you decide when. You can build up to 20 drafts a day per organization. Another way to start: in the workflow list, the **Ideas to get started** section has a **Use** button on each idea that creates the draft directly from it. You can reopen the gallery at any time from **Not sure where to start? › View examples**. If you already have steps, Cord asks **Replace what you have?** before replacing the trigger and steps of the draft. ## 2. Choose the trigger 1. In the **When this happens** block, click **Add a trigger**. 2. **Search or filter.** Type in **Find a trigger** (for example "reject"; accents are optional) or use the categories, from **You run it** to **Automations**. Use the arrow keys to move through the list and Enter to pick the first one; the current trigger has a check mark. 3. **Select the event.** The trigger card sits at the top of the canvas. To change it later, open it and click **Change**. The trigger decides which data is available in the rest of the workflow. A quote carries number, client and total; a payout carries amount, currency and arrival date. If you switch to a trigger that does not carry data you already used, Cord flags it when you publish. The full list is in [Triggers](/en/docs/automatizacion/workflows/disparadores). ## 3. Add steps Below the trigger, under **Do this**, click **Add a step** and choose: - **Action or lookup:** one of the 11 [actions](/en/docs/automatizacion/workflows/acciones) (create a task, email the team, email the client, send the client a WhatsApp, expire the quote, approve the internal request, void the invoice, send the data to a URL, send a Slack or Teams message, or add a note in HubSpot) or a [lookup](/en/docs/automatizacion/workflows/consultas). - **Add condition:** split the flow into **If the condition is met** and **If the condition isn't met**. - **Add wait:** pause for 1 to 30 days. - **Wait until...:** pause until a condition is met, with a deadline of 1 to 30 days. Adding a step opens the side panel to configure it (**Edit action**, **Edit condition** or **Edit wait**). Fill in the fields and click **Done**. Each card on the canvas shows a summary: the task title, "Wait 3 days", or the first condition followed by "and 2 more". Inside a condition, each branch has its own button to add steps. Steps you place there only run in that branch. ### Event data in your texts Action text fields show **Event data**: tap an item to insert it at the cursor. It is inserted as `{{cliente}}` and replaced with the real value when the workflow runs. Items marked "checked at run time" are read at that moment, not when the event happened. More in [Event data](/en/docs/automatizacion/workflows/datos-del-evento). ### Reorder, copy and delete steps Each card has a **Step options** menu with **Move up**, **Move down**, **Duplicate step**, **Copy step** and **Delete step**. Duplicating or copying a condition also includes the steps in its branches. - **Copy and paste:** after **Copy step**, the **Add a step** menu offers **Paste copied step** in that spot. On desktop, Cmd+C and Cmd+V (Ctrl+C and Ctrl+V on Windows) also work with a step selected, even to paste it into another workflow. The pasted step gets new identifiers. - **Drag:** on desktop, drag a card and drop it on a **+**, on **Add a step** in any branch or on a branch's name to put it first. - **What doesn't fit isn't pasted or dropped:** a "For each" can't hold waits, approvals or another "For each", and steps go up to 4 levels deep. Cord says so and leaves the workflow as it was. - **Undo and redo:** the buttons in the corner of the canvas undo any change to the definition: a step deleted, moved or pasted, or what you typed in a panel (continuous typing is undone in one go). On desktop also with Cmd+Z and Cmd+Shift+Z (Ctrl+Z and Ctrl+Y on Windows). Inside a text field, those shortcuts undo the text. ### Moving around the canvas On desktop use **Zoom in**, **Zoom out** and **Fit to screen** for long workflows. With the keyboard, Tab reaches the cards, the up and down arrows go through the flow in reading order, left and right jump to the neighboring branch, Enter opens the step and Delete removes it. The Escape key closes, in this order, the example gallery, the trigger picker, open menus and the side panel. On a phone the panel opens over the screen and closes with **Close** or **Done**. ## 4. Save the draft Click **Save draft** (or Cmd+S / Ctrl+S on desktop). You will see "Draft saved". While something is unsaved, the browser warns you if you try to leave the page. Saving **does not activate anything**. The draft can stay incomplete as long as you want. ## 5. Publish Click **Publish**. Before activating the workflow, Cord checks that it is complete. If something is missing, you see "To fix before publishing: N" and the step with the problem is highlighted. The most common messages: | Message | What is missing | |---|---| | Choose which event starts the workflow. | There is no trigger. | | Add at least one step. | The workflow has no steps. | | Choose what this step does. | An action step is empty. | | Fill in "Task title". | A required action field is empty. | | The variable `{{x}}` does not exist for this event. | You used data that trigger does not carry. | | Add at least one condition. | A condition has no rules. | | Fill in the value for "Total". | A comparison has no value. | When published you see "Workflow published" and the status becomes **Active**. If your plan does not allow more active workflows, Cord tells you and does not activate it; see [Limits](/en/docs/automatizacion/workflows/limites). ## 6. Check that it works 1. **Cause the event** with a test case: for example, send a quote to your own email or reject a test quote from its link. 2. **Open the Runs tab** of the workflow and click **Refresh**. A new run should appear. 3. **Review each step.** Each one shows **Done**, **Met**, **Not met**, **Waiting** or **Error**, with its detail. If a step failed, the message tells you what happened and what to do. See [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones). A workflow only reacts to events that happen **after** it is published. It does not run on earlier quotes, invoices or payments. ## Next - [Ready-made ideas](/en/docs/automatizacion/workflows/ideas) - [Actions](/en/docs/automatizacion/workflows/acciones) - [Conditions](/en/docs/automatizacion/workflows/condiciones) --- # Publish, pause and delete URL: https://docs.cordhq.app/en/docs/automatizacion/workflows/publicar Last updated: 2026-10-14 The life cycle of a workflow in Cord: draft and published version, versions, testing without publishing, unpublished changes, pausing, resuming, duplicating and deleting. ## The three statuses | Status | Meaning | Does it run? | Counts toward the plan limit? | |---|---|---|---| | **Draft** | Never published. | No | No | | **Active** | Has a published version and is on. | Yes | Yes | | **Paused** | Has a published version but is off. | No | No | ## Draft and published version Every workflow has two copies: - The **draft**, which is what you see and edit in the editor. - The **published version**, which is what runs when the event happens. While you edit, the published version keeps running unchanged. If the two differ, the editor shows **Unpublished changes** and the button reads **Publish changes**. ### Save the draft **Save draft** (or Cmd+S / Ctrl+S on desktop) saves the name and steps. It does not validate anything or affect what is running, so you can save work in progress. The name is required: if you leave it empty you see "Give the workflow a name." If someone else saved the same workflow while you were editing it, Save does not overwrite their changes: you see "Someone else saved changes to this workflow while you were editing it. Reload the page to see the latest version: your changes were not saved." ### Publish **Publish** (or **Publish changes**) does four things: 1. **Checks** that the draft is complete. If something is missing, it does not publish and shows "To fix before publishing: N" with each problem highlighted on its step. 2. **Checks your permissions.** The workflow will act with yours, so you cannot publish a step you could not do by hand. The editor marks the step you are missing, for example: "To publish this step you need the "Approvals" permission." See **Which permissions it acts with** below. 3. **Checks your plan** if the workflow was not active. If you already reached the maximum of active workflows, you see "Your plan allows N active workflows. Pause one or upgrade to publish this one." 4. **Copies the draft to the published version**, bumps the version number and makes the workflow **Active**. Publishing changes to a workflow that was already active does not use another slot. Before publishing, the button asks you **What changed?**. The note is optional, up to 280 characters, and it stays in the **Versions** tab and on every run that uses that version. In the same window, **What will happen** sums up the effect of publishing what is on screen: - how many times the trigger happened in the last 30 days and, if you set an **Only when…** filter, how many of those meet it (in a very busy account the 300 most recent are checked, and it says so); - in a scheduled workflow, when it runs next; - how many runs are still in progress and which version they will finish with. Publishing does not run the workflow on what already happened: it starts with the next event. ## Versions Every time you publish, the published version is replaced by a **new version**, and Cord numbers each publish. What matters about that numbering: - **Each run remembers its version.** When it is created, the run keeps a full copy of the version published at that moment: its steps, its texts and its time limits. It runs with that copy from start to finish, even if a wait makes it last days. In **Runs**, the details of each run say which version it ran with and that version's note. - **A new version only applies to new events.** Queued or waiting runs carry on with the version they started with. When you retry a failed run you can use the new version: that is what **Retry** does. - **Every version stays in the history.** The **Versions** tab lists each publication, newest first, with when and who published it and its note; the one that is running says **Current**. **Restore as draft** copies a version into the draft so you can review it and publish it as a new version: what runs does not change until you publish. | You want to | Do this | |---|---| | Try a change without affecting what runs | Edit it in the draft, click **Save draft** and **Test**. Do not publish yet. | | Make the change apply right away | **Publish changes**. It applies to events from that moment on. | | Make a waiting run use the change | You cannot: cancel it and let the next event create one with the new version. | | Fix the text of a run that failed | Publish the change and click **Retry** on the run: it runs with the published version from the step that failed. | | Go back to a previous version | In **Versions**, click **Restore as draft** on that version and publish. | ## Test before publishing The **Test** button, next to Save, runs the draft **with the latest real event of its trigger**. It is the same run the published workflow would make, on the same engine, except that nothing leaves Cord: - **Conditions** and **lookups** read your real data: you see which branch it would take. - Each **action** is built exactly as it would go out — the subject and body your client would get, the data of a POST — and is not sent. Whatever would fail in production fails here too, for the same reason: a message that ended up empty, an internal URL, a header that can no longer be read. - **Waits** count as finished: the test moves the clock forward and keeps going, so you see the whole flow in one go, with the dates of that moment. A wait-until whose condition isn't met reaches its deadline and continues through **If the time runs out**. - The test runs with **your** permissions, because you are the one who would publish it: a step you couldn't publish tells you which permission is missing. The result reads just like a run in the **Runs** tab: each step with what it received and what it would do. The canvas also paints the path: each step that would run gets its mark, the branch each decision would take is highlighted and what wouldn't run is dimmed. While you view the path, the canvas can't be edited; **Back to editing**, or closing the test, returns it. If the trigger has never happened in your account yet, the test says so: there is nothing to test with. Make the event happen once (for example, send a test quote) and try again. Testing doesn't create a run, leaves nothing in the history and doesn't use your sending quota. ## What happens to runs in progress Each run keeps a copy of the version published **when the event happened**. If you publish changes, runs already queued or waiting finish with the previous version; new ones use the new version. That way a change never leaves a run halfway with steps that no longer exist. ## Which permissions it acts with A workflow only does what **the person who published it** could do by hand. Each action asks for the same permission as that action done from the app: | Action | Publisher's permission | |---|---| | Approve the internal request | Approvals | | Void the invoice | Collections | | Email the client, Send the client a WhatsApp and Expire the quote | Quotes | | Create a task | Quotes, Collections or Clients | | Send the data to a URL | Settings | | Email the team, Slack, Teams and HubSpot | None extra | The account owner has all of them. Cord checks the permissions again **before each action**, also when a run continues after a wait: - If the person who published it **is no longer on the team**, no step runs on their behalf: the run fails with "The person who published this workflow is no longer on the team, so it was paused." and the workflow is paused. - If they **no longer have the permission** for a step, that step does not run, the run fails with "The person who published this workflow no longer has the permission this step needs, so it was paused." and the workflow is paused. To turn it back on, someone with the permission for all its steps publishes it again, and from that moment it acts with theirs. **Resume** is not enough, because it does not change who answers for the workflow. When a workflow approves an internal request, the quote's activity says so: "Approved by a workflow and sent to the client". ## Pause and resume From the editor's **More actions** menu: - **Pause** turns the workflow off. It stops creating new runs and frees its slot in the plan limit. You see "Workflow paused. Runs already in progress wait until you resume it." - **Resume** turns it back on with its latest published version and you see "Workflow resumed". If your plan has no room, you see the same limit message as when publishing. If the person who published it can no longer perform all of its steps, you see "The person who published this workflow can no longer perform all of its steps. Publish it again to turn it back on." Cord also pauses a workflow on its own in two cases: when the person who published it loses a permission one of its steps needs (see **Which permissions it acts with**) and when its last 5 runs fail or need attention (see [Automatic pause](/en/docs/automatizacion/workflows/ejecuciones)). The editor and the list say why, and the notice goes away when you resume it or publish it again. Only a workflow that has been published at least once can be paused or resumed. A draft shows "Publish the workflow before pausing or resuming it." Events that happen while it is paused **are not recovered** when you resume. Whatever was already in progress **is not lost**: queued or waiting runs stay on their step and continue when you resume it, and if their wait ended in the meantime, they continue as soon as you resume it. To discard one, cancel it in **Runs**; to discard them all at once, use **Cancel waiting runs** in the workflow's menu, which tells you how many there are before it does anything. Pausing and canceling are separate decisions: pausing keeps them, canceling stops them for good. ## Duplicate **Duplicate** creates a new workflow named "*Name* (copy)" with a copy of the draft. The copy starts as a **Draft**, with no run history, and must be published separately. It is the quick way to have two similar workflows with different triggers. ## Delete **Delete workflow** removes it from your list and it stops running: queued or waiting runs are canceled. **It cannot be undone from the app.** Cord asks you to confirm first. What the workflow already did **is not deleted**: tasks it created stay in Tasks, emails were already sent, and Slack messages and HubSpot notes stay where they are. Its run history is not deleted either: it is kept, and if you need to look at it after deleting the workflow, write to us. If you are not sure, pause instead of deleting. A paused workflow stays in your list with its history, keeps whatever was in progress and does not count toward your plan limit. ## Change log Creating, publishing, pausing, resuming, deleting, retrying or canceling a run is recorded in **Settings › Audit log**, with who did it and when. ## Related - [Runs and errors](/en/docs/automatizacion/workflows/ejecuciones): what happens to each run and how to retry it. - [Limits](/en/docs/automatizacion/workflows/limites): how many active workflows your plan allows. - [Create your first workflow](/en/docs/automatizacion/workflows/primer-workflow): the editor, step by step. --- # Internal approvals URL: https://docs.cordhq.app/en/docs/cotizacion/aprobaciones-internas Last updated: 2026-10-10 How to set discount, amount, and margin caps that hold a quote until a manager approves it, and how the decision is made from Cord, Slack, or Teams. ## What it is Internal approvals are a rule for your organization. You define how far a seller can go without asking (maximum discount, maximum amount, and minimum margin). When a quote exceeds any of those caps when it's sent (with **Create and send**, **Save and send**, **Send to client**, from the board, or through the API), Cord doesn't send it: it keeps it as a draft marked **Pending approval** and notifies whoever can decide. This is not the client's approval. That's the [signature on the link](/en/docs/interaccion/firma); this is an internal control for your team. ## Requirements - **Plan:** Scale or Developer. On other plans the caps can't be saved with a value above 0 and Cord doesn't evaluate them. - **Permission to configure:** **Settings**. - **Permission to decide:** **Approvals**. The account owner can always decide. - **Country:** available in all 12 markets. ## Set up the caps 1. Go to **Settings › Quotes › Approvals**. 2. Under **Approval thresholds**, enter the caps you want to use. Each one is independent; a value of **0** means "no cap". 3. Save your changes. They apply to every send from then on, including drafts and new versions. | Cap | What Cord compares | When it asks for approval | |---|---|---| | **Max discount without approval (%)** | The largest discount on any line: the difference between its **List** price and its **Price**. | If any line has a discount above the cap. | | **Max amount without approval** | The quote total. | If the total is above the cap. | | **Minimum gross margin without approval (%)** | The margin of each line with a captured cost: (price − cost) ÷ price. | If any line with a cost falls below the minimum. Lines without a cost don't count. | If the quote carries a **manual** [document discount](/en/docs/cotizacion/descuentos), Cord counts it as a discount on each line for the discount and margin caps: moving the reduction to the footer doesn't get around the rule. A **coupon** doesn't count toward those caps, because it was created by whoever manages Settings and is already an authorized reduction. **The amount is compared in your business currency.** The amount cap is entered in your business currency. If you quote in another currency, Cord converts the total with the quote's own locked exchange rate or, if the quote doesn't carry one, with that day's rate. If there's no exchange rate to prove it, Cord doesn't guess: it asks for approval and the reason says the total can't be compared with the cap because it's in another currency. ## What happens on send When the seller sends the quote (**Create and send** or **Save and send** in the editor, **Send to client** on the detail, or by dragging it to *Sent* on the board) and it exceeds at least one cap: 1. The quote is saved as a **Draft** with the internal status **Pending approval**. The client gets no email and the link isn't activated. In the editor, the seller sees "Approval requested for COT-0149. Waiting for an approver's sign-off." 2. Cord writes the reason: which cap was exceeded and by how much (for example, a 22% discount against an allowed 15%, or a USD 310,000 total against a USD 250,000 cap). The reason shows on the quote detail and in its activity. 3. The quote appears under **Quotes** with the **Needs approval** filter, and above the list you see how many are **awaiting your approval**. 4. Cord emits the approval-request event, which feeds Slack, Teams, webhooks, and [workflows](/en/docs/automatizacion/workflows/disparadores). With **Save draft** (or autosave), Cord doesn't evaluate the caps: the rule is checked every time someone tries to send. A draft that's already waiting for approval can't be sent from the detail: Cord replies that the quote is waiting for approval and that the approver will send it when they decide. If you reopen it in the editor and lower the discount until it's within the caps, **Save and send** sends it and the request no longer applies. ### On a new version A new version (**Modify and resend**) is also evaluated when you click **Send new version**. If the quote had already been approved by a manager and the version doesn't make anything worse than what was approved (same or lower discount, same or lower total, same or better margin), it's sent. If it exceeds a cap it didn't exceed before, or exceeds it by more, Cord doesn't send it and replies that the version needs approval, with the reason, and asks you to adjust it or have an approver review it. ## Who approves and how The quote detail shows the **Pending approval** notice with the reason. Anyone with the Approvals permission sees two buttons: - **Approve and send:** the quote moves to *Sent*, the link becomes active, the client gets the email with the link (if their profile has an email), and the activity logs that management approved it and sent it to the client. It counts as one of the month's sends. - **Reject:** Cord asks you to confirm ("Reject this approval request?"). The quote stays a draft and the detail shows **Approval request rejected by management**. If you connected Cord's Slack app, the request arrives in your channel with the number, client, total, reason, and **Approve** and **Reject** buttons. For the button to decide, the email of your Slack account must match an active Cord member with the Approvals permission. If it doesn't, Slack replies that your account doesn't match a member with that permission and that you should decide from Cord. Once decided, the message updates with who approved or rejected. If you connected Microsoft Teams, the request arrives in the channel as a card with the number, client, total, and reason, and a **Decide in Cord** button that opens the detail. Teams doesn't allow deciding from the card: the decision is made in Cord. The **Approve the internal request** action in [Workflows](/en/docs/automatizacion/workflows/acciones) approves the pending request and sends the quote. Use it with care: a workflow that approves without conditions defeats the purpose of the cap. ## Behavior and edge cases - **Approve and send does email the client** when their profile has an email, just like a normal send. If it doesn't, share the link from the detail with **Copy link**, **WhatsApp**, or your own email. - **Every send goes through the rule.** Whether the quote is sent on creation, from a draft, from the board, or through the API, Cord checks the caps every time. - **A request is decided only once.** If two managers decide at the same time, the second is told there's no pending approval request. - **The seller sees the margin before sending.** In the editor, the **Margin** column turns red when a line falls below your minimum margin. - **If your plan drops below Scale,** Cord stops evaluating the caps and requests left pending can no longer be decided with **Approve and send**; the seller can send that draft directly and the request no longer applies. ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Internal approvals | No | No | No | Yes | Yes | ## Common problems **I can't save a cap above 0.** Your plan doesn't include internal approvals. **The margin cap doesn't trigger.** The lines have no cost. Capture the cost on each product's profile; free lines have no cost. **I approved and the client got nothing.** Their profile has no email, or the email didn't arrive. Look for the email entry in the activity and, if it isn't there, share the link from the detail. **The version needs approval.** The new version exceeds a cap by more than the approved version did. Adjust the discount or margin, or ask an approver to review it. **The Slack button says I don't have permission.** Your Slack email doesn't match your Cord user, or your role doesn't have Approvals. ## Related - [Preview and sending](/en/docs/cotizacion/envio) - [Quote management](/en/docs/gestion/cotizaciones) - [Team and security](/en/docs/cuenta/equipo-seguridad) - [Slack](/en/docs/automatizacion/integraciones/slack) and [Microsoft Teams](/en/docs/automatizacion/integraciones/teams) --- # Client data URL: https://docs.cordhq.app/en/docs/cotizacion/cliente Last updated: 2026-10-13 Pick or create the client for a quote, apply their price tier and terms, and complete the tax information the invoice will need. ## What it is Step 1 of the editor, **Who are you quoting?**, links the quote to a client in your directory. Three things come from their profile: their price tier discount, their payment terms, and the recipient data the invoice will use. The same step exists when you create an invoice, titled **Who are you invoicing?**. ## Requirements - **Permission:** Quotes to pick a client; **Clients** to create a new one. - **Plan:** Free allows up to 50 clients and Starter up to 500; from Pro there's no cap. - **To send:** the quote needs a client. A draft can be saved without one, but on send Cord asks you to "Choose a client to be able to send." ## Pick or create the client 1. In **Who are you quoting?**, click the client search ("Search a client by name, contact or email…") and type part of the company name, contact, email, or tax ID. The list shows up to eight matches, each with its email, its tax ID and, if it has a price tier, its discount (for example −10%). 2. Pick the client with a click, or with the arrow keys and **Enter**. **Escape** closes the list and keeps the client that was already selected. 3. If they don't exist, choose **+ Create new client…**, which always appears at the end of the list; fill in the form and click **Create and select**. They're saved in your directory and selected on the quote. 4. Check the **Payment terms** preselected to the right of the search and change them if needed. Below the search, Cord shows the selected client's email and tax ID and, if their tier has a discount, a note such as "Client tier: −10% applied to your catalog list prices." ## Payment terms Terms are chosen with chips: **Due on receipt**, **Net 15**, **Net 30**, and **Net 60**. For another term, the **Other term** chip opens a list with **Net 7**, **Net 45**, and **Net 90**. "Net N" means the client pays N calendar days after the document date. When you pick a client, the terms from their profile are preselected; you can change them for this quote only without touching the profile. Credit terms change what happens on approval (see [Advanced options](/en/docs/cotizacion/opciones)). Other ways to fill your directory: - **From Clients:** **+ New client** for one, or **Import CSV** to load up to 2,000 rows per file (company, contact, email, phone, tax ID, payment terms, and credit limit). - **From a client's profile:** **New quote** opens the editor with that client already selected. - **Through the API:** the [clients API](/en/docs/desarrolladores/funciones/clientes) creates and syncs clients from your system. ## Price tier and automatic discount Each client can have a **Price tier** with a suggested discount you can change in the automatic discount field: | Tier | Suggested discount | |---|---| | Standard | 0% | | Silver | 5% | | Gold | 10% | | Distributor | 15% | When you pick the client, Cord lowers the **Price** column of each catalog product by that percentage: with 10%, a product with a **List** price of MXN 1,000 comes in at MXN 900. The list price doesn't change and you can adjust any line's price by hand. ## Commercial and tax information ### Commercial - **Name or legal name** (required): the client's name, whether a company or a person. It's also the recipient name on their invoice; write it as it appears on their tax documents. - **Contact:** the person who decides. - **Email:** where the link is sent when you send the quote from Cord. - **Phone** with country code (chosen next to the number, following the client's country), **Credit limit**, and **Payment terms** (Due on receipt, Net 15, Net 30, Net 60, or another term: Net 7, Net 45, or Net 90) proposed when you quote them. See [Credit terms](/en/docs/pagos/credito). - **Document language:** the language in which the client receives the quote, its link, the PDF, and the emails. **Organization default** uses your account's language. The quote saves it when sent; see [Document language](/en/docs/gestion/clientes#document-language). ### Tax - **Country** and **Tax ID:** the tax ID label adapts to the client's country: **RFC** in Mexico, NIF/CIF in Spain, EIN/Tax ID in the United States, and so on. As you type, the profile checks its format in Cord's 12 markets (in Mexico, the RFC's shape, date and check digit) and warns you if it doesn't look right. When you save, Cord validates it with the rules of the client's country (or yours, if you don't assign a country) and stores it normalized, in uppercase; one that fails isn't saved and the message says what to check. When editing, it's only validated again if you change the ID or the country. - **Address:** address, city, state or province, and postal code, in the **Address** section; field names follow the country. If your business invoices in Mexico and the client is Mexican, a **Tax details for CFDI (Mexico)** section appears with two CFDI 4.0 fields, filtered by RFC type (12 characters, legal entity; 13, individual): - **Tax regime**, for example *601 - General de Ley Personas Morales*. - **CFDI use**, for example *G03 - Gastos en general*, which is used if you leave it empty. If your business invoices in Mexico and the client is from another country, that section doesn't appear: their CFDI is stamped to a foreign resident (generic RFC XEXX010101000, their country as tax residence, their tax ID as the foreign tax registration number, and use S01). The profile shows a notice about it. ## Behavior and edge cases - **Incomplete tax data:** the quote is still commercially valid. In Mexico, without an RFC the CFDI is issued with the generic general-public RFC (XAXX010101000); with an RFC but no regime, Cord uses 601. Check RFC, postal code, and regime against the client's tax certificate before stamping. - **Changing the client after sending** isn't possible with **Modify and resend**: duplicate the quote and send it to the right client. - **Editing the profile** doesn't rewrite fiscal documents already issued: they keep the recipient data they were issued with. - **Preview in the client's language:** the editor preview appears in the document language of the selected client. In a new version of a quote already sent, it appears in the language it was sent in, which the version keeps. - **Credit limit:** if the client has one, their profile shows how much open balance they have against it. It's a signal for you, not a block. ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Clients in the directory | 50 | 500 | No cap | No cap | No cap | ## Common problems **"+ Create new client…" fails to save.** Your role doesn't have the Clients permission, or you reached your plan's client cap. **The search says "No client matches."** Search by another part of the name, by email, or by tax ID, or create the client with **+ Create new client…**. **I can't change the client or the terms.** You're on a new version of a quote that was already sent: there the client, currency, and terms stay as they were sent. **The tier discount wasn't applied.** It only lowers catalog products; free lines have no list price. **The CFDI was issued to "público en general" (generic RFC XAXX010101000).** The client is Mexican and had no RFC when you stamped. If they're actually foreign, choose their country in the profile: their next CFDI will be issued to a foreign resident. ## Related - [Clients and statements](/en/docs/gestion/clientes) - [Products and pricing](/en/docs/cotizacion/productos) - [Approval and invoicing](/en/docs/cotizacion/timbrado) --- # Discounts and coupons URL: https://docs.cordhq.app/en/docs/cotizacion/descuentos Last updated: 2026-10-10 Apply a percentage or fixed-amount discount to a whole quote or invoice, create coupons with validity dates and usage limits, and understand how it's calculated, when a use is counted, and how it travels to the CFDI, Verifactu, and e-invoices. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. ## What it is Cord has two ways to lower the price of a sale, and both can live on the same document: - **Negotiated price per line.** You lower the price of one specific line. It's the difference between the list price and the negotiated price, and the panel shows it as **Discount given**. See [Products and pricing](/en/docs/cotizacion/productos). - **Document discount.** A reduction on the **whole** quote or invoice: a **percentage** or an **amount** in the document's currency. Cord applies it **before tax** and spreads it across the lines in proportion to their amount. You can enter it by hand or with a **coupon**. A **coupon** is a reusable code (for example, `WELCOME10`) that you create under **Settings › Discounts › Coupons**, with its value, its validity dates, and how many times it can be used. Your team applies it in the editor, and your buyers can enter it when they quote from your website through the API or Cord Elements. ## Requirements | | Details | |---|---| | **Plan** | All plans. | | **Permission to apply** | **Quotes**: apply a discount or validate a coupon in the quote or invoice editor. | | **Permission to manage coupons** | **Settings**: create, edit, deactivate, and delete coupons. | | **Country** | All 12 markets. Each tax rail declares the discount the way its authority requires (see [On your tax invoice](#on-your-tax-invoice)). | ## Apply a discount The control lives in the editor's **Review and send** panel, between the subtotal and the taxes. It's in the new-quote editor, when editing a quote, and in the invoice editor. 1. In **Review and send**, click **+ Add discount or coupon**. 2. Choose the type: **Percent** (0 to 100), **Amount** (in the document's currency), or **Coupon**. 3. Type the value or the code and click **Apply**. A coupon is validated right then: if it doesn't apply, the panel tells you why (see [Coupon messages](#coupon-messages)). 4. The summary shows the row **Discount (10%)** or **Discount (WELCOME10)** with the amount in green, and the taxes and total already calculated on the discounted base. To take it off, click **Remove** next to the label. A document carries **one** document discount at a time. If you send a coupon and a manual discount together (for example, from the API), the coupon wins. ## How it's calculated 1. **Gross subtotal:** the sum of the lines at their negotiated price, before tax. 2. **Discount:** the percentage of that subtotal, or the amount you entered. An amount larger than the subtotal is capped at the subtotal: the discount never makes the sale negative. 3. **Spread per line:** each line gets a share proportional to its gross amount. The spread is done in the currency's smallest unit (cents in MXN, cents in EUR, whole units in CLP or JPY), so the shares add up to exactly the discount and no line goes negative. 4. **Taxes:** each line calculates its tax on its already-discounted base, with its own rate. That's why an exempt line and a taxed line each get their share of the discount and the tax only drops where it should. 5. **Withholdings:** if your catalog has withholdings (for example, ISR or IRPF), they're calculated on the discounted bases. | Example (Mexico, 16% VAT) | No discount | With 10% | |---|---:|---:| | Subtotal | 169,370.00 MXN | 169,370.00 MXN | | Discount (WELCOME10) | — | −16,937.00 MXN | | IVA 16% | 27,099.20 MXN | 24,389.28 MXN | | **Total** | **196,469.20 MXN** | **176,822.28 MXN** | **Tax-inclusive prices.** If you turned on **Prices include IVA** (or your country's tax), an **amount** discount lowers what your client pays, and the pre-tax base is broken out afterwards. A percentage works the same with or without tax-inclusive prices. The browser and the API never send the discount amount: they send the **definition** (percentage or amount) or the coupon **code**. Cord recalculates on the server with the same engine the editor uses, so what you see is what's saved, charged, and invoiced. ## Create and manage coupons 1. Open **Settings › Discounts › Coupons** with the **Settings** permission. 2. Click **New coupon**. 3. Type the **Code**: 3 to 32 letters, numbers, hyphens, or underscores. Cord turns it into uppercase and doesn't allow two coupons with the same code on your account. 4. Optional: an internal **Name** (for example, "New client promotion"). 5. Choose the **Discount**: **Percentage** or **Fixed amount**, and its **Value**. A fixed amount also asks for its **Currency**, among the ones your account offers when quoting. 6. Optional: **Valid from** and **Valid until**. The dates are read in your business's time zone. 7. Optional: **Total uses** and **Uses per client**. Empty means unlimited. 8. Click **Create coupon**. | Rule | Details | |---|---| | **Currency** | A percentage coupon works in any currency. A fixed-amount coupon only applies to documents in **its** currency: a 2,500 MXN coupon can't be applied to a quote in USD. | | **What you can edit** | The name, the validity dates, the usage limits, and whether it's active. The **code, type, value, and currency don't change** once it's created: a document that already carries it keeps what it discounted. For a different value, create another coupon. | | **Deactivate** | The toggle on each row. A deactivated coupon can no longer be applied to new documents; documents that already carry it keep it. | | **Delete** | Only a coupon that was never used. One with uses is deactivated instead, to keep its history. | | **Per-client limit** | A coupon with **Uses per client** requires choosing the client before applying it. | ## When a use is counted A coupon is **applied** to the document when you validate it, but its use is **counted** when the document becomes binding: | Document | The use is counted | The use is returned | |---|---|---| | **Quote** | When it's **approved**: the client clicks **Approve quote** on the link, or you use **Mark approved**. | If the quote is **rejected** or **expires**. | | **Invoice** | When it's **issued**, before it gets its number. | If the invoice is **voided**, or if you delete a draft whose issuance had failed. | | **Invoice from a quote** | Not counted again: it reuses the quote's use. | Along with the quote. | - The **validity dates** and whether the coupon is **active** are checked when it's **applied**. A document built while the coupon was valid keeps it even if the coupon later expires or you deactivate it. - The **usage limits** are checked when applying and again when approving or issuing, because they're the coupon's budget. If the uses ran out between the draft and that moment: - **Invoice:** it isn't issued and no number is used up. Cord tells you the coupon has no uses left and to remove it from the draft to issue the invoice. - **Quote approved by the client:** the approval doesn't go through. Your client reads that the quote needs an update from you, and the activity shows that they tried to approve with an exhausted coupon. Remove the coupon and send the quote again. ## Coupon messages | Message | What to do | |---|---| | That coupon does not exist. | Check the code; spaces and lowercase don't matter. | | That coupon is deactivated. | Turn it back on in **Settings › Discounts › Coupons** if you want to keep using it. | | That coupon is not valid yet. / That coupon has expired. | Check **Valid from** and **Valid until**. | | That coupon is in a different currency than this document. | Use a percentage coupon or a fixed-amount one in the document's currency. | | That coupon has no uses left. | Raise **Total uses** or create another coupon. | | This client has already used that coupon as many times as allowed. | The per-client limit was reached. | | That coupon is limited per client: choose a client first. | Choose the client in **Who are you quoting?** and apply it again. | ## Where the discount shows up - **Quote link and PDF:** the row **Discount (WELCOME10)** or **Discount (10%)** between the subtotal and the taxes. Each line keeps its amount before the discount. - **Quote and invoice detail**, and the **invoice link**: the same row. - **Google Sheets and Excel:** the **discount** column of the quotes sheet, with the subtotal before the discount. - **QuickBooks Online and Xero:** each line arrives with its already-discounted price. ## On your tax invoice The discount travels, spread per line, to every tax document, in the shape each authority requires: | Document | How it's declared | |---|---| | **CFDI 4.0 (Mexico)** | Each line carries its unit value **before** the discount and its share of the discount in the **Descuento** attribute; the VAT base is the amount minus the discount. A line that the discount brings to zero can't be stamped (the SAT requires a base greater than zero for a transferred tax): Cord rejects it before stamping and tells you which one. In the [global invoice](/en/docs/pagos/facturacion#global-invoice), each sale carries its share of the discount. | | **Verifactu (Spain)** | Each line declares its **already-discounted** base. | | **Factur-X, XRechnung, and Peppol** | Each line with its amount before the discount, and the discount as a **document allowance**, one per VAT category and rate, so that each group in the breakdown matches the invoice to the cent. | | **Facturae (Spain)** | Each line with its own discount. | | **Authorized invoices in Argentina, Brazil, Chile, Colombia, and Peru** | Each line with its share of the discount, in the field each country's authority requires. | A **credit note** spreads its amount in the same proportion, discount included. ## Copies, recurring invoices, and partial approval | Case | What happens to the discount | |---|---| | **Partial approval** | Cord reapplies the definition to the approved lines: a percentage is recalculated; an amount is capped at the new subtotal. | | **Invoice from a quote** | Inherits the definition and applies it to what's invoiced. | | **Duplicate or repeat an invoice** | Copies each line's **gross** price and the discount separately. | | **Recurring invoices** | Only carry a **manual** discount: a coupon isn't repeated every month. | | **Duplicate a quote** | The copy doesn't carry the document discount: add it again if it applies. | | **Replace a CFDI (Mexico)** | The replacement inherits the original's discount, with its coupon, without counting another use. | | **Shopify order** | The order Cord creates in your store carries each line's negotiated price, but **not yet** the document discount. Check the order total in Shopify. | ## Discounts and internal approvals If your organization uses [internal approvals](/en/docs/cotizacion/aprobaciones-internas): - A **manual** document discount counts as a discount on each line for the **maximum discount** threshold and the **minimum margin** threshold. Moving the reduction to the footer doesn't get around the rule. - A **coupon** doesn't count toward those thresholds: it was created by whoever manages Settings and is already an authorized reduction. ## From the API and Cord Elements - `POST /api/v1/cotizaciones` and `POST /api/v1/facturas` accept `descuento` (`{ "tipo": "porcentaje" | "monto", "valor": 10 }`) or `cupon` (`"WELCOME10"`). See the [Quotes API](/en/docs/desarrolladores/funciones/cotizaciones) and the [Invoices API](/en/docs/desarrolladores/funciones/facturas). - With a **publishable key** (your website's), the only discount accepted is a `cupon`: a buyer can't set a percentage for themselves. - A coupon that doesn't exist responds `404` with `code: "coupon_no_existe"`; an expired, exhausted, or wrong-currency one responds `409` with `coupon_vencido`, `coupon_agotado`, `coupon_moneda`, and so on. ## Limits - One document discount per document. - Percentage from 0 to 100; an amount is capped at the gross subtotal. - Coupon codes of 3 to 32 characters (`A-Z`, `0-9`, `-`, `_`), unique on your account. - Uses are counted per binding document: approving and then invoicing the same sale counts a single use. ## Troubleshooting **The coupon says it's exhausted, but there are documents that weren't approved.** A use is counted when approving or issuing. Check which approved quotes or issued invoices carry it; when an invoice is voided or a quote is rejected, the use comes back. **I can't change a coupon's value.** The value isn't editable so it doesn't change what it already discounted on existing documents. Deactivate it and create another. **The CFDI is rejected because of a line at zero.** The discount left a line without a base. Lower the discount or remove that line before stamping. **The coupon isn't on the duplicated quote.** Duplicating doesn't copy the document discount: apply it again. ## Related - [Products and pricing](/en/docs/cotizacion/productos) - [Internal approvals](/en/docs/cotizacion/aprobaciones-internas) - [Advanced options](/en/docs/cotizacion/opciones) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Tax invoicing by country](/en/docs/pagos/facturacion) - [European e-invoicing](/en/docs/pagos/factura-electronica) --- # Preview and sending URL: https://docs.cordhq.app/en/docs/cotizacion/envio Last updated: 2026-10-11 The editor's Review and send summary, preview, autosave, and shortcuts; how to send the quote by email or WhatsApp and what happens with the link, send limits, and payment. ## What it is Sending a quote activates its **public link**: a page with your brand where the client reviews, comments, signs, and pays. It isn't an attached PDF; it's the same document your team keeps seeing in Cord, and any new version arrives at the same link. ## Requirements - **Permission:** Quotes. - **Plan:** all. Free has a cap of 5 sends per month. - **Client email:** optional. Without an email, the quote is still marked as sent and you share the link. - **Online payment:** optional. For the client to pay from the link you need an active payment rail (see [Payment methods](/en/docs/pagos/metodos)). ## The "Review and send" summary On the right of the editor (at the end, on a phone) the summary tells you how much it is and what comes next: - **Document tag:** **Draft** or, on a new version, **Version N**. - **Save status:** on a draft that's already saved, "Saving…" and then "Saved at …" (see "Autosave and local copy" below). - **Count:** lines and units, for example "3 lines · 46 units". - **Subtotal**, **Discount given** (if you lowered prices), one row per tax rate, and withholding if your catalog has any. - The **Prices include VAT** switch (with your country's tax name). - **Total**, and below it the terms on one line, for example "Net 30 · valid for 30 days". - The main button (**Create and send**, **Save and send**, or **Send new version**), **Save draft** or **Save changes**, and **Preview**. ## Review before sending ### Preview in the editor Click **Preview** in the summary. **What your client will see** opens: a sheet with your logo (or your initial), your business name and tax ID, the document type and its number (or "Draft"), the date, the client and their email, the validity, the item table with the list price struck through where there's a discount, subtotal, taxes, withholding, the total with its currency, and your note. It's an approximate view and saves nothing: "Approximate view. The final PDF uses your template, branding and tax details." ### Preview of the link To see the real link exactly as your client will open it: 1. Save the draft, open it from **Quotes** and, in the actions panel, click **Preview**. 2. The link opens in a new tab with the notice "Preview — this is what your client sees. Your visit is not counted as a view." While you're signed in to the organization that owns the quote, your visit doesn't mark it as *Viewed* or trigger notifications. 3. Check the total, the lines, the struck-through prices where you negotiated, the payment plan if you asked for a deposit, and the notes. What the client sees is explained in [What your client sees](/en/docs/interaccion/vista-del-cliente). ## Send the quote There are three paths and all three do the same thing: they change the status to *Sent*, activate the link and, if the client has an email, send them an email with the link and log the email in the activity. | From | Button | |---|---| | The editor of a new quote | **Create and send** (sending creates V1 and the public link) | | The editor of a draft | **Save and send** | | The detail of a draft | **Send to client** | Before sending, the editor checks that there's a client ("Choose a client to be able to send.") and that every line has a description, a quantity greater than zero, and a price; if something is missing, it takes you to the line marked in red. You can also drag the card from *Draft* to *Sent* on the board (see [Home and views](/en/docs/gestion/dashboard)); it performs exactly the same send. **Internal approval.** If your organization uses [internal approvals](/en/docs/cotizacion/aprobaciones-internas) and the quote exceeds your caps on **Create and send** or **Save and send**, it stays a draft **Pending approval** until a manager approves it. The editor tells you: "Approval requested for COT-0149. Waiting for an approver's sign-off." ## Autosave and local copy - **A draft that's already saved saves itself** a few seconds after your last change, as long as all its lines are complete. The summary shows "Saving…" and "Saved at …"; if it fails, it says "Not saved: check your connection." - **A new quote isn't created on its own**, because every quote counts against your plan's limit. While you build it, your browser keeps a local copy of the client, terms, lines, and note. If you close the tab without saving, the next time you open **New quote** Cord asks "You have unsaved changes from last time" and lets you **Restore** or **Discard**. The copy lives only in that browser and expires after 7 days. - **Leaving with unsaved changes** makes the browser ask for confirmation before closing the page. ## Keyboard shortcuts On desktop: | Shortcut | What it does | |---|---| | **⌘ Enter** (Ctrl Enter on Windows) | The main action: create and send, save and send, or send the version. | | **⌘ S** (Ctrl S) | Saves the draft. Not available on a new version. | | **/** | Jumps to the catalog search when you're not typing in a field. **⌘ K** still opens the app's general search. | | **Alt + Up / Down arrow** | Moves the line you're on. | ## On a phone The editor stacks into one column: AI, client, lines, terms, note, and the summary at the end. A bar pinned to the bottom shows the **Total** and the main button; it steps aside once the summary is in view. On a phone there are no keyboard shortcuts and no dragging to reorder lines. ## New version From the detail of a *Sent*, *Viewed*, or *Expired* quote, **Modify and resend** (with the next version number, for example "Modify and resend (V2)") opens the same editor in new-version mode (the old `/app/cotizaciones/[id]/editar` route only redirects there). A new version changes lines and prices; the client, currency, and terms stay as they were sent, and the AI block doesn't appear. When you send it, the validity restarts from that day with the same length the quote was sent with (if it was 30 days, it expires in 30 days), so an *Expired* quote goes back to *Sent* with a new date. The summary is tagged **Version N** and the main button is **Send new version**: your client sees the new version at the same link and the previous one stays in the history. ## Share the link Once sent, the detail's actions panel gives you more ways to deliver it: - **Copy link:** to paste it into your email, Slack, or the chat where you talk with your client. - **WhatsApp:** opens WhatsApp with a ready message: "Hi! Here's your quote COT-0149 for … You can review and approve it here:" followed by the link. If you have templates in **Settings › Templates**, you choose which one to send first. - **PDF:** opens the printable version to download or print it. - **Open link:** opens the public view to review it. The link doesn't change when you create a new version with **Modify and resend**: the client keeps using the same one. ## Paying from the link Once the client approves, the quote becomes a payment point, as long as your account has an active online rail: 1. **Credit or debit card** with Cord Payments, inside the same link. 2. **SPEI transfer** (Mexico, MXN only): Cord generates a dedicated CLABE for that charge and marks the quote as paid when the deposit arrives. In other currencies, SPEI isn't offered. 3. **Bank transfer with a reference** (Spain, Germany, and France in EUR; United Kingdom in GBP; United States in USD), if the document has a linked client: your client transfers to an account of their own with that charge's reference and Cord reconciles it on its own. It's a new feature: see [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). 4. **Mercado Pago** in Mexico, Brazil, Colombia, Argentina, Chile, and Peru, if you connected your account. Where you also have Cord Payments, Cord Payments is the primary rail. If you enabled bank transfer details, the link also shows them with the note "After transferring, send your receipt to the seller to confirm payment." You record that payment yourself with **Record payment**. **Money straight to your account.** Card and transfer funds go to your connected account, not to a Cord account. Today Cord charges a platform fee only on MXN charges; in other currencies it charges no fee of its own (see [Fees and advantages](/en/docs/pagos/condiciones)). ## Behavior and edge cases - **No client email:** the quote moves to *Sent* and no email goes out. Share the link. - **Resending doesn't use sends.** **Modify and resend** creates a new version and sends the email again, but doesn't count against Free's monthly cap. - **The email carries your brand.** From Starter you can customize the sender, reply-to address, introduction, and signature in **Settings › Notifications › Email**. - **A test quote** is marked on the link with the ribbon "Test quote — no commercial or fiscal validity". ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Sends per month | 5 | No cap | No cap | No cap | No cap | | Custom email | No | Yes | Yes | Yes | Yes | When you hit Free's cap, **Send to client** tells you that you reached your plan's monthly limit and suggests upgrading. ## Common problems **The client didn't get the email.** Check that their profile has an email and look for the email entry in the activity. If it isn't there, share the link manually. **I don't see the pay button on the link.** Payment shows after approval and only if you have an active rail. With a credit term (Net 7 to Net 90) it's enabled on the due date (see [Credit terms](/en/docs/pagos/credito) and [Advanced options](/en/docs/cotizacion/opciones)). **My new quote didn't save itself.** Autosave is for drafts that already exist. Click **Save draft** (or ⌘ S) the first time; until then, the local copy lets you restore it in that browser. **The summary says "Not saved: check your connection."** Autosave didn't reach the server. Check your network and click **Save changes**. **My own visit marked the quote as viewed.** It shouldn't: open the link while signed in to the same organization. From another browser without a session, Cord can't tell you apart from the client. ## Related - [What your client sees](/en/docs/interaccion/vista-del-cliente) - [Internal approvals](/en/docs/cotizacion/aprobaciones-internas) - [Notifications](/en/docs/gestion/notificaciones) - [Accept a payment](/en/docs/pagos/aceptar) --- # Cord AI: automatic quotes URL: https://docs.cordhq.app/en/docs/cotizacion/ia Last updated: 2026-10-15 Build a quote's lines by pasting text, a photo, or a PDF: Cord AI matches them against your catalog and you review before sending. ## What it is Cord AI is the artificial intelligence engine in the quote and invoice editor. It reads an order as text, a PDF, or an image, extracts products and quantities, and matches them against **your real catalog**. It doesn't save or send anything on its own: it fills the editor's lines and you decide. ## Requirements - **Permission:** Quotes, to open **New quote**. - **Plan:** all, with a monthly allowance per plan (see below). - **Catalog:** Cord AI matches against your products. Without a catalog, everything comes in as free lines. ## How to use it 1. Open **Quotes › New quote**. The first block, above the editor's three steps, is **Build the quote with AI**. You can also get there from the command palette with **Build with AI**. 2. Paste the order into the text box, attach a file with the clip (**Attach photo or PDF**), or both. 3. Click **Build quote with AI**. When it finishes, Cord tells you how many lines it built, for example "3 lines ready. Check quantities and prices." 4. Review the lines that were added, pick the client, adjust prices and terms, and save or send. If you'd rather enter lines by hand, you don't need the AI block: go straight to step 1 and add lines from the catalog search (see [Products and discounts](/en/docs/cotizacion/productos)). ## When it shows and when it folds - **New quote or invoice with no lines:** the block shows open. - **A document that already has lines** (for example, a draft you reopen): the block starts folded as a one-line bar with an **Open** button. Open it to use it again. - **New version of a sent quote:** the block doesn't appear; in a version you adjust lines by hand. - **Invoice:** the same block appears as **Build the invoice with AI**, with the **Build invoice with AI** button, and uses the same monthly allowance. If the document already has lines when you build with AI, Cord asks "Replace the current lines?" and lets you choose **Replace** or **Add at the end**. ## What it can read | Input | Limit | What Cord AI does | |---|---|---| | **Text** (email, WhatsApp, notes) | 2,000 characters | Finds matches in your catalog, takes the list price and, if the client mentions a lower price, proposes it as negotiated. | | **PDF** (purchase order, requisition, tender) | 3 MB, can have several pages | Reads it with the same vision model as a photo, with no separate OCR. | | **Image** (JPG, PNG, or WEBP) | Cord compresses it before uploading | Reads the photo and builds the lines. | Anything it can't find in your catalog comes in as a **free line** so you decide what to do with it; if the order had no price, the line asks you for one before saving. The list price and product data always come from your catalog, not from the text. ## Human review Cord AI is a copilot. You: - confirm the products are the right ones; - adjust quantities if something was misread; - choose the client, prices, and terms before saving or sending. ## Your connected systems If you connected other systems in **Settings › Artificial intelligence** (your CRM, your ERP or an MCP-compatible database), Cord AI can look them up while building the quote. It's available on Scale and Developer, with these rules: - **No tools by default.** A newly connected system starts with no tools allowed. In its row, click **Tools** and turn on, one by one, the ones the AI may use. - **Read or write.** Cord only treats a tool as read-only when the system itself declares it that way. Any other tool can change data and shows as **Can change data · asks to confirm**. - **Confirmation before every write.** If Cord AI wants to use a tool that can change data, it stops and shows you the system, the tool name and what it will send. It only runs if you click **Use the tool**; with **Don't use it** nothing is sent and Cord AI finishes the quote without it. Each confirmation works once, for 15 minutes, and your decision is recorded in the **Audit log**. - **Nothing with photos, PDFs or emails.** When you attach a file, or quote from the [Gmail add-on](/en/docs/automatizacion/integraciones/gmail), Cord AI reads the order without access to your connected systems: a document or an email from someone else could carry hidden instructions. Read-only tools run without asking, so turn on only the ones you need. Removing a permission or pausing the connection doesn't undo what a tool already did in that system. ## Limits by plan Each build that identifies products uses one unit of the monthly allowance. If it identifies none, nothing is used. | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Builds included per month | 3 | 20 | 50 | 500 | No cap | | Beyond the allowance | Stops | Overage billed | Overage billed | Overage billed | Not applicable | See your usage in **Settings › Plans & subscription › Subscription**. ## Common problems **"Write the order, paste it or attach a photo or PDF."** You clicked the button with no text and no file. **"The PDF is over 3 MB."** Scan it at a lower resolution or upload a photo instead. **"Upload a photo (JPG, PNG or WEBP) or a PDF."** You attached another format. Spreadsheets aren't processed by this assistant; to load many products use the [CSV import](/en/docs/cuenta/catalogo). **I don't see the AI text box.** The block is folded because the document already has lines: click **Open**. A new version of a sent quote has no AI block. **It matched a product wrong.** Clear names and defined SKUs in your catalog improve matching. Fix the line before sending. ## Frequently asked questions **Does Cord AI replace the seller?** No. It fills a draft that a person always reviews before it's sent. **Does it work in any language?** Yes. It understands orders in Spanish, English, and other languages and matches them against your catalog. ## Related - [Products and pricing](/en/docs/cotizacion/productos) - [Set up with AI](/en/docs/cuenta/configurar-con-ia) - [Your Cord subscription](/en/docs/cuenta/suscripcion) --- # Advanced options URL: https://docs.cordhq.app/en/docs/cotizacion/opciones Last updated: 2026-10-11 Payment terms, deposit, monthly retainer, tax-inclusive prices, withholding, sales versus accounting currency, locked rate, validity, notes, and the defaults in Settings › Quotes. ## What it is Beyond client and lines, each quote carries its commercial and financial conditions. Payment terms are chosen with the client, in step 1 (**Who are you quoting?**). Validity, deposit, currency, and retainer live in step 3, **Terms** ("How long it's valid, how it's paid and in which currency."), below the lines. In the **Review and send** summary on the right of the editor, the tax-inclusive switch and the [document discount or coupon](/en/docs/cotizacion/descuentos) sit next to the totals. The values a new quote starts with are set once in **Settings › Quotes**. ## Requirements - **Permission:** Quotes to use the options; Settings to change the defaults. - **Plan:** every option is on every plan. The monthly retainer and paying the deposit online require an active payment rail. - **Country:** the invoice series is Mexico only; SPEI is Mexico and MXN only; bank transfer with a reference is for Spain, Germany, France, the United Kingdom, and the United States in their currency. ## Payment terms In **Who are you quoting?** you choose a chip: **Due on receipt**, **Net 15**, **Net 30**, or **Net 60**. The **Other term** chip offers **Net 7**, **Net 45**, and **Net 90**. Net N means N calendar days of credit. When you pick a client, Cord preselects the terms from their profile. Below the summary total you read the term together with the validity, for example "Net 30 · valid for 30 days". - **Due on receipt:** payment is available as soon as the client approves. - **Net 7 to Net 90 (credit):** the pay button doesn't appear on approval. The client sees that the order is confirmed on credit and the date it's due; online payment is enabled on that date, counted from approval. ## Deposit In the **Terms** step, the **Deposit (%)** field (optional) takes a percentage between 1 and 99. Below it, the editor tells you how much the client pays on approval and how much later, for example "Upon approval, your client pays MXN 3,000.00 as a deposit and the rest (MXN 7,000.00) per the terms." On approval, Cord splits the charge into deposit and balance: the client pays the deposit immediately (even if the terms are on credit) and the balance keeps its due date. Even before approval, the link shows what they'll pay once approved. Details in [Upfront and balance](/en/docs/pagos/anticipos). ## Monthly retainer In the **Terms** step, turn on **Monthly recurring charge (retainer)** to charge the total every month by card. - It only exists with **Due on receipt** terms: if you choose any credit term (Net N), the switch disappears. - It excludes a deposit: when on, the deposit field is hidden. - The client authorizes their card once from the link on approval; they pay the first month then, and the same amount is charged every month until it's canceled. Details in [Monthly retainers](/en/docs/pagos/igualas). ## Tax-inclusive prices and withholding - **Prices include VAT** (with your country's tax name: IVA, GST, Sales tax…): it's the switch in the **Review and send** summary, above the total. With it on, the price you enter already includes tax and Cord breaks it out instead of adding it on top. To have it on for every new quote, turn it on in **Settings › Quotes › Taxes**, under **Behavior in quotes**. - **Tax per line:** each line carries its rate, taken from your tax catalog. See [Products and pricing](/en/docs/cotizacion/productos). - **Withholding:** if your catalog has active withholding entries marked as default, Cord applies them to every quote and **subtracts** them from the total; they show as rows in the summary, on the link, and in the PDF. They aren't toggled per quote: they're managed in **Settings › Quotes › Taxes**. Where your country has no withholding, no row appears. ## Sales currency and accounting currency These are two different pieces of data and Cord doesn't mix them: - **Sales currency:** the one you choose in **Which currency are you quoting in?**, inside the **Terms** step. It's what the client sees on the link, what they're charged in, and what the invoice is issued in. You can choose MXN, USD, CAD, BRL, EUR, GBP, COP, ARS, CLP, PEN, JPY, CNY, CHF, or AUD. - **Accounting currency:** your business's currency, set in **Settings › General**. It's the one you keep your books in. When both are the same there's no exchange rate. When they differ, Cord gets a real, dated rate from an external provider and adds a coverage cushion: | Option | Cushion | |---|---| | **Light** | +1% | | **Normal** (default) | +2% | | **Cautious** | +5% | If you change the currency of a document that already has lines, Cord warns you that prices are not converted: the lines keep the same numbers, now in the new currency, and you need to review each price. When the sales currency differs from your business's, the **Terms** step shows a panel with **Rate today**, **Your protected rate**, and the question "How cautious do you want to be?" to choose the cushion. The rate is locked when you save the quote (or when you change the currency pair on a draft) and isn't recalculated: the invoice declares it as the exchange rate even if the market moves. **No provable rate, no save.** If no source publishes that pair's rate at that moment, Cord doesn't save the quote in that currency and asks you to try again or quote in your business currency. It never uses a made-up rate. The "Rate locked for 30 days" label is informational: the rate is kept as long as you don't change the pair. More in [Treasury and FX Lock](/en/docs/pagos/tesoreria-fx). ## Validity In the **Terms** step, the **Valid for** field sets how many days the proposal is valid: 15, 30, 60, or your organization's default. A daily process marks as *Expired* every sent or viewed quote whose date has passed, and three days earlier it can alert you (see [Notifications](/en/docs/gestion/notificaciones)). An expired quote no longer accepts the client's approval; to bring it back, send a new version with **Modify and resend**: the validity restarts from that day with the same length. ## Notes and conditions - **Note for your client** (optional): the block at the end of the editor, with free text for the quote (for example, "on-site delivery included"). It appears on the link and in the PDF. - **PDF conditions:** your business policies (cancellation, delivery, warranty) are set once in **Settings › Quotes › PDF document**, one per line, and are printed only in the PDF. ## Defaults (Settings › Quotes) In **Settings › Quotes › Numbering & tax** you define what every quote starts with: | Field | What it does | |---|---| | **Quote number prefix** | Up to 6 letters or numbers (Cord uppercases it). The quote number is prefix, hyphen, and a 4-digit sequence, for example COT-0149. Each account starts with its country’s prefix (Q in the United States, COT in Mexico, PRE in Spain), and if you leave it empty, Cord goes back to it. | | **Series (optional)** | Mexico only: series for CFDI numbering. | | **Default rate (%)** | The rate new lines get when your catalog has no profile marked as default. | | **Withholding applied** | Read only: lists your catalog's default withholding, with the **Manage taxes** link. | | **Default validity (days)** | Between 1 and 365. The editor starts with this value. | | **Default payment terms** | Due on receipt or a Net term (7, 15, 30, 45, 60, or 90 days). Preselected on creation; the client's profile wins when you pick one. | | **Default deposit (%)** | Between 1 and 99, or empty for no deposit. Prefills the editor field. | | **Default legal text** | Printed at the bottom of the quote link and the PDF, in small type. Leave it empty to hide it. | Changing a default doesn't modify quotes already created. ## Limits by plan The options on this page have no cap by plan. Online payment, retainers, and automatic bank transfer depend on having an active payment rail in your country (see [Payment methods](/en/docs/pagos/metodos)). ## Common problems **I don't see the retainer switch.** You chose a credit term (Net N); retainers only exist with Due on receipt terms. **I can't change validity, deposit, currency, or retainer.** You're building a new version of a quote that was already sent: the client, currency, and terms stay as they were sent. When you send it, the validity restarts from that day with the same length. If you need a different length or different terms, duplicate the quote. **I don't see the deposit field.** You have the retainer turned on. **Cord couldn't get the exchange rate.** No source published that pair's rate at that moment. Try again shortly or quote in your business currency. **I changed the default validity and my quotes didn't change.** That's expected: it applies to new ones. ## Related - [Products and pricing](/en/docs/cotizacion/productos) - [Preview and sending](/en/docs/cotizacion/envio) - [Upfront and balance](/en/docs/pagos/anticipos) · [Credit terms](/en/docs/pagos/credito) · [Retainers](/en/docs/pagos/igualas) - [Settings map](/en/docs/cuenta/mapa-de-ajustes) --- # Products and pricing URL: https://docs.cordhq.app/en/docs/cotizacion/productos Last updated: 2026-10-10 Add products, kits, and free lines, negotiate prices, use the price suggested by your history, watch your margin, and understand how taxes and discounts are calculated. ## What it is Step 2 of the editor, **What are you quoting?**, is where you add lines. Each line keeps its **List** price (from your catalog) and its **Price** (what the client will actually pay, which you can lower without touching your list price). The discount isn't a separate field: it's the difference between the two. When you create an invoice, the same step is called **What are you charging for?** and works the same way, without the margin column. The table has the columns **Item**, **Qty**, **List**, **Price**, the line's tax (only if your catalog has more than one rate), **Amount**, and **Margin** (quotes only). ## Requirements - **Permission:** Quotes to quote; **Products** to create, edit, or import the catalog. - **Plan:** all. The price suggested by history is available from Starter. Free allows up to 50 products and Starter up to 500; from Pro there's no cap. - **Per-quote limit:** 200 lines. ## Build your catalog 1. **Manually:** in **Products › + New product** you set SKU, name, description, unit, and list price. If you capture the **cost**, Cord calculates the margin. 2. **CSV import:** with **Import CSV**, Cord proposes which column is name, SKU, unit, price, and status; you confirm the mapping. Up to 2,000 rows per file; if a SKU already exists, it's updated. 3. **Kits:** group products you sell together. A kit can have a fixed **combo price**, different from the sum of its parts. See [Import your catalog](/en/docs/cuenta/catalogo) for the import details. ### Volume pricing On each product's profile you can define tiers: a fixed unit price from a minimum quantity (for example, 90 per piece from 500 units). When quoting, Cord applies the tier that matches the quantity entered. ## Add lines 1. **Search the catalog** by name or SKU in the "Search your catalog… (name or SKU)" box. On desktop, the `/` key takes you to that box. Press **Enter** to add the result and keep typing to add several in a row. 2. **Add several units at once** by typing the quantity with the search: "40 pipe", "40x pipe", or "pipe x40" add 40 units of the product, and the results list shows ×40. If what you type is already the name of a product with a number in it (for example "Bulb 100 W"), the number is read as part of the name. 3. **Insert a kit** with **+ Insert kit**: choose the kit, type how many times to insert it, and click **Add**. Cord adds all its parts multiplying the quantities; if the kit has a bundle price, it spreads it across its lines and tells you how much the client saves. 4. **Add a free line** with **+ Free line** for something that isn't in your catalog: you type the description, quantity, and price. 5. **Adjust each line:** quantity, **Price** and, if your catalog has more than one rate, the line's tax. Lines don't carry their own notes. For clarifications to the client use **Note for your client**, at the end of the editor. ## Edit, reorder, and remove lines - **Decimal quantities and prices:** quantity accepts decimals (1.5 or 0,125 kg) and price accepts a comma or a period as the decimal mark. With both separators, the last one is the decimal (1.234,50 or 1,234.50). - **Suggested tax:** if you assigned a tax rate to the product and that rate is still in your tax catalog, the line comes in with it; otherwise, with your default rate. You can change it on the line. - **Duplicate:** each row's **Duplicate line** button creates a copy right below it. - **Remove with undo:** when you remove a line, a "Removed "…"." bar with an **Undo** button appears for a few seconds. - **Reorder:** on desktop, drag the row by its handle on the left. With the keyboard, from any field on the line, use **Alt + Up arrow** or **Alt + Down arrow**. There's no dragging on a phone. - **Incomplete lines:** when you save or send, Cord marks in red a line with no description, a quantity of 0, or no price (for example, "Give this line a price (it can be 0)."). A line isn't saved at zero unless you decide so. - **Narrow screens:** in a narrow window the row rearranges itself: the list price moves under the name or, narrower still, the fields stack with their labels (Qty, Price). No amount is hidden. ## How the discount is built 1. **Client tier (automatic):** if the client has a discount on their price tier, Cord lowers the price of catalog products by that percentage and shows "Client tier: −10% applied to your catalog list prices." 2. **Shopify B2B price list (automatic):** if you connected [Shopify](/en/docs/automatizacion/integraciones/shopify) and the client buys through a company with a B2B price list, that list wins over the tier discount, product by product, and only when the quote is in the list's currency. If you already changed the price by hand, Cord doesn't overwrite it. 3. **Volume price (automatic):** if the quantity reaches a tier, the line's list price becomes the tier's. 4. **Manual price:** you can lower the price of any line. In the **Review and send** summary, **Discount given** adds up the difference between list and price across the whole quote. You can also apply a **document discount** to the whole sale (percentage, amount, or coupon), which Cord spreads across the lines before tax: see [Discounts and coupons](/en/docs/cotizacion/descuentos). Discounts are always calculated **before** taxes. The editor and the server use the same calculation engine: what you see is what's saved, charged, and invoiced. ## Price suggested by your history From Starter, when you add a catalog product Cord looks at your already decided quotes (approved, paid, invoiced, rejected, or expired) and suggests a price. It groups history into discount bands of 5 points and picks the lowest band that closes at least 60% of the time; if none does, it picks the band with the best close rate. - Cord looks first at the history of **that product**, then at **that client's**, and finally at **your whole organization's**, and uses the first with at least 3 decided lines. - The suggestion appears under the name as "Suggested: … (68% close)". Click it to apply it to the line's price. - If the price already matches the suggestion, or there isn't enough history, nothing appears. ## Margin The **Margin** column shows your profit on the price after cost: (price − cost) ÷ price. Lines without a cost show a dash. Each line's cost is kept when you reopen a draft or build a new version, so the margin isn't lost. If your organization has a minimum margin in [internal approvals](/en/docs/cotizacion/aprobaciones-internas), lines below it turn red. The margin column is internal: it doesn't appear on the link or in the PDF. ## Shopify stock If your products come from a connected Shopify store, the editor shows "N in stock", "Only N in stock" if the quantity exceeds what's available, or "Out of stock" next to each one. It's a warning: Cord doesn't block the quote. ## Real-time calculation The **Review and send** summary updates instantly: - **Subtotal:** the sum of the lines before taxes. - **Discount given:** total difference between list and price (only if there's a discount). - **Discount:** the document discount or the coupon, if you applied one, with its label (for example, "Discount (WELCOME10)"). - **Taxes:** one row per rate, with your country's name for it (IVA in Mexico and Spain, VAT in the United Kingdom, GST in Canada, Sales tax by state in the United States). - **Withholding:** if your catalog has any, it's subtracted. - **Total:** what the client will pay. ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Products in the catalog | 50 | 500 | No cap | No cap | No cap | | Price suggested by history | No | Yes | Yes | Yes | Yes | | Lines per quote | 200 | 200 | 200 | 200 | 200 | ## Common problems **"Suggested" doesn't appear.** You're on Free, the product doesn't have enough history, or the price is already the suggested one. **The margin shows a dash.** The product has no cost captured, or it's a free line. **I don't see the per-line tax column.** Your catalog has a single rate; every line uses it. **The Shopify list wasn't applied.** The quote is in a different currency from the list's, or you already edited that line's price. **I removed a line by mistake.** Click **Undo** on the bar that appears at the bottom before it closes. If it already closed, add it again from the search. **I can't drag lines on my phone.** Dragging is a desktop feature; on a phone lines stay in the order you add them. ## Related - [Discounts and coupons](/en/docs/cotizacion/descuentos) - [Client data](/en/docs/cotizacion/cliente) - [Advanced options](/en/docs/cotizacion/opciones) - [Import your catalog](/en/docs/cuenta/catalogo) - [Internal approvals](/en/docs/cotizacion/aprobaciones-internas) --- # Quote creation overview URL: https://docs.cordhq.app/en/docs/cotizacion/resumen Last updated: 2026-10-10 The full life cycle of a quote in Cord: the real statuses, who triggers each step, every guide in this section, and the limits per plan. A quote in Cord is a living document with its own link. Your team builds it in the internal editor; your client reviews, negotiates, signs, and pays from the link without creating an account. The quoting engine is the same in the 12 countries where Cord operates (Mexico, the United States, Canada, Brazil, Spain, the United Kingdom, Germany, France, Colombia, Argentina, Chile, and Peru); what changes between countries is the fiscal document that closes the cycle (see [Approval and invoicing](/en/docs/cotizacion/timbrado)). ## Requirements - **Permission:** creating, editing, sending, and resending requires the **Quotes** permission. Marking a quote as approved or rejected, and deciding internal approvals, requires **Approvals**. The account owner has every permission. - **Plan:** every plan can quote. Limits change by plan (see below). - **Country:** any of the 12 markets. CFDI 4.0 stamping is exclusive to Mexico. ## Quote statuses Cord uses eight statuses. They are the same in the app, the public link, the API, and webhooks. | Status | What it means | Who triggers it | |---|---|---| | **Draft** | Saved, but the client doesn't have an active link yet. | The seller, with **Save draft**. A quote waiting for an [internal approval](/en/docs/cotizacion/aprobaciones-internas) also stays a draft. | | **Sent** | The link is active and the client can review it. | The seller, with **Create and send**, **Send to client**, **Modify and resend**, or by dragging the card on the board. Also a manager with **Approve and send**. | | **Viewed** | The client opened the link for the first time. | The client. Only a real open with the tab visible counts; your own preview doesn't (see [What your client sees](/en/docs/interaccion/vista-del-cliente)). | | **Approved** | The client signed the full proposal or only some lines. | The client, with **Approve quote** and **Confirm and sign**. The seller can use **Mark approved** if approval came another way. | | **Rejected** | The proposal closed without a sale. | The client, with **Reject** and **Confirm rejection**. The seller with **Mark rejected**. | | **Expired** | The validity date passed without a decision. | Cord's daily process, which checks sent or viewed quotes whose validity date has passed. A [workflow](/en/docs/automatizacion/workflows/acciones) can also expire it earlier. | | **Paid** | The charge is settled. | Cord, when it confirms an online payment; or the seller with **Record payment**. | | **Invoiced** | The fiscal or commercial document was issued. | The seller, with **Stamp CFDI 4.0**, **Issue invoice**, or **Issue pro forma**. | Valid transitions are strict. For example, only a *Sent* or *Viewed* quote can be approved or rejected, and only an *Approved* or *Invoiced* quote can move to *Paid*. If two people act on the same quote at the same time, the first one wins and the second is asked to reload and try again. **Expired isn't final.** An *Expired* quote still allows **Modify and resend**. When you click **Send new version**, the validity starts over from that day with the same length it was sent with (if it was 30 days, it expires in 30 days) and the quote goes back to *Sent*. If you need a different length, client, currency, or terms, use **Duplicate quote** (see [Quote management](/en/docs/gestion/cotizaciones)). ## The workflow, step by step 1. **[Build with AI (optional)](/en/docs/cotizacion/ia).** Paste the client's order or upload a photo or PDF and Cord fills the lines from your catalog. 2. **[Choose the client](/en/docs/cotizacion/cliente).** In step 1, **Who are you quoting?**, you search for or create the client and choose their payment terms. 3. **[Add products and negotiate](/en/docs/cotizacion/productos).** In step 2, **What are you quoting?**, you add products, kits, or free lines and adjust each line's **Price** without touching your list price. 4. **[Set the terms](/en/docs/cotizacion/opciones).** In step 3, **Terms**, you choose validity, deposit, currency, and monthly retainer. 5. **[Review and send](/en/docs/cotizacion/envio).** In the **Review and send** summary you decide whether prices already include tax, apply a [discount or coupon](/en/docs/cotizacion/descuentos) if you want one, confirm the total, open the **Preview**, and send the link by email, WhatsApp, or wherever you talk to your client. 6. **[Negotiate on the link](/en/docs/interaccion/negociacion).** The client asks, comments on lines, or proposes a counteroffer; you reply with a new version. 7. **[The client signs](/en/docs/interaccion/firma).** Cord keeps the technical evidence of the approval. 8. **[Collect and invoice](/en/docs/cotizacion/timbrado).** Payment is enabled on the link and you issue the document that applies to your country. ## Every guide in this section ### Create a quote - [Generate with AI](/en/docs/cotizacion/ia): text, PDF, or photo turned into lines. - [Client data](/en/docs/cotizacion/cliente): create or pick a client, price tier, and tax data. - [Products and pricing](/en/docs/cotizacion/productos): catalog, kits, volume, suggested price, and margin. - [Discounts and coupons](/en/docs/cotizacion/descuentos): a discount on the subtotal by percentage or amount, and coupons with validity dates and a usage cap. - [Advanced options](/en/docs/cotizacion/opciones): the Terms step (validity, deposit, currency, and retainer), tax-inclusive prices, and defaults. - [Preview and sending](/en/docs/cotizacion/envio): summary, preview, autosave, shortcuts, sending, and what the client receives. - [Internal approvals](/en/docs/cotizacion/aprobaciones-internas): discount, amount, and margin caps that require sign-off. - [Approval and invoicing](/en/docs/cotizacion/timbrado): from the client's yes to the fiscal document. ### Interaction and closing - [What your client sees](/en/docs/interaccion/vista-del-cliente): the link step by step and which signals your team gets. - [Chat and comments](/en/docs/interaccion/chat): the general conversation and per-line threads. - [Negotiation and counteroffers](/en/docs/interaccion/negociacion): counteroffer, partial approval, rejection, and versions. - [Approval and evidence](/en/docs/interaccion/firma): the signature and its audit trail. ### Sales management - [Home and views](/en/docs/gestion/dashboard): Home widgets and the quotes board. - [Quote management](/en/docs/gestion/cotizaciones): filters, actions by status, duplicating, and versions. - [Clients and statements](/en/docs/gestion/clientes): directory, client profile, import, and export. - [Tasks and follow-up](/en/docs/gestion/tareas): to-dos with due dates. - [Notifications](/en/docs/gestion/notificaciones): what Cord alerts you about and through which channel. - [Reports and performance](/en/docs/gestion/informes): what each report measures. ## Limits by plan | Limit | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Active quotes (draft, sent, viewed, or approved) | 5 | 50 | No cap | No cap | No cap | | Quote sends per month | 5 | No cap | No cap | No cap | No cap | | AI builds included per month | 3 | 20 | 50 | 500 | No cap | | Lines per quote | 200 | 200 | 200 | 200 | 200 | | Live presence and client attention | No | No | Yes | Yes | Yes | | Internal approvals | No | No | No | Yes | Yes | Paid, invoiced, rejected, and expired quotes don't count as active. On Free, the AI cap is hard; from Starter up, AI overage is billed. When you hit the active-quote cap, Cord tells you how many active quotes your plan allows and asks you to free up space or upgrade. Plan details live in [Your Cord subscription](/en/docs/cuenta/suscripcion). ## Common problems **I don't see "New quote".** Your role doesn't have the Quotes permission. Ask whoever manages the team. **I can't create more quotes.** You reached your plan's active-quote cap. Close the ones that won't move forward (reject them or delete drafts) or change plans. **The client says they can't approve.** Check the status: if it's *Expired*, *Rejected*, or already *Approved*, the link no longer accepts a signature. ## Frequently asked questions **Does Cord work for businesses outside Mexico?** Yes. A quote can use any currency Cord offers (MXN, USD, CAD, BRL, EUR, GBP, COP, ARS, CLP, and PEN, plus JPY, CNY, CHF, and AUD for international trade). Online payment is available with Cord Payments in Mexico, the United States, Canada, Spain, the United Kingdom, Germany, and France, and with Mercado Pago in Mexico, Brazil, Colombia, Argentina, Chile, and Peru. Without a connected rail you can quote, invoice, and record payments you receive outside Cord. **Does CFDI 4.0 stamping work in any country?** No: stamping with the SAT is exclusive to Mexico. In Spain, Cord issues the invoice with a Verifactu record (in beta) from Starter, with the company certificate uploaded; without it, it issues a pro forma. In the other markets it issues a standard invoice; in Argentina, Brazil, Chile, Colombia, and Peru, the invoice authorized by the tax authority when issuing is active on your account. See [Approval and invoicing](/en/docs/cotizacion/timbrado). **Do I need technical knowledge?** No. Create your account, upload your catalog, and send your first quote. The [API](/en/docs/desarrolladores/funciones/cotizaciones) is optional. --- # Approval and invoicing URL: https://docs.cordhq.app/en/docs/cotizacion/timbrado Last updated: 2026-10-10 What happens when the client approves, how you record a payment, and how you issue the document that applies to your country: CFDI 4.0, Verifactu, pro forma, or commercial invoice. ## Requirements - **Permission:** on the quote detail, **Mark approved**, **Record payment**, and the button to issue the document appear for anyone with the **Approvals** permission. - **Status:** the document is issued from an *Approved* or *Paid* quote. - **Country and plan:** the document type depends on your country and plan (see below). ## Digital Approval When the client reviews the link and clicks **Approve quote** (see [Approval and technical evidence](/en/docs/interaccion/firma)), several things happen: 1. The status changes from *Sent* or *Viewed* to *Approved*. 2. The quote is commercially frozen: it can no longer be modified or resent. 3. If you configured a deposit or cash payment and your account collects online, **payment on the link is enabled** automatically. If the client approved through another channel, you can use **Mark approved** from the quote's details. ## Invoicing: a different document depending on your country Cord doesn't issue the same kind of receipt everywhere — your business's country and your plan decide the rail. The button appears in the actions panel of an *Approved* or *Paid* quote: - **Mexico:** on the Starter plan or higher, the button is **Stamp CFDI 4.0** and it stamps with the SAT through a certified electronic-invoicing provider. On the Free plan the button is **Issue pro forma**: a numbered pro forma that does not replace a tax invoice. - **Spain:** on the Starter plan or higher, with your organization's certificate uploaded, Cord issues the invoice with its chained Verifactu record and sends it to the AEAT (in beta). Until those conditions are met, the button is **Issue pro forma**: a numbered pro forma that does not replace a tax invoice. - **Argentina, Brazil, Chile, Colombia, and Peru:** the button is **Issue invoice**. If issuing with the country's authority is active on your account (new feature, from Starter), it creates the authorized e-invoice, with the legal number the authority assigns; if not, a commercial invoice. - **Other supported markets** (United States, Canada, United Kingdom, Germany, and France): the button is **Issue invoice** and it creates a commercial invoice with sequential numbering and taxes configured by the business, without automatic filing with the local tax authority. In Germany and France it can also be downloaded as a European e-invoice (see [European e-invoicing](/en/docs/pagos/factura-electronica)). See the full country-by-country detail in [Fiscal invoicing by country](/en/docs/pagos/facturacion). ### CFDI 4.0 stamping (Mexico) 1. Go to the approved (or paid) quote and click **Stamp CFDI 4.0**. Cord asks you to confirm before issuing. 2. Cord builds the CFDI with the data the client already has: the name entered under **Company**, their RFC, tax regime, postal code, and CFDI use. There's no extra step to fill them in: if the client has no RFC on file, the CFDI is issued with the **generic general-public RFC** (XAXX010101000), so review their data on their profile before stamping (see [Client data](/en/docs/cotizacion/cliente)). 3. If the client approved only some line items, only the approved lines are invoiced. If the quote carries a [document discount or a coupon](/en/docs/cotizacion/descuentos), it's reapplied to what was approved and the coupon doesn't count another use. 4. Cord sets the **payment method** from what you've already collected: if the quote is already **fully paid**, the CFDI goes out **PUE** with the payment's form; if it will be collected later (for example, with Net 30 terms), it goes out **PPD** and Cord stamps a **payment complement** for each payment it receives. See [Payment method: PUE or PPD](/en/docs/pagos/facturacion#payment-method-pue-or-ppd). 5. When it's done, the receipt appears in the **Tax documents** section of the details, with its number, its UUID, and links to download the **PDF** and the **XML**, and the quote moves to *Invoiced*. Cord doesn't email the receipt to the client automatically from this step: download it and share it, or email it from **Invoices**. **Active stamping:** to stamp on behalf of your business you need the Starter plan or higher and your CSD uploaded (see [CSD](/en/docs/cuenta/csd)). If tax stamping isn't active on your account yet, the document is marked as **Simulated** or **Tax test mode**: it's recorded for audit purposes, but it is not a valid CFDI before the SAT. ## Collections and Treasury For quotes with credit terms (Net 7 to Net 90) or those where the client only paid the advance, Cord has a **Collections** and **Treasury** module — the full picture lives in [Treasury and FX Lock](/en/docs/pagos/tesoreria-fx) and [Autonomous Collections (AI)](/en/docs/pagos/cobranza-ia); here's a summary of how it connects to a closed quote. ### Late interest Automatic application is suspended while the country-by-country legal review is completed. Saved rates do not generate new charges during this period. ### Autonomous Collections Agent (AI) Available from the **Pro** plan, Cord's AI Agent monitors your overdue portfolio and, depending on the mode you choose (Approval or Automatic), drafts personalized collection emails and can propose a monthly installment plan to the debtor, which only the debtor can accept. The full behavior lives in [Autonomous Collections (AI)](/en/docs/pagos/cobranza-ia). ### Predictive Treasury In **Reports › Cash flow · 90 days** (Pro plan or higher), Cord crosses the credit terms of your open quotes with each client's actual payment behavior to give you a more realistic estimate of the money that will actually come in over the next 90 days. ## Common problems **I don't see the button to issue.** The quote isn't *Approved* or *Paid*, or your role doesn't have the Approvals permission. **The document came out as Simulated or Tax test mode.** Stamping isn't active on your account yet: check your plan and your [CSD](/en/docs/cuenta/csd). **The invoice has fewer lines than the quote.** The client approved only some lines; only approved lines are invoiced. **The CFDI came out PPD.** The quote wasn't fully paid when it was stamped. Each payment that arrives later gets its automatic payment complement. ## Related - [Approval and evidence](/en/docs/interaccion/firma) - [Fiscal invoicing by country](/en/docs/pagos/facturacion) - [Issued invoices](/en/docs/pagos/facturas-emitidas) - [Receivables and collections](/en/docs/pagos/cartera-cobranza) --- # Import your catalog URL: https://docs.cordhq.app/en/docs/cuenta/catalogo Last updated: 2026-10-10 Create products and services, build kits, set volume pricing, and import products and clients from a CSV file with column mapping and preview. The catalog is what your team searches and adds when quoting. With it, the name, unit and price of each item always come out the same, and Cord can calculate your margin live. It lives in **Products**, in the sidebar, with two tabs: **Catalog** and **Kits**. ## Requirements - **Products permission** to create, edit and import products and to manage kits. - **Clients permission** to import clients. - **Plan limits:** how many products and clients can exist at once depends on your plan (see [Limits by plan](#limits-by-plan)). ## Create a product 1. In **Products**, select **+ New product** (or **Create › Product** in the top bar). 2. Choose what you sell: **Product**, **Service**, or **Subscription or license**. It only changes the suggested units (unit and box, hour and project, month and license); it doesn't limit anything else. 3. Enter the **Name** (required) and, optionally, the **SKU**, the **Unit**, and a **Description**. The unit is free text: pick a suggestion or type your own. 4. Enter the **Selling price**, before taxes, in your account's currency. 5. Optional: under **Your cost** enter what it costs you. Cord shows how much you earn or lose per unit and calculates the margin when quoting. Your client never sees the cost. 6. Optional: under **Tax**, choose the rate this product brings into a quote or invoice (shown when your tax catalog has more than one rate). 7. Mexico only, optional: assign its **SAT keys** (see below). 8. Optional: add **Volume pricing** (see below). 9. Choose the **Status** (Active or Inactive) and select **Save product**. An **inactive** product is no longer offered when quoting, but keeps its history and earlier quotes. **A product's tax is a suggestion.** Cord calculates taxes per **quote line**, so the same product can be taxed in one sale and exempt in another. When you add the product, the line comes in with the rate you assigned to it (or with your default rate if you didn't assign one, or if that rate is no longer in your catalog under **Settings › Quotes › Taxes**, where each rate is named after your country's tax), and you can change it on the line. Changing the product's rate later doesn't alter quotes or invoices already sent. See [Products and pricing](/en/docs/cotizacion/productos). ## SAT keys (Mexico) If your business invoices in Mexico, each product has an **E-invoicing (SAT, Mexico)** section: - **SAT product or service key:** type a word ("software", "consulting") and pick the key from the SAT catalog, or type its 8 digits. - **SAT unit key:** derived from the product's unit ("hour" → `HUR`, "month" → `MON`, "kg" → `KGM`). Type another one only if your accountant asks for a different key. Invoices read these keys when stamping. A product without a product key, or a free line, is stamped with the generic keys `01010101` and `H87`. More in [Invoicing](/en/docs/pagos/facturacion). ## Volume pricing Use it for wholesale: the price drops automatically when the line quantity reaches a tier. 1. In the product form, open **Volume pricing** and select **Add volume tier**. 2. For each tier, enter **From** (the minimum quantity) and the unit price from that quantity on. 3. Save the product. For example, with a list price of 100.00 MXN and tiers **From 500 → 90.00 MXN** and **From 2,000 → 75.00 MXN**: a 300-piece line uses 100.00 MXN, an 800-piece line uses 90.00 MXN and a 2,500-piece line uses 75.00 MXN. Below the first tier the list price applies. The client-level discount is calculated on the price of the applicable tier. ## Kits A kit groups items you usually quote together, for example an installation package, so you can insert them into a quote with one click. 1. Open **Products › Kits** and select **+ New kit**. 2. Enter the **Name** and, optionally, a description. 3. Under **Kit line items**, search catalog products by name or SKU, or add a **+ Free-form line** (for example, labor) with its description. Adjust each line's quantity. 4. Optional: turn on **Sell the kit at a fixed price** to offer a bundle. Cord shows the sum of list prices and how much the bundle saves (or how much more it costs). 5. Select **Save kit**. When quoting, use **+ Insert kit** in the editor. The lines come in as normal quote lines: you can edit or remove them like any other, and changing the kit later does not modify quotes already created. With a bundle price, Cord spreads that total across the catalog lines; free lines do not take part. Only active kits appear when inserting. ## Import products from CSV 1. In **Products**, select **Import CSV**. If you don't know the format yet, use **↓ Download sample template**. 2. **File.** Drag your file or click to choose it. Only `.csv` is accepted. 3. **Columns.** Match your file's columns to Cord's fields. Cord suggests the matching based on the header names. Uncheck **The first row is headers** if your file has none. 4. **Review.** You see how many products will be imported, how many rows are skipped for having no name, and a preview of the first rows. Decide whether to **Update existing products with the same SKU**. 5. Select **Import** to load the catalog. ### Columns that are imported | Cord field | Required | How it is read | |---|---|---| | **Name** | Yes | Rows without a name are skipped. | | **SKU / Code** | No | Stored in uppercase. It is the key for updating existing products. | | **Unit** | No | If empty, `pieza` (piece) is used. | | **List price** | No | Use a period as the decimal separator, for example `1234.50`. A negative price is stored as 0. | | **Active** | No | `0`, `no`, `false`, `inactive`, `off` or empty mark it inactive; any other value, active. Without the column, all are active. | **Not imported:** cost, description and volume pricing. Enter them in each product's form after importing. ### Update existing products With **Update existing products with the same SKU** on (the default), a row whose SKU already exists in your catalog **updates** that product instead of creating a new one. Rows without a SKU always create a new product. **When updating, Cord rewrites name, unit, price and status with what the file contains.** If you don't map the price column, updated products end up with price 0; if you don't map the unit, they end up as `pieza`. To change prices safely, first export your catalog from **Settings › Advanced › Data & privacy** (same format as the import), edit that file and import it again. ## Import clients from CSV The **Clients** directory has the same three-step assistant: **Import CSV**, match columns and review. It also offers its own sample template. | Cord field | Required | How it is read | |---|---|---| | **Company** | Yes | Rows without a company are skipped. | | **Contact**, **Email**, **Phone** | No | Text as provided. | | **Tax ID** (RFC, NIF, EIN...) | No | Validated with the country's rules and stored normalized. A row whose ID fails is skipped and the screen tells you which one and why; the rest is imported. An ID the client already had unchanged isn't validated again. | | **Payment terms** | No | A code (`net45`) is taken as is. A number is read as the closest offered term **without going over**: "45 days" becomes Net 45, "40 days" Net 30, and "5" Due on receipt. Without a number, "credit", "net", or "plazo" become Net 30. Empty or any other text, Due on receipt. | | **Credit limit** | No | A number without a currency symbol; empty means no limit. | With **Update existing clients (same tax ID or name)** on, a row that matches by tax ID or, if it has none, by company name, updates that client. As with products, empty or unmapped fields replace what the client already had. ## Limits by plan | Plan | Products | Clients | Kits | |---|---:|---:|---| | Free | 50 | 50 | No separate cap | | Starter | 500 | 500 | No separate cap | | Professional, Scale and Developer | No cap | No cap | No separate cap | Each import accepts **up to 2,000 rows**; if your file is larger, split it. Inactive products also count toward the cap. If you reach the product cap in the middle of an import, what was already imported is kept and Cord tells you how many were created and updated. ## The product page The **Products** list has quick filters: **All**, **Active**, **Inactive**, **With volume pricing**, **No cost set** and **Low margin**. Opening a product shows its page with closed revenue and units sold, win rate, price realization (minimum, average and maximum charged against list price), list margin versus realized margin, its volume pricing ladder, who buys it most, its latest quotes and which kits include it. ## Common problems **"Maximum 2000 rows per import".** Split the file into parts of 2,000 rows or fewer. **"Choose which column has the product name".** Map the **Name** field before continuing. **"The file is empty or couldn't be read".** Save it as CSV with UTF-8 encoding. An Excel file (`.xlsx`) is not accepted by this assistant: export it as CSV. **Prices were imported wrong.** Check the decimal separator: use a period and don't use periods as thousands separators. **I hit my plan's cap.** Deactivate or delete products you no longer use, or change plans in [Your subscription](/en/docs/cuenta/suscripcion). **Does your catalog live in another system?** You can keep it in sync from [Shopify](/en/docs/automatizacion/integraciones/shopify) or with the [Products API](/en/docs/desarrolladores/funciones/productos). To build the catalog from your price list in Excel, PDF or a photo, use [Set up with AI](/en/docs/cuenta/configurar-con-ia). ## Related pages - [Products and pricing](/en/docs/cotizacion/productos) - [Clients and statements](/en/docs/gestion/clientes) - [Set up your account with AI](/en/docs/cuenta/configurar-con-ia) - [Your Cord subscription](/en/docs/cuenta/suscripcion) --- # Configure your account URL: https://docs.cordhq.app/en/docs/cuenta/configuracion Last updated: 2026-10-13 Your company details, country, language and time zone, tax details, inviting your team, and the defaults for your quotes. ## 1. General company data The first step is to register your company in Cord. Go to **Settings > General** to fill in the following information: - **Name:** This is how your clients will see your company on quotes and public links. - **Currency:** the currency you quote and charge your clients in (not your Cord subscription's currency, which follows your country — see [Your subscription](/en/docs/cuenta/suscripcion)). - **Contact email, phone, and address.** - **Website and WhatsApp** (shown on your public link). - **Country of operation:** sets the regulatory rail Cord uses — which tax fields it asks for, which tax rates it seeds by default, and the invoicing vocabulary (see below). - **Time zone:** used to calculate and display the dates on your quotes and invoices. - **Language:** applies to the app, your public links, and the emails Cord sends on your behalf. Each person can see the interface in another language from [Your preferences](/en/docs/cuenta/preferencias); what your clients receive stays in this one, except for clients you give another language in their record (see [Document language](/en/docs/gestion/clientes#document-language)). The tax details used for invoicing (Legal name, your tax ID, fiscal address) are captured separately, under **Settings › Invoicing › Tax details**. That form changes based on your country: in Mexico it asks for **RFC** and **Tax Regime** and enables the CSD for CFDI 4.0 (see [Add tax information](/en/docs/cuenta/csd)); outside Mexico it asks for your legal name, your local tax ID (NIF/CIF in Spain, EIN/Tax ID in the US...), address, and invoice prefix — Cord issues a numbered invoice with an immutable copy and a PDF. Cord does not automatically file it with the local tax authority. In Spain, Verifactu (in beta) requires Starter or higher and a valid electronic certificate; see [Fiscal invoicing by country](/en/docs/pagos/facturacion). ## 2. Invite your sales team Selling is usually a team effort. From the **Pro** plan, Cord lets you invite as many team members as your plan allows (you'll see your seat usage and limit right on the screen). Go to **Settings > Team and permissions** and select **Add member**. See [Team, permissions, and security](/en/docs/cuenta/equipo-seguridad). ### Roles and permissions Every invite starts from a permission **preset** you can use as-is or customize field by field: - **Admin:** almost all control, including the team; the Refunds permission isn't enabled by default. - **Sales rep:** quotes, clients, products, and analytics; doesn't manage settings or approve. - **Read only:** can enter the app without modification permissions, useful for audits. - **Custom:** toggle individual permissions (quoting, catalog, clients, collections, settings...) when none of the three presets fits. From each member's profile you can see their effective role, last session, recent activity, edit their permissions, resend the invitation, revoke access, or re-invite them if already revoked. If you restricted invitations to your company's email domains (`Settings > Security`), an invite to an address outside those domains is rejected before it sends. A member who signs in through SSO has permissions managed by your identity provider and isn't edited here. ## 3. Quote defaults If your business sells on credit (you don't charge upfront, but on 7, 15, 30, 45, 60, or 90-day terms), you don't have to configure it manually on every quote. Go to **Settings > Quotes > Numbering & tax** to set the values every new quote starts with: - **Default validity (days).** - **Default payment terms:** *Due on receipt* or a *Net* term of 7, 15, 30, 45, 60, or 90 days. Every new quote inherits this term (you can still change it per quote, and the client's profile wins when you pick one). See [Credit terms](/en/docs/pagos/credito). - **Default deposit (%).** - **Quote number prefix** and the **legal notice** that accompanies the PDF. **The credit limit is a signal, not an automatic block.** Each client can have their own credit limit (**Clients > [client]**). Cord uses it to warn you — on the client's profile and in Collections — how much open balance they carry against that limit, but it doesn't by itself stop a new quote from being created; the call to pause selling to an over-exposed client is still yours. --- # Set up your account with AI URL: https://docs.cordhq.app/en/docs/cuenta/configurar-con-ia Last updated: 2026-10-11 Cord reads your website, a description of your business and your price list, and proposes your setup for you to approve. ## How it works When you finish signing up, Cord asks for three things, all optional: - **Your website.** It provides your name, contact details, logo and brand color. - **What your business does.** How you charge, on what terms and which taxes you handle, in your own words. For example: "we sell building materials on 30-day credit and withhold 4% on freight". - **Your price list** as Excel, CSV, PDF or a photo, up to 4 MB. Cord builds your catalog from it with SKU, unit and price. From that it builds a proposal and shows it to you for review. You can change any field, drop the logo, uncheck products or taxes, or leave out a whole section (Brand, Business or Quotes) with its **Apply this section** box, and then apply it. That way you can update, for example, only the catalog. If you'd rather do it later, skip it: the assistant also lives in **Settings › General › Set up with AI**. ## What it proposes | Section | What it includes | |---|---| | Branding | Logo from your website, brand color and PDF template. | | Business | Name, legal name, tax ID, email, phone and address. | | Quotes | Payment terms, validity, number prefix, tax-inclusive pricing, PDF conditions and message. | | Taxes | Only the ones your business uses that your catalog doesn't have yet. They arrive **unchecked**. | | Catalog | The products from your price list, in your currency. | | Messages | WhatsApp messages for sharing your quotes. They are saved in **Settings › Templates** and appear when you tap **WhatsApp** on a quote. | ## What it doesn't do - **It applies nothing without you.** The AI only drafts. Every field is validated with the same rules as Settings: an RFC with a wrong check digit, an invalid email or an absurd rate is dropped, and the review tells you why. - **It doesn't make up tax data.** If it can't validate your tax ID for your country, it doesn't propose it. - **It doesn't upload your certificate or enable payments.** The CSD (Mexico), the Verifactu certificate (Spain) and Cord Payments remain your steps. - **It doesn't obey your website.** What it reads from your page or your file is treated as content, never as instructions. You can generate up to six proposals a day per company, and each one expires after 7 days if you don't apply it. ## From the terminal or an agent The same proposal can be requested from outside the app, and it always ends in the same review: - **CLI:** `cord setup --sitio yourcompany.com --archivo prices.xlsx` opens the review in your browser and shows the result in the terminal. See [Cord CLI](/en/docs/desarrolladores/herramientas/cli). - **AI agents:** with the [MCP server](/en/docs/desarrolladores/herramientas/mcp), the `proponer_configuracion` tool shares the review link with you. - **API:** `POST /api/v1/setup/plans` returns `review_url`. Through this route the file can be up to 3 MB. See the [API reference](/en/docs/desarrolladores/referencia). If you open the link while in the test environment, Cord asks you to leave it: the proposal sets up your real account. ## Pending proposals and history In **Settings › General › Set up with AI**, below the assistant: - **Proposals to review:** the ones not applied yet, including those requested by the CLI, the API or an agent. Each one shows where it came from (website, file or description), where it was requested and which person or key requested it, and what it contains. **Review** opens the same review. - **History:** applied, discarded, failed or expired proposals, with who applied it, when, and what happened in each section. --- # Create your account URL: https://docs.cordhq.app/en/docs/cuenta/crear-cuenta Last updated: 2026-10-11 How to sign up for Cord with email or Google, verify your email, choose your country, and what Cord sets up from that choice: currency, taxes, time zone and online payments. Creating a Cord account has three moments: **signing up** (your personal identity), **setting up your workspace** (the organization you will quote and collect with) and, optionally, **setting up with AI** your brand, catalog and taxes. Every new account starts on the **Free** plan, with no card required and no expiration date. ## Requirements - **Country:** your business must operate in one of the 12 available countries: Mexico, the United States, Canada, Brazil, Spain, the United Kingdom, Germany, France, Colombia, Argentina, Chile or Peru. - **Plan:** none. Signing up creates a Free account; you can change plans later from [Your subscription](/en/docs/cuenta/suscripcion). - **Email:** if you sign up with a password, you need access to the inbox to confirm the address before you can sign in. ## 1. Sign up 1. Open [cordhq.app/sign-up](https://cordhq.app/sign-up). 2. Choose how to sign up: - **With email:** enter your first name, last name, work email and a password of at least 10 characters that does not contain your email. The meter under the field tells you how strong it is. - **With Google:** use the **Google** button below the form. The **Apple** button says **Coming soon**: it is not available yet. 3. Read the privacy summary above the boxes (who processes your data and why) and check both legal boxes: you accept the **Terms and Conditions** and declare that you'll use Cord for your business or professional activity, not as a consumer, and you confirm you read the **Privacy Notice**. Without them, the sign-up buttons stay disabled. Confirming the privacy notice does not authorize optional analytics. 4. Select the button to create your account (or the Google button). ### Email verification If you signed up with email and password, Cord **does not sign you in yet**: it takes you to a verification screen and emails you a link. Open it from your inbox to confirm the address and continue. - The link expires after **24 hours**. - The resend option on that screen sends a new link; earlier ones keep working until they expire. - If the link is no longer valid, the screen tells you and lets you request another. With **Google** there is no verification step: Google has already confirmed your email. **Were you invited to a team?** If you arrived from an invitation, sign up with the same email you were invited with. After you confirm your email, Cord takes you back to the invitation so you can join that organization with the permissions you were given. You will not see the setup wizard: only the organization owner completes it. See [Team, permissions and security](/en/docs/cuenta/equipo-seguridad). ## 2. Set up your workspace The first time an organization owner enters the app, Cord opens a full-screen **four-step** wizard. You can move forward with **Continue** or the `Enter` key, and go back with **Back**. 1. **What's your company called?** Enter the name your clients will see on every quote and choose the **Country you operate in**. Cord preselects a country based on your location; check it before continuing. 2. **What's your role?** Owner or director, Sales, Finance / Admin, Operations or Other. 3. **What does your business do?** Choose your industry and team size. 4. **What will you use Cord for?** Select all that apply (quote faster, collect payments online, issue invoices, follow up on quotes, control margins or automate collections) and select **Finish**. ### What your country sets up The country is not decorative: Cord uses it so the account is ready to operate in your market from day one. | What is set | How | |---|---| | **Currency** | The country's currency, for example MXN in Mexico, EUR in Spain, Germany and France, GBP in the United Kingdom, COP in Colombia. It is the currency you quote and charge your clients in; you can quote in another currency when you need to. | | **Time zone** | That of the country's capital or main business center. Your quotes and invoices are dated with it. | | **Language** | Spanish if the country's language is Spanish; English everywhere else. | | **Taxes** | Cord seeds your tax catalog with the country's standard, editable rates (see below). | | **Tax vocabulary** | The name of your identifier (RFC, NIF / CIF, EIN / Tax ID, CUIT, NIT, RUT, RUC...) and of the tax (IVA, VAT, USt., TVA, IGV, Sales tax...). | | **Invoicing** | In Mexico, CFDI 4.0 with your CSD. In the other countries, a commercial invoice with a number and PDF; in Argentina, Brazil, Chile, Colombia, and Peru, the invoice authorized by the tax authority when issuing is active. See [Invoicing by country](/en/docs/pagos/facturacion). | You can change all of these later in **Settings › General**, except the tax catalog, which you edit in **Settings › Quotes › Taxes**. ### Taxes created at the start Seeded rates are a starting point, not tax advice: review them with your accountant and adjust the ones that do not apply to your business. - **Mexico:** IVA 16%, IVA 8% border region, Exempt and the most common IVA and ISR withholdings. - **Spain:** IVA 21%, 10% and 4%, Exempt and IRPF withholdings (15%, and 7% for new self-employed). - **Canada:** GST 5%, the provincial HST rates, QST, PST and RST, and Zero-rated. - **United Kingdom, Germany and France:** the country's VAT, USt. and TVA rates and Zero-rated. - **Colombia, Argentina, Chile and Peru:** the country's IVA or IGV and Exempt; Colombia and Peru also include their usual withholdings. - **United States:** there is no national rate. As soon as you declare your state in your tax details, Cord offers that state's sales tax plus the exempt option. - **Brazil:** no suggested rate on purpose (taxes depend on the state and the municipality); enter your own in Settings. ### Online payments by country | Country | How you collect online inside the link | |---|---| | Mexico | Cord Payments, which includes SPEI, or Mercado Pago. | | United States, Canada, Spain, United Kingdom, Germany and France | Cord Payments. Besides card, depending on the country: [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) (EUR, GBP, or USD) and [bank debit](/en/docs/pagos/domiciliacion) (SEPA, ACH, Bacs, or Canadian pre-authorized debit). | | Brazil, Colombia, Argentina, Chile and Peru | Mercado Pago. Cord Payments is not available in these countries and Cord tells you before you start. | In every country you can record manual payments (bank transfer, cash) without connecting a payment method. See [Payment methods](/en/docs/pagos/metodos). ## 3. Set up with AI (optional) When you select **Finish**, Cord offers **Set up your account with AI**: you give it your website, a description of your business or your price list, and it proposes your brand, catalog, terms and taxes for you to review before applying them. - **Build my proposal** generates the proposal; review it and select **Apply setup**. - **I'll set it up later** takes you straight to your dashboard. The assistant stays available in **Settings › General › Set up with AI**. When you finish, if you are going to connect Cord to your own system, the **Connecting Cord to your code?** panel shows three [CLI](/en/docs/desarrolladores/herramientas/cli) commands that check themselves off as you run them. Full details in [Set up your account with AI](/en/docs/cuenta/configurar-con-ia). ## 4. Finish setup with the widget ### The welcome The first time you open your account, the content steps aside, blue lights come on behind the guide and Cord tells you your next step: for example, **Next, create your first quote**. The headline and description come from what you answered in the wizard: your goals, your role, your industry, your team size and your country. **Get started** takes you straight to that step; **Got it** closes the welcome and leaves the guide open. The welcome appears only once, only to the organization owner and only during the first 14 days after finishing the wizard. It does not appear in the test environment. ### The essential steps While your account is incomplete, the app shows the **Set up Cord** widget with its essential steps in 5 sections: 11, or 10 if you answered that you work alone. Each step checks itself off when Cord detects the change in your account; there are no boxes to tick by hand. | Section | Step | It checks off when... | |---|---|---| | Set up your business | Customize your brand | You upload a logo or enter a contact email or phone. | | | Complete your tax details | You save your tax identifier (RFC, NIF, EIN...). | | | Customize your PDF and portal | You write the PDF message or terms, or the portal welcome. | | Build your catalog | Create your catalog (**Build your service catalog** if you sell services or software) | You have at least one product. | | | Add your clients | You have at least one client. | | Close your first sale | Create your first quote | You save your first quote. | | | Send your first quote | A quote leaves draft. | | Get paid | Turn on online payments (or **Get paid with Mercado Pago** in CO, AR, CL and PE) | Any online payment method is enabled. | | | Charge and invoice | A quote is paid or invoiced. | | Grow your operation | Automate your follow-up | You have a published, active workflow; a draft does not count. | | | Invite your team | There is a second active or invited member (requires the Pro plan or higher). It does not appear if you work alone. | The step marked **Up next** is the one that brings you closest to what you said you wanted to do with Cord, and its section opens first. If you chose **Collect payments online**, for example, the guide takes you to online payments first; if your role is Finance / Admin, to invoicing and collecting before quoting. Every step has **Configure**, which opens the matching screen, and **Read the guide**, which opens its page in these docs. ### Recommended for you At the end of the guide you'll find **Recommended for you**: optional steps picked from your answers. Each one says why it's recommended and none of them count toward finishing the guide. | Step | Recommended if... | It checks off when... | |---|---|---| | Add your costs | You chose **Control margins**. | At least one product has a cost. | | Schedule your first follow-up | You chose **Follow up on quotes**. | You have at least one task. | | Issue your first invoice | You chose **Issue invoices** or your role is Finance / Admin. | You issue an invoice (a draft does not count). | | Upload your CSD | Your country is Mexico and you chose **Issue invoices**. | Your digital seal certificate is uploaded. | | Turn on AI collections | You chose **Automate collections**. | The collections agent is on. | | Connect your Shopify store | Your industry is Retail. | Shopify is connected. | | Connect your accounting | Your role is Finance / Admin and your industry is not Retail. | QuickBooks Online or Xero is connected. | | Connect your tools | In every other case. | You connect an integration or a notification channel (Slack, Teams or WhatsApp). | | Create your API key | Your industry is SaaS / Technology. | You have an active API key. | If a step needs a higher plan than yours, it says so next to the title (for example, **Pro plan**). The widget can be **minimized to the bar**: it becomes a pill with your completion percentage (**Setup guide**) in the top bar. **Hide guide** removes it from the screen; reopen it from **Help › User guide**. Each organization tracks its own progress: if you manage several, one does not mix with another. A test organization never completes the widget. ## Common problems **"Check your details — email must be valid and password at least 10 characters."** Fix the email format or use a longer password. **"Use at least 10 characters."** The password is shorter than the minimum. A phrase of several words is easier to remember and harder to guess. **"Your password can't contain your email."** Remove your email, or the part before the @ sign, from the password. **"This password appears in public data breaches. Choose another one."** That password already circulates in leaked lists from other sites, so it would be among the first tried against your account. Choose one you do not use anywhere else. Cord checks it without your password leaving Cord. **I already had an account with that email.** Sign-up answers as usual ("check your email") and you receive a **You already have a Cord account** email with a button to sign in. Cord never shows on screen which emails have an account. If you do not remember the password, use recovery from the sign-in screen. **The verification email did not arrive.** Check spam and promotions, wait a couple of minutes and use the resend option on the verification screen. Asking for another one does not cancel the earlier ones: any link that has not expired (24 hours) works. **I opened the link on another device and was not signed in.** The link only opens a session in the browser where you signed up. Anywhere else it confirms your email and asks you to sign in with your password, so nobody who signs up with your email ends up with a session of yours. **I chose the wrong country.** Change it in **Settings › General**. Then review the currency, the time zone and your tax catalog: Cord does not replace rates you already had. **I don't see the four-step wizard.** It only appears to the owner of an organization that has not completed it yet. An invited member goes straight into the app. ## Related pages - [Set up your account with AI](/en/docs/cuenta/configurar-con-ia) - [Configure your account](/en/docs/cuenta/configuracion): general details and defaults. - [Add tax information (CSD)](/en/docs/cuenta/csd): Mexico only. - [Import your catalog](/en/docs/cuenta/catalogo) - [Your Cord subscription](/en/docs/cuenta/suscripcion) - [Complete app map](/en/docs/operacion/mapa-de-la-app) --- # Add tax information (CSD) URL: https://docs.cordhq.app/en/docs/cuenta/csd Last updated: 2026-10-07 Upload your Digital Seal Certificate to enable CFDI 4.0 invoicing. **This article applies to accounts with Country of operation = Mexico.** The CSD and CFDI 4.0 are a Mexico-only requirement. If your business operates in another country, your **Settings › Invoicing › Tax details** screen doesn't show the CSD: you capture your local invoicing identity there instead (legal name, your local tax ID — NIF/CIF, EIN/Tax ID, depending on your country — and address), and Cord issues your invoice with a number, an immutable copy, and a PDF. In Spain, a chained Verifactu record (in beta) is created from Starter, with the company's electronic certificate uploaded; without it, the invoice is issued as a pro forma, without registration with the Spanish tax authority. ## What is a CSD and why do you need it? The **Digital Seal Certificate (CSD)** is an electronic document issued by the SAT that allows you to digitally sign (stamp) your electronic invoices. Unlike the FIEL (e.firma), the CSD is used exclusively for issuing tax receipts. For Cord to convert your approved quotes or orders directly into an official invoice with the SAT without having to re-enter data on another portal, **it is mandatory** to upload your CSD. CFDI issuance requires the **Starter plan or above**; see tax invoice allowances in [Your subscription](/en/docs/cuenta/suscripcion). ## Before you start - **Starter plan or above.** The CSD can't be uploaded on Free. - **Settings permission** in your organization role. - **Complete tax details:** RFC, legal name, tax regime, and issuing postal code, entered on the same screen. Without them Cord rejects the upload and asks you to complete them first. - **Recent sign-in:** because this is a sensitive action, Cord may ask you to confirm your identity again before accepting the files. ## Steps to upload your CSD in Cord 1. Go to **Settings › Invoicing › Tax details**. 2. In the **Digital Seal Certificate (CSD)** section, choose your files and enter the password: - **`.cer` file**: The public certificate. - **`.key` file**: Your private key. - **Key password**: The password you chose when processing your CSD with the SAT (Note: this is usually different from your FIEL password). It is only used to decrypt your `.key` and is not stored in Cord. 3. Click **Upload CSD and connect**. **Warning:** the file and password travel over HTTPS/TLS to the server and fiscal provider. Cord keeps only the secret reference required to operate the integration encrypted at rest; do not describe this as end-to-end encryption. We never use your FIEL: upload only the CSD and never your FIEL (e.firma) for invoicing. ## Validations and Common Errors When you upload your CSD, the fiscal provider Cord stamps with reviews the certificate. If it is rejected, you'll see the reason on screen. The most common cases: - **Validity:** an expired CSD (they last 4 years) is rejected; renew it on the SAT portal and upload it again. - **RFC:** Cord stamps under the certificate's RFC, so the CSD must belong to the RFC you entered in your tax details. - **Incorrect password:** if the password can't open the `.key` file, the upload is rejected. Once accepted, the section shows **CSD uploaded**, and any closed quote will be able to issue its CFDI 4.0 with a single click. --- # Export your data and delete the organization URL: https://docs.cordhq.app/en/docs/cuenta/datos-y-eliminacion Last updated: 2026-10-15 Download all your organization data and your tax documents as PDF and XML, and schedule the deletion of the organization or your account with 30 days to cancel. Everything lives in **Settings › Data & privacy**. Exporting and downloading tax documents requires the Settings permission; deleting the organization requires being its owner. ## Export all organization data **All organization data (ZIP)** downloads one JSON file per table, in the `tablas/` folder: the business profile and settings, the team and its permissions, domains and SSO, catalog, taxes and coupons, clients, quotes with their lines, versions, comments, signatures and visits, invoices, payments, charges, refunds, disputes, payouts and fees, collections (conversations, promises, plans and interest), tasks and events, workflows with their runs, integrations, API keys and webhooks (without their secrets), the history of the tax rails and the full audit log, with no cap. The last file in the ZIP is `manifiesto.json`, with: - `completa`: `true` only if every table was read. - For each table: its file, how many records it holds and which columns were left out, with the reason. - The tables that are not exported and why. - The parts available in the tax documents download. Never included: | Reason | What is left out | |---|---| | Secrets | Keys and token hashes, signing secrets, your clients’ access links and what Cord stores encrypted, such as the full payout account number (only its last four digits are included). | | Tax credentials | Certificates and their passwords, private keys, authorized number ranges and sessions with the tax authority. | | Integration access | Tokens of connected apps and addresses that work like a password, such as a webhook or notification channel URL. | | Technical data | Access challenges and expirations, queues, retries, locks, live presence and the API and webhook logs, which are deleted after 30 days. | | Cord’s records | Support notes and access, courtesy grants, provider usage, fee invoicing batches and evidence of acceptance of Cord’s terms. | | Identity verification | The evidence Cord keeps under its own obligations. The people registered on the payments account are exported. | | Tax files | Signed XML, invoicing records and tax authority responses: they are in the tax documents download. | | Event log | The one that feeds webhooks and the API: it repeats what is already in the tables and includes access links to your documents. | Team members’ personal accounts (password, sessions, passkeys and two-step verification) belong to each person; the team and its permissions are in `org_members`. **How to check that everything was exported.** Open `manifiesto.json` and look for `"completa": true`. If the export could not read every table within the download time, it says `"completa": false`, marks the tables that were cut short and the ZIP includes `EXPORTACION-INCOMPLETA.txt`. If a read fails, the download stops with an error and the ZIP won’t open: a file with empty or missing tables is never delivered. In both cases, export again. Each table is read separately: if someone works in the account while you export, a new record may appear in one table and not yet in another. You can export up to five times every 10 minutes. - **Catalog and clients (CSV):** the same format as the import, to open in Excel or move to another tool. ## Download your tax documents Keeping your invoices is your business's obligation: Cord does not replace your tax archive. Under **Tax documents (PDF and XML)** you download one ZIP per year, in parts of up to 100 documents. 1. Open **Settings › Data & privacy**. 2. Under **Tax documents (PDF and XML)**, find the year. 3. Click **Download ZIP** or, if the year has more than 100 documents, each part (for example **1 to 100** and **101 to 200**). The year is the issue date's year in the organization's time zone. Issued and voided documents are included; drafts are not. Each document goes in its own folder, with: | Document | What it includes | |---|---| | CFDI (Mexico) | PDF and stamped XML, the payment complements (XML and PDF), and the cancellation receipt when a cancellation was requested. | | Verifactu (Spain) | PDF with the QR code and the billing records with the AEAT's response. | | Invoice transmitted through the certified platform (France) | PDF, the transmitted Factur-X, and the statuses the platform returned. | | ARCA (Argentina) | PDF with the CAE and the authorization data. ARCA does not provide an XML of the receipt. | | NFS-e (Brazil) | PDF, the signed DPS, and the NFS-e XML. | | NF-e (Brazil) | PDF, the procNFe (the NF-e with its authorization protocol), and the cancellation or correction letter events. | | SUNAT (Peru) | PDF, the signed XML, and the receipt confirmation (CDR). | | SII (Chile) | PDF, the signed DTE and the EnvioDTE envelope, in ISO-8859-1 as they were signed, and the SII's response. | | DIAN (Colombia) | PDF, the signed XML, and the DIAN's response (ApplicationResponse). | | Any other invoice | PDF. | Each ZIP also includes an `indice.csv` with one row per document: folder, number, type, country, issue date, status, total, currency, the files included, and what's still pending with its reason. The CFDI files are requested from the stamping service at download time; if one didn't respond, the index marks it and you only need to download that part again. The European e-invoice versions (Factur-X, XRechnung, Peppol, and Facturae) are downloaded from each invoice, not from this ZIP. ## Delete the organization Only the owner can delete it. Deleting doesn't erase anything right away: it schedules the deletion in 30 days. 1. Open **Settings › Data & privacy** and, in the danger zone, click **Delete organization**. 2. Enter your password (or the code from your authenticator app if you sign in without a password). 3. Type the organization's exact name. 4. Confirm that keeping your invoices is your business's obligation and that you'll download them before the date. 5. Click **Schedule deletion**. During those 30 days: - The organization stays open: the team can sign in and download the tax documents. - The danger zone shows the date and the **Cancel deletion** button. If you cancel, everything stays as it was. Once the deletion has started on that date, it can't be canceled. - No subscription renewals are charged during this period: if one falls due in those days, its invoice stays pending and isn't charged. Anything already owed before you scheduled the deletion is still collected. Changing plans is blocked until you cancel the deletion. When the organization is deleted, the subscription is canceled and nothing left pending from this period is charged. - If you cancel the deletion, billing resumes, including any renewal that fell due during this period. If you had already scheduled your subscription to cancel, that stays in place. - The owner gets an email when it's scheduled and another one a few days before the date. On that date Cord deletes the organization's quotes, clients, products, invoices, API keys, webhooks, and team. Provider records, backups still in rotation, and pseudonymous contract evidence are handled separately. An organization with Verifactu records can't be deleted: the law requires keeping them. If those records appear during this period, the deletion isn't completed: the organization stays, its subscription no longer renews and ends at the end of what you already paid for, and we let you know by email. If you want to close it without erasing those records, write to soporte@flouvia.com. The test environment isn't deleted here: you empty it with **Clear test data**. ## Delete your personal account The danger zone in **Your account** deletes your account, sessions, passkeys, and connected accounts. It requires your password (or your code) and typing your email. - **No organizations of your own:** the account is deleted right away. - **You're the sole owner of an organization with more members:** first transfer ownership or delete that organization. - **You're the sole owner and there's no one else:** the deletion of those organizations is scheduled in 30 days and your account is deleted with them. Until then you can sign in, download their tax documents, and click **Cancel deletion** in **Your account**. ## Common problems **"We couldn't stop your subscription's charges".** Nothing was scheduled. Try again in a few minutes. **I don't see the delete button.** Only the organization's owner can schedule or cancel the deletion. **The ZIP index lists pending files.** Download that part again; the documents that did arrive come out complete again. **The export ZIP won’t open.** The download stopped before finishing: export again. A complete file includes `manifiesto.json` with `"completa": true`. **I can't change plans.** The organization has a scheduled deletion: cancel it first. ## Related pages - [Settings map](/en/docs/cuenta/mapa-de-ajustes): what each Settings tab contains. - [Team, permissions, and security](/en/docs/cuenta/equipo-seguridad): ownership, roles, and your personal account. - [Your Cord subscription](/en/docs/cuenta/suscripcion): plans, allowances, and cancellation. --- # Custom domain URL: https://docs.cordhq.app/en/docs/cuenta/dominio-propio Last updated: 2026-10-07 Serve your quote and invoice links from a subdomain of your company: requirements, TXT and CNAME DNS records, connection statuses, and what happens if it stops being available. With a custom domain, the link your client receives no longer starts with `cordhq.app` and uses a subdomain of your company instead. Your main website does not change: Cord only uses the address you assign to it. ## Requirements - **Professional plan or higher.** On Free and Starter the tab shows **View Professional plan**. - **Settings permission** in your role. - **An unused subdomain** of a domain you already own, for example `quotes.yourcompany.com`. You do not need to buy another domain. Root domains (`yourcompany.com`), wildcards, IP addresses, ports and paths are not accepted. - **Access to the DNS panel** where you manage your domain. - **Being outside the test environment.** In test mode the tab shows **Unavailable in the test environment**. An organization has one custom domain at a time. ## Connect your domain Open **Settings › Brand appearance › Custom domain**. 1. **Choose your domain.** In **Subdomain** enter only the hostname, without `https://`, paths or ports, and select **Save domain**. 2. **Configure DNS.** Cord shows a table with **Type**, **Name** and **Value**. First comes an ownership **TXT** record, named `_cord.` followed by your subdomain. Add it in your DNS panel exactly as shown (use **Copy name** and **Copy value**). 3. Select **Verify connection**. Once Cord confirms the TXT, the **CNAME** record that connects your subdomain appears. Add it as well. 4. Select **Verify connection** again until the status reads **Active**. DNS changes can take time to propagate, and the HTTPS certificate also needs time. **Keep the TXT record** after your domain is active: Cord checks it again periodically. Only change the subdomain you are going to use, without touching your website or email records. If your DNS panel appends the domain to the name automatically, do not type it twice. ## Connection statuses | Status | What it means | What to do | |---|---|---| | **Setup pending** | The domain is saved, but the connection is not active. | Add the DNS records and verify. | | **Waiting for DNS** | Cord has not confirmed your records yet. | Check names and values; verify again later. | | **Preparing HTTPS** | DNS is correct and the certificate is being issued. | Wait a few minutes and verify again. | | **Active** | Your address works and is secured with HTTPS. | Nothing; you can open it with **Open domain**. | | **Needs attention** | The connection could not be completed. | Read the message shown with the status; if it persists, contact support. | Status is checked when you open the tab or select **Verify connection**. The screen shows the **Last verified** date. ## What changes once it is active - **New links use your domain.** The public link of every quote (`/q/...`) and every invoice (`/i/...`), including the one in the emails Cord sends on your behalf, is built with your subdomain. - **The root of your subdomain** shows a minimal page with your business branding. - **Only your documents are served.** Your domain cannot be used to enter the app, Settings or another organization's documents: a link that does not belong to your account does not open there. - **Your links are not indexed** by search engines. ## If the domain stops being available - **If the connection fails or a verification expires,** Cord tries to verify it again when someone opens a link. Until it is confirmed, new links are generated with `cordhq.app` so your sends keep working. - **If you downgrade,** links your clients already have with your domain redirect them to the same quote or invoice on `cordhq.app`. Nothing is deleted; you get your domain back when you return to an eligible plan. - **If the tab says "Custom domains are being prepared",** the connection is not yet available for your account. Your links keep working on `cordhq.app`; you will be able to set it up there when it is ready. ## Disconnect or change domain To use a different domain, first disconnect the current one with **Disconnect domain** and confirm. Links using that address will no longer be available at it. Cord does not remove records from your DNS provider: delete them yourself if you no longer need them. ## Common problems **"We could not find the ownership TXT."** Check that the name starts with `_cord.` and that the value is complete, without extra quotes. **"The DNS server did not respond."** Do not change your records because of this message: wait one minute and verify again. **"This address is already assigned or needs a review."** Contact support. Do not delete its configuration to try connecting it again. **"Enter a valid domain name."** Enter only the subdomain, without a protocol, paths or ports. **"You do not have permission to manage domains."** Ask your organization's administrator to give you the Settings permission or to make the connection. ## Related pages - [Customize your branding](/en/docs/cuenta/marca) - [Client portal](/en/docs/cuenta/portal-cliente) - [Your Cord subscription](/en/docs/cuenta/suscripcion) - [Preview and sending](/en/docs/cotizacion/envio) --- # Team, permissions, and security URL: https://docs.cordhq.app/en/docs/cuenta/equipo-seguridad Last updated: 2026-10-14 How to invite members, assign permissions, require 2FA, restrict domains, manage sessions, passkeys, OAuth, SSO access, and emergency access in Cord. Cord has three distinct access layers: 1. **Your account** protects personal identity: password, 2FA, passkeys, sessions, and the connected Google account. 2. **Team and permissions** decides what each member can do inside an organization. 3. **Organization security** applies requirements such as 2FA, inactivity timeout, and allowed domains for invitations. ## Plans and seats Inviting a team and using custom roles start on **Professional**. The current included allowance is: | Plan | Included users | Additional users | |---|---:|---| | Free | 1 | Not available | | Starter | 1 | Not available | | Professional | 5 | Monthly charge per user | | Scale | 15 | Monthly charge per user | | Developer | Unlimited | Included | A valid invitation already reserves a seat even if it has not been accepted yet. If the indicator is full, revoke an invitation you won't use or review your plan. Additional user rates are in [Your subscription](/en/docs/cuenta/suscripcion). ## Invite a person 1. Open **Settings › Team & permissions › Team & roles** and select **Add member**. 2. Enter their email. 3. Choose Admin, Rep, Read only, or a custom combination. 4. Review each permission and send the invitation. The invitation expires after **7 days**. Cord tries to send it by email and also returns a copyable link as a backup. **Resend** rotates the previous token and creates a new one valid for seven days; the old link stops working. If the organization restricts domains, the email must end exactly in one of the domains configured under **Settings › Team & permissions › Security**. The rule also covers link-only invitations: it is checked when the invitation is accepted, against the email of the account the person signs in with, so an account from another domain cannot join even if it has the link. Each link works only once. ## Roles and permissions Roles are editable presets, not a replacement for effective permissions: - **Admin:** almost everything, including team; refunds are not enabled. - **Rep:** quotes, clients, products, and reports; no settings or approvals. - **Read only:** enters the app without modification permissions. - **Custom:** a combination saved specifically for that member. - **Super admin:** whoever created the account (the owner). Full access by definition; cannot be downgraded or revoked from Team. The independent permissions are Quotes, Approvals, Collections, Clients, Products, Reports, Settings, Payment settings, Refunds, and Team. Who can grant what: - The owner can grant any permission. - Anyone else with the Team permission can only grant the permissions they have themselves, whether inviting, editing a member, or choosing a role. What the member already had is kept even if the editor doesn't have it, and removing permissions is always allowed. - **Refunds** can only be granted by the owner. - Nobody can change their own permissions or role: ask someone else who manages the team. - Resending a link-only invitation that grants permissions you can't grant is up to the owner, because the new link comes back to you. Hiding a button is not the security boundary. The APIs validate the permission and the active organization again before reading or modifying data. ## Membership states - **Active:** accepted the invitation and keeps access. - **Invited:** the link is still pending; it may be valid or expired. - **Revoked:** no longer enters the organization. The record is kept to show history and the person can be invited again. The screen shows last session, recent quotes, and last action when data is available. Revoking removes access; it does not automatically reassign or delete documents that person created. ## Require two-step verification Under **Settings › Team & permissions › Security**, turn on **Require two-factor authentication (2FA)** for the organization. A member who has not set up TOTP yet is sent to **Settings › Your account** to finish activation before continuing to use protected sections. Personal activation happens under **Settings › Your account**: scan the QR code with your authenticator app, confirm the code, and save the ten single-use backup codes shown on activation. Store those codes outside Cord. Regenerating them invalidates the previous set. Disabling 2FA requires your current password or an authenticator code, depending on the account type. When you sign in, each authenticator code works only once and each backup code is spent when used. From the third failed code in a day, Cord sends you the email **Sign-in attempt with your password** (at most one per hour): whoever tried it typed your correct password, so change it if it wasn't you. After ten failed codes in 24 hours, the second step is paused except from a network where you already have an open session; resetting your password lifts the pause. When the organization requires 2FA, protection also applies to dashboard requests, not only to the visible screen. Actions needed to set up 2FA, confirm your identity, or sign out remain available. If a sensitive action asks you to verify your identity again, complete it before retrying. Team permissions are still required; having 2FA does not grant permission to refund or administer the business. ## Passkeys and password Under **Settings › Your account** each person can: - create or change their password; - register several passkeys compatible with the device or key manager; - remove a passkey they no longer recognize; - connect or disconnect Google. Apple shows as **Coming soon**: it isn't available yet. An account created with OAuth can set a password later. Before disconnecting the last working method, confirm you keep another way to sign in. Every new password, when you sign up, recover it or change it, must be at least 10 characters long, cannot contain your email and cannot appear in public data breaches. If your current password predates this rule, it still works for signing in; the rule applies the next time you change it. ## Active sessions The session list shows device, known IP, last activity, and which one is the current session. You can close an individual session or all the others. The organization can also configure an inactivity timeout under **Settings › Team & permissions › Security**: unlimited, 1, 4, 8, or 24 hours. This rule is different from manually closing personal sessions. The timeout is checked when entering the app, billing, and protected internal APIs, and also when registering a passkey. When it expires, the operation stops and you must sign in again. Activity is measured by authenticated requests to those surfaces, not by moving the mouse; automatic app requests may also count. Visiting a public page or using the 2FA recovery routes does not restart the window. "Unlimited" disables the inactivity timeout but keeps the maximum session lifetime, revocations, and account suspension. ## Enterprise SSO SAML 2.0 connections are administered under **Settings › Team & permissions › SSO** and require the **Scale or Developer** plan and the **Team** permission. A saved configuration does not guarantee access after losing that plan. The technical setup of the connection (Entity ID, sign-in URL, certificate, domains, provisioning, and role mapping) is in [SSO & SAML](/en/docs/desarrolladores/seguridad/sso). Members managed by SSO are flagged in Team, and their permissions are managed by your identity provider. ### Require SSO Once a connection is working, you can require your team to sign in only through SSO. 1. Under **Settings › Team & permissions › SSO**, confirm you have at least one **Active** connection with a verified domain. Without one, Cord rejects the change. 2. Under **Require SSO**, turn on **Require your team to sign in via SSO**. 3. Save. With the option on, Cord blocks password, Google, Apple, and passkeys for every member **except the account owner**, who always keeps their password as a fallback. ### Emergency access If your identity provider is down and your team cannot sign in, the owner can temporarily disable the requirement: 1. Under **Settings › Team & permissions › SSO**, select **Disable for 1 hour**. 2. Confirm your password (or your verification code) and select **Disable for 1 hour**. During that hour the team can use their other sign-in methods again, and the screen shows **SSO temporarily disabled until** the expiration date and time. When it ends, the requirement comes back on its own. Only the owner can use this option, and the action is recorded in the organization's audit log. ## Delete a personal account The danger zone in **Your account** permanently deletes the personal identity, sessions, passkeys, and connected accounts. It requires a credential and typing the email to confirm. Without organizations of their own, the account is deleted right away. If that person is the sole owner of an organization with more members, they must transfer ownership first; if there's no one else, that organization's deletion is scheduled in 30 days and the account is deleted with it, with time to download the tax documents and cancel. Details in [Data and deletion](/en/docs/cuenta/datos-y-eliminacion). ## Common problems **I can't invite.** Check the Team permission, Professional plan or higher, an available seat, and an allowed domain. **The link expired.** Use Resend; don't try to recover the previous token. **I can't grant a permission.** You can only grant the permissions you have, and Refunds can only be granted by the owner. **The person can't accept the link.** If the organization restricts domains, they must sign in with an account from one of those domains. **The person signs in but can't edit.** Check the effective permissions, not only the role name. **The organization requires 2FA.** The person must complete TOTP in their own account; an administrator cannot generate the codes for them. **"Too many attempts" when signing in.** Ten failed passwords from the same device in 15 minutes pause that device for that long. If the attempts come from many places (30 in an hour), the account only lets you in from a network where you already have an open session. In both cases, resetting your password from the forgot-password link on the sign-in screen lifts the pause. Cord never says on screen whether an email has an account. **I got "Sign-in attempt with your password".** Someone typed your password and failed the verification code. If it wasn't you, change it under **Settings › Your account** and sign out the sessions you don't recognize. **Opening my organization asks me to sign in with SSO again.** Your organization requires SSO and the session wasn't opened with its identity provider (for example, you signed in through the SSO of another organization you also belong to). Sign in with this one's. **I can't turn on Require SSO.** You need an active connection with at least one verified domain. **The identity provider is down.** The owner can sign in with their password and use **Disable for 1 hour**. ## Related pages - [SSO & SAML](/en/docs/desarrolladores/seguridad/sso) - [Your Cord subscription](/en/docs/cuenta/suscripcion): included seats and additional users. - [Settings map](/en/docs/cuenta/mapa-de-ajustes) - [Create your account](/en/docs/cuenta/crear-cuenta) --- # Complete Settings map URL: https://docs.cordhq.app/en/docs/cuenta/mapa-de-ajustes Last updated: 2026-10-15 Reference for every Settings category and tab in Cord: your account, general, brand, team, notifications, plans, advanced, quotes, invoicing, payments, integrations, and developer options. Open **Settings** with the gear in the top bar. The index groups categories into four sections: **Personal settings**, **Account settings**, **Product settings** and **Developers**. Each category opens its first tab and shows the others in a horizontal bar. The index search (and the **⌘K** palette) also recognizes alternative terms: IVA, VAT, RFC, NIF, CSD, SAML, DNS, API and others. Organization changes affect everyone working in that workspace. Your password, 2FA, passkeys and sessions are personal and don't change when you switch organizations. ## Before changing anything - Confirm you are in the right organization, and outside the test environment if you are configuring something real. - **Settings** controls most tabs; **Team**, **Payment configuration** and other sensitive operations have their own permissions. - Many values are defaults for new documents: documents already sent or issued keep their version. - Availability by country and plan is shown inside each screen. An option appearing on this map does not mean it is enabled for every account. ## Personal settings ### Your account › Profile & security Your name, picture, emails, password, connected Google account (Apple coming soon), 2FA, backup codes, passkeys, active sessions, and deleting your personal account. Guide: [Team, permissions and security](/en/docs/cuenta/equipo-seguridad). ### Your account › Preferences Theme, interface language, home page, developer mode, and which notices you get by email in each organization. They're only yours and need no permissions. Guide: [Your preferences](/en/docs/cuenta/preferencias). ## Account settings ### General | Tab | What it contains | |---|---| | **General** | Business name, base currency, contact email and phone, address, website, WhatsApp, country of operation, language and time zone. Guide: [Configure your account](/en/docs/cuenta/configuracion). | | **Set up with AI** | A proposal for your brand, profile, taxes, catalog and templates based on your website and price list, the proposals waiting for review (including those from the CLI, the API or an agent) and the history of what was applied. Guide: [Set up your account with AI](/en/docs/cuenta/configurar-con-ia). | Changing the base currency does not convert historical amounts. ### Brand appearance | Tab | What it contains | Plan | |---|---|---| | **Identity** | Primary and on-color logo, size, palette and typography, with a preview on portal, quote, PDF and email. Guide: [Customize your branding](/en/docs/cuenta/marca). | All | | **Client portal** | Layout, top announcement, welcome, comments and counteroffers, Cord branding. Guide: [Client portal](/en/docs/cuenta/portal-cliente). | All; removing Cord branding from Starter | | **Custom domain** | A subdomain of your company for your links, with DNS records and verification. Guide: [Custom domain](/en/docs/cuenta/dominio-propio). | Professional or higher | ### Team & permissions | Tab | What it contains | Plan | |---|---|---| | **Team & roles** | Members, invitations, roles and per-section permissions. | Inviting from Professional | | **SSO** | SAML 2.0 connections, **Require SSO** and emergency access. Requires the Team permission. | Scale or Developer | | **Security** | Require 2FA, allowed domains for invitations and inactivity timeout. | All | Guide: [Team, permissions and security](/en/docs/cuenta/equipo-seguridad). ### Notifications | Tab | What it contains | Plan | |---|---|---| | **Notifications** | A matrix of which event alerts through each channel: email, Slack and Microsoft Teams. Slack and Teams only alert if their channel is connected; the new-member alert only arrives by email. Guide: [Notifications](/en/docs/gestion/notificaciones). | All | | **Email** | Sender name, reply-to address, introduction and signature of the emails to your clients, with a preview. | Customizing from Starter | ### Plans & subscription **Subscription:** your effective plan, status, cycle, usage for the period, plan changes and access to Billing for your card, receipts and invoices. Guide: [Your Cord subscription](/en/docs/cuenta/suscripcion). ### Advanced | Tab | What it contains | Plan | |---|---|---| | **Data & privacy** | Export all organization data (a ZIP with one JSON file per table and a manifest of counts and exclusions), catalog and clients as CSV, tax documents as PDF and XML (one ZIP per year, in parts of up to 100), data retention, and the danger zone to schedule the organization's deletion in 30 days (requires recent authentication and typing its name). Guide: [Data and deletion](/en/docs/cuenta/datos-y-eliminacion). | All | | **Settings history** | Who changed the configuration and when, with previous and saved values (last 50). You can restore appearance and text values with no later changes; it does not restore logos, payments, permissions or tax data. | Professional or higher | | **Audit log** | Relevant actions with actor, date, resource and context. | Professional or higher | ## Product settings ### Quotes | Tab | What it contains | Plan | |---|---|---| | **Numbering & tax** (outside Mexico, **Numbering & taxes**) | Number prefix and series, validity, payment terms, deposit and default legal text. | All | | **Taxes** | Rate catalog with name, type (consumption, withholding or exempt) and rate, and whether your prices include tax. Guide: [Products and pricing](/en/docs/cotizacion/productos). | All | | **PDF document** | Minimal, Classic or Detailed template, footer message, terms and line-item listing. | All | | **Approvals** | Internal thresholds for maximum discount, maximum amount and minimum margin. Late-payment interest shows as **Coming soon**: it will be turned on per country once its legal review is complete. Guide: [Credit terms](/en/docs/pagos/credito). | Scale or Developer | | **Templates** | WhatsApp messages with variables such as `{cliente}`, `{empresa}`, `{folio}`, `{total}` and `{link}`. When you tap **WhatsApp** on a quote you choose which one to send, or the standard message. | All | ### Discounts | Tab | What it contains | Plan | |---|---|---| | **Coupons** | Discount codes by percentage or fixed amount, with validity dates, currency, total and per-client usage caps, and a switch to pause them. Creating, editing, or deleting requires the Settings permission. Guide: [Discounts and coupons](/en/docs/cotizacion/descuentos). | All | ### Invoicing **Tax details** (outside Mexico, **Tax profile**): in Mexico, RFC, legal name, tax regime, postal code, CFDI use and your CSD to stamp CFDI 4.0; in the other countries, your local tax identifier, address and invoice prefix. Issued invoices live in **Invoices** in the sidebar. Guides: [Add tax information (CSD)](/en/docs/cuenta/csd) and [Invoicing by country](/en/docs/pagos/facturacion). **Reminders:** turn automatic reminders to your customers on or off, choose the invoice schedule (up to 8 moments before, on, and after the due date), and resume paused customers. Guide: [Automatic payment reminders](/en/docs/pagos/recordatorios). All plans. ### Payments All four tabs require the **Payment settings** permission. | Tab | What it contains | Plan | |---|---|---| | **Account** | Cord Payments onboarding and verification, and your account status: payments and payouts (enabled or paused), verification and, if details are missing, their deadline. Under **Danger zone**, **Disconnect Cord Payments**. In Colombia, Argentina, Chile and Peru it tells you Cord Payments isn't available and takes you to connect Mercado Pago. Guide: [Connect account (KYC)](/en/docs/pagos/onboarding). | All | | **Payment methods** | One switch per method, saved right away, with its status and its fee: card and, depending on your country, automatic transfer (SPEI in Mexico; bank transfer with a reference in Spain, Germany, France, the United Kingdom, and the United States) and direct debit (SEPA, ACH, Bacs, or pre-authorized debit); **Allow automatic payments**; Mercado Pago in Mexico, Brazil, Colombia, Argentina, Chile and Peru, and manual transfer with your bank details. At the top, **Your client will see** sums up what's turned on. Guides: [Payment methods](/en/docs/pagos/metodos), [Automatic payments](/en/docs/pagos/cobro-automatico) and [Mercado Pago](/en/docs/pagos/mercado-pago). | All | | **Payouts** | With an active account: available and processing balance, next payout, the last five payouts, the payout bank account (changing it requires recent authentication) and the frequency. Guide: [Payouts to your bank](/en/docs/pagos/depositos). | All | | **Fees** | The fee for each method in your country, always visible, and the Cord Payments fee version you accepted or the checkbox to accept the current one. Guide: [Cord Payments fees](/en/docs/pagos/condiciones). | All | ### Integrations **Integrations:** a directory of 13 apps —HubSpot, Shopify, Google Sheets, Microsoft Excel, Gmail, QuickBooks Online, Xero, Slack, Microsoft Teams, WhatsApp Business, Make, Zapier and n8n— with one page per app to connect it, configure it and see the workflows that use it. Apps marked as upcoming have no committed date. Guide: [Integrations](/en/docs/automatizacion/integraciones). ## Developers This group appears in the index only when you turn on **Developer mode** at the bottom of Settings. The same switch turns on the **Cord Workbench** dock across the app. Each tab's direct URL works even when the mode is off. | Category | What it contains | Plan | |---|---|---| | **MCP** | Configuration to connect an AI assistant to Cord through the MCP server. Guide: [MCP Server](/en/docs/desarrolladores/herramientas/mcp). | All | | **Artificial intelligence** | Status of **AI collections** (Off, On · with your approval or On · automatic) and connections to your other systems: for each one you choose, tool by tool, what the AI may use when quoting. Guides: [Autonomous collections (AI)](/en/docs/pagos/cobranza-ia) and [Your connected systems](/en/docs/cotizacion/ia#your-connected-systems). | AI collections from Professional; agent governance on Scale or Developer | | **Embeddable quote builder** | Preview, allowed domains and code to embed the quote builder on your site. Guide: [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen). | All | API keys, webhooks, logs and events are not in Settings: they live in [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). ## If a change doesn't show up 1. Confirm the save finished without an error. 2. Check the effective organization, permission, country and plan. 3. Open a new document if the option only works as a default. 4. Leave test mode if you are validating an external provider. 5. If it persists, note the route, time, user, expected result and visible message before contacting [support](https://cordhq.app/en/support). ## Related pages - [Complete app map](/en/docs/operacion/mapa-de-la-app) - [Create your account](/en/docs/cuenta/crear-cuenta) - [Your Cord subscription](/en/docs/cuenta/suscripcion) --- # Customize your branding URL: https://docs.cordhq.app/en/docs/cuenta/marca Last updated: 2026-10-11 Add your logo, colors, and typography so your links, documents, and emails carry your identity. ## First impressions matter When a prospect receives your quote, the first thing they see is Cord's **Interactive Public Link**. Ensuring this link carries your visual identity is key to conveying professionalism and trust. Open **Settings › Brand appearance**. The category has three tabs: **Identity**, **Client portal**, and **Custom domain**. Changes apply when you save; until then you can **undo changes** or **reset style**. ## Identity Your identity is shared: it's used on your portal, your quotes, and your emails. ### 1. Logo - Upload a **PNG, JPG, SVG, or WEBP** image up to **1 MB**. Its original proportions are preserved. - You can upload a **primary** logo and an **on color** variant, used on colored document, portal, and email headers. - Choose the **logo size**: small, medium, or large. ### 2. Brand palette - Start with one of the suggested palettes or enter your exact hex colors (Example: `#0071e3`). - The **primary** color is required; the **secondary** color is optional. ### 3. Typography - Choose **System**, **Humanist**, or **Editorial**. It applies to the portal, quotes, and emails; commercial invoices use an equivalent print font. **Tip:** button text automatically adapts to your primary color to stay readable. ### Preview The preview shows a sample quote with your brand, in your currency, with your tax and your numbering prefix, on **Portal**, **Quote**, **PDF**, and **Email**, on desktop or mobile, and lets you compare your draft with what's saved. It doesn't generate activity or messages. ## Client portal Under **Settings › Brand appearance › Client portal** you adjust the layout, top announcement, welcome, comments and counteroffers, and Cord branding (removing it requires the **Starter plan or above**). Full guide: [Client portal](/en/docs/cuenta/portal-cliente). ## Custom domain From the **Professional** plan you can serve your links from a subdomain of your company, for example `quotes.yourcompany.com`. Full guide: [Custom domain](/en/docs/cuenta/dominio-propio). ## PDF document and emails The PDF design (template, footer message and terms) is configured under **Settings › Quotes › PDF document**. The sender, introduction and signature of your emails, under **Settings › Notifications › Email** (customizing them requires the Starter plan or above). ## Related pages - [Client portal](/en/docs/cuenta/portal-cliente) - [Custom domain](/en/docs/cuenta/dominio-propio) - [Settings map](/en/docs/cuenta/mapa-de-ajustes) --- # Client portal URL: https://docs.cordhq.app/en/docs/cuenta/portal-cliente Last updated: 2026-10-13 What your client sees when opening a quote link and how to adjust it: layout, top announcement, welcome, comments and counteroffers, and Cord branding by plan. The **client portal** is the page that opens when your client clicks a quote link. They need no account or password: the link is their access. From there they review the proposal, comment, approve or reject and, when applicable, pay online. This page is about the link of each **quote**. To give a client a single link with all their **invoices**, their balance, and paying several at once, see [Client portal: invoices and payments](/en/docs/pagos/portal-facturas). The layout, top announcement, welcome message and **Show Cord branding** switch on this page also apply to that portal; the layout and announcement also apply to each invoice page. ## Requirements - **Settings permission** to change the portal configuration. - **All plans** can customize layout, announcement, welcome and comments. - **Starter or higher** to remove Cord branding. - **Professional or higher** to serve the portal from your own domain. See [Custom domain](/en/docs/cuenta/dominio-propio). ## What your client sees | Element | Detail | |---|---| | **Header with your brand** | Your logo, colors and typography from [Identity](/en/docs/cuenta/marca). | | **Top announcement** | A strip in your brand color, if you wrote an announcement. | | **Welcome** | Your welcome message, if you wrote one. | | **Line items** | Each item with quantity, price and amount, in the quote's currency. If the negotiated price is lower than the list price, the list price appears struck through. | | **Partial approval** | While the quote is open, each line has an **Include this line in your approval** checkbox. | | **Line comments and conversation** | If comments are on: a button to comment on each line and a general chat with **Counteroffer**. | | **Approve or reject** | **Approve quote** records the signer's name and technical evidence; **Reject quote** accepts an optional reason. | | **Online payment** | If you have an active payment method and the quote allows it. See [Accept a payment](/en/docs/pagos/aceptar). | | **Download PDF** | The quote document. | | **Contact** | Shortcuts to reach you by WhatsApp, email or phone, based on the contact details you entered in Settings › General. | | **Activity notice** | "Whoever sent you this proposal can see when you open it and which sections you review." | | **Cord branding** | The "Verified by Cord" seal, unless your plan allows removing it and you turned it off. | **Your own visit does not count as a view.** If you open the link while signed in to Cord, you see a **Preview — this is what your client sees** strip. Cord does not record that visit as client activity or trigger "viewed" alerts. ## Customize the portal 1. Open **Settings › Brand appearance › Client portal**. 2. Under **Layout**, choose the header style (**Essential**, **Soft** or **Contrast**), **Corners** (Precise, Soft or Rounded) and **Spacing** (Comfortable or Compact). 3. Under **Messages**, write the **Top announcement** (up to 200 characters; leave it empty to hide it) and the **Welcome message** (up to 280 characters). 4. Under **Interaction**, turn **Comments and counteroffers** and **Show Cord branding** on or off. 5. Check the preview on the right and save. The preview shows a sample quote on **Portal**, **Quote**, **PDF** and **Email**, on **Desktop** or **Mobile**, and lets you compare **Your draft** against **Saved**. It generates no activity or messages. ## Behavior and edge cases - **Layout is shared.** The header style, corners and spacing are also used in emails and commercial invoices. The quote PDF has its own design under **Settings › Quotes › PDF document**. - **Turning comments off does not delete the conversation.** The client stops seeing the per-line button, the chat and the counteroffer, but earlier messages are kept on your side. - **Closed quote.** Once approved or rejected, the partial-approval checkboxes and the option to comment on lines disappear. - **Logo and colors** are not edited here: they come from **Identity**. The **Edit** link on the **Shared identity** card takes you there. - **The contact details** your client sees come from **Settings › General**: if you leave WhatsApp, email or phone empty, that shortcut does not appear. - **The language is the quote's**, not your interface's: buttons, labels and the PDF appear in that client's document language (or your organization's), and your notice and welcome message are shown exactly as you wrote them. See [Document language](/en/docs/gestion/clientes#document-language). ## Cord branding by plan | Plan | Cord branding in the portal | |---|---| | Free | Always visible. The switch appears disabled and takes you to review your plan. | | Starter, Professional, Scale and Developer | You can hide it with **Show Cord branding**. | If you downgrade to Free, the branding shows on your links again even if you had turned it off; when you return to an eligible plan your choice is respected again. ## Common problems **I saved an announcement and don't see it.** Open the link in a new window and confirm the text was not left empty. Remember the announcement appears on the quote link. **The client says they can't comment.** Check that **Comments and counteroffers** is on and that the quote is still open. **I can't remove Cord branding.** You need the Starter plan or higher; see [Your subscription](/en/docs/cuenta/suscripcion). ## Related pages - [Customize your branding](/en/docs/cuenta/marca) - [Custom domain](/en/docs/cuenta/dominio-propio) - [Chat and negotiation](/en/docs/interaccion/chat) - [Approval and evidence](/en/docs/interaccion/firma) - [Preview and sending](/en/docs/cotizacion/envio) - [Client portal: invoices and payments](/en/docs/pagos/portal-facturas) --- # Your preferences URL: https://docs.cordhq.app/en/docs/cuenta/preferencias Last updated: 2026-10-13 Choose your theme, interface language, home page, developer mode and which notices you get by email. They're only yours and follow you on any computer. Open **Settings › Your account › Preferences**. You don't need any permission: each person has their own. Each change saves right away and follows you on any computer or browser where you sign in. ## Interface | Preference | What it does | |---|---| | **Theme** | Light, dark or same as system. The theme button in the top bar changes this same preference. | | **Interface language** | Spanish, English, Portuguese, French, German or the company's. It only changes what you see: your clients keep receiving quotes, invoices, PDFs and messages in their document language, the one each client has in their record or, if they have none, the company's, chosen in **Settings › General**. | | **Home page** | Where you land when you open Cord (when you sign in, from a bookmark or by typing the address). **Home** stays in the sidebar and takes you to the usual dashboard. | | **Developer mode** | Shows the **Developers** category in Settings and the developer console. | ## My email notices For each notice you choose **All**, **Only mine** or **None**: - **Only mine** means the quotes you created. - **Someone joined the team** isn't tied to a document: there it's only **All** or **None**. - Notices belong to the organization you're in: if you belong to several, you choose in each one. - Each email reaches you in the interface language you chose. For each notice you haven't changed: - **The owner** gets what the company had checked for email in **Settings › Notifications**. If it was never saved, they get approved, rejected and paid quotes. - **The rest of the team** gets their own approved, rejected and paid quotes. Slack, Microsoft Teams and the task reminder are set up for the whole team in [Notifications](/en/docs/gestion/notificaciones). --- # Account Overview URL: https://docs.cordhq.app/en/docs/cuenta/resumen Last updated: 2026-10-14 How to prepare your Cord account to quote, collect and invoice: the setup widget, its 11 tasks and the guides in this section. ## Your account, ready step by step Cord is available to businesses in the 12 markets currently offered: Mexico, the United States, Canada, Brazil, Spain, the United Kingdom, Germany, France, Colombia, Argentina, Chile, and Peru. After you [create your account](/en/docs/cuenta/crear-cuenta), the floating **Set up Cord** widget organizes 11 tasks into 5 sections and updates its progress as you complete each one; you can minimize it without losing your progress. 1. **Set up your business** - **[Customize your brand](/en/docs/cuenta/marca):** logo, color, and contact details for your public link. - **Complete your tax details:** your country's invoicing identity — in Mexico, RFC, tax regime, and postal code to stamp CFDI 4.0 (and then the [CSD](/en/docs/cuenta/csd)); outside Mexico, your legal name, your local tax ID, and your address. - **Customize your PDF and portal:** the message, terms, and welcome copy that go on your PDFs and portal. 2. **Build your catalog** - **[Create your catalog](/en/docs/cuenta/catalogo):** add at least one product or service. - **Add your clients:** register your first client. 3. **Close your first sale** - **Create your first quote:** manually or with [Cord AI](/en/docs/cotizacion/ia). - **Send your first quote:** to the prospect's email, or by sharing the link. 4. **Get paid** - **Turn on online payments:** connect Cord Payments (card and, depending on your country, SPEI, [bank transfer with a reference](/en/docs/pagos/transferencia-referencia), or [bank debit](/en/docs/pagos/domiciliacion)) or, where applicable, [Mercado Pago](/en/docs/pagos/mercado-pago). In Colombia, Argentina, Chile, and Peru, where Cord Payments isn't available, the step is completed with Mercado Pago. - **Charge and invoice:** the task is marked once your first quote is paid —online or marked by hand— or invoiced. 5. **Grow your operation** - **[Automate your follow-up](/en/docs/automatizacion/workflows):** turn on your first workflow. - **[Invite your team](/en/docs/cuenta/equipo-seguridad):** invite a second member with the right role (team invitations require Pro or above). Every task marks itself done automatically as soon as Cord detects the change in your account — no checkbox to tick by hand. The section open by default is always the first one you still have pending. ## Guides in this section - [Create your account](/en/docs/cuenta/crear-cuenta): sign-up, verification, country and the initial wizard. - [Configure your account](/en/docs/cuenta/configuracion): general details, team, and defaults. - [Settings map](/en/docs/cuenta/mapa-de-ajustes): what each Settings tab contains. - [Set up with AI](/en/docs/cuenta/configurar-con-ia): a setup proposal you review and approve. - [Branding](/en/docs/cuenta/marca): logo, colors, and the look of your documents. - [Client portal](/en/docs/cuenta/portal-cliente): what your client sees when opening the link. - [Custom domain](/en/docs/cuenta/dominio-propio): your links from a subdomain of your company. - [Catalog](/en/docs/cuenta/catalogo): products, services, and import. - [Tax information (CSD)](/en/docs/cuenta/csd): digital seal for CFDI 4.0 in Mexico. - [Team, permissions, and security](/en/docs/cuenta/equipo-seguridad): members, roles, 2FA, sessions, and SSO. - [Your subscription](/en/docs/cuenta/suscripcion): plans, allowances, and limits. - [Data and deletion](/en/docs/cuenta/datos-y-eliminacion): export data, download tax documents, and delete the organization or your account. **Tip:** Do you have multiple companies? Cord is **multi-company**. You can manage several companies or legal entities from a single login. The setup widget tracks progress independently per company, so one company's progress never mixes with another's. --- # Your Cord subscription URL: https://docs.cordhq.app/en/docs/cuenta/suscripcion Last updated: 2026-10-10 Plans in MXN, USD and EUR, included allowances, overage, how to change plan or billing cycle, what happens when you downgrade, and your subscription receipts. Your subscription pays for using Cord. It is separate from what you charge your clients: the currency you quote in, Cord Payments fees and your client invoices are managed separately. ## Requirements - **Settings permission** to see the plan, change it and open Billing. - **Outside the test environment.** In test mode the screen shows **Not available in test mode** and you cannot subscribe or change plans. - **Developer** is not self-service: it is agreed with sales. ## Your subscription currency Cord charges you in one of three currencies, based on your organization's country: | Country | Subscription currency | | --- | --- | | Mexico | MXN | | Spain, Germany and France | EUR | | United States, Canada, Brazil, United Kingdom, Colombia, Argentina, Chile and Peru | USD | **An existing contract keeps its currency.** Once you have paid an invoice in a currency, Cord keeps charging you in it even if you change your account's country, language or currency. The currency you choose in **Settings › General** is the one you sell in, not the one for your subscription. ## Pricing | Plan | MXN per month | USD per month | EUR per month | | --- | ---: | ---: | ---: | | Free | 0 MXN | 0 USD | 0 EUR | | Starter | 240 MXN | 12 USD | 12 EUR | | Professional | 590 MXN | 30 USD | 30 EUR | | Scale | 1,390 MXN | 70 USD | 70 EUR | | Developer | Via sales | Via sales | Via sales | The **annual cycle** costs ten monthly payments and is charged yearly (for example, Starter annual: 2,400 MXN, 120 USD or 120 EUR). Overage is billed separately and is not part of that saving. Prices include taxes: what you see is what you pay. ## Monthly allowances | Plan | AI builds | Tax invoices | Commercial invoices | API requests | Included users | Quotes sent | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | Free | 3 | Not included | 10 | 100 | 1 | 5 | | Starter | 20 | 30 | Unlimited | 1,000 | 1 | Unlimited | | Professional | 50 | 200 | Unlimited | 5,000 | 5 | Unlimited | | Scale | 500 | 500 | Unlimited | 10,000 | 15 | Unlimited | | Developer | Unlimited | 1,000 | Unlimited | 50,000 | Unlimited | Unlimited | Check your usage for the period under **Settings › Plans & subscription › Plan usage this period**. ## Capacity limits Besides monthly allowances, Free and Starter cap how many resources can exist at the same time. These are not billed as overage: to go past them you need to upgrade. | Plan | Active quotes | Products | Clients | Active workflows | | --- | ---: | ---: | ---: | ---: | | Free | 5 | 50 | 50 | 1 | | Starter | 50 | 500 | 500 | 5 | | Professional, Scale and Developer | No cap | No cap | No cap | No cap | An **active** quote is one that is still live: draft, sent, viewed or approved. Paid, invoiced, rejected or expired quotes do not count. ## Overage **Free has hard limits**: when you reach the limit, the feature stops until next month or until you upgrade. From Starter on, usage above the allowance is charged at the end of the period, and only the overage is billed, never the included amount again. Free's quote sends have no overage: the cap of five per month is fixed. | Extra item | Starter | Professional | Scale | Developer | | --- | ---: | ---: | ---: | ---: | | AI build | 4.00 MXN | 3.50 MXN | 3.00 MXN | Unlimited | | Tax invoice | 3.00 MXN | 3.00 MXN | 2.00 MXN | 1.50 MXN | | 100 API requests | 0.60 MXN | 0.60 MXN | 0.40 MXN | 0.40 MXN | | Additional user per month | Not available | 300 MXN | 300 MXN | Unlimited | | Extra item | Starter | Professional | Scale | Developer | | --- | ---: | ---: | ---: | ---: | | AI build | 0.20 USD | 0.175 USD | 0.15 USD | Unlimited | | Tax invoice | 0.15 USD | 0.15 USD | 0.10 USD | 0.075 USD | | 100 API requests | 0.03 USD | 0.03 USD | 0.02 USD | 0.02 USD | | Additional user per month | Not available | 15 USD | 15 USD | Unlimited | | Extra item | Starter | Professional | Scale | Developer | | --- | ---: | ---: | ---: | ---: | | AI build | 0.20 EUR | 0.175 EUR | 0.15 EUR | Custom | | Tax invoice | 0.15 EUR | 0.15 EUR | 0.10 EUR | Custom | | 100 API requests | 0.03 EUR | 0.03 EUR | 0.02 EUR | Custom | | Additional user per month | Not available | 15 EUR | 15 EUR | Custom | Rates are fixed per currency, not a daily exchange-rate conversion. Starter keeps a single user: to invite a team you need Professional or higher. As a safeguard, exceptionally high usage in a period is stopped and asks you to contact us before continuing. ### Invoices with automatic sales tax (US only) This feature is new and may not be enabled on your account yet. If you do not see it, write to us. If your business is in the United States and you turned on sales tax by the client's address (see [Invoicing by country](/en/docs/pagos/facturacion)), each issued invoice or paid quote recorded for your filing in a state where you collect counts once against its own monthly allowance, separate from tax invoices. Previews don't count, a sale to a state where you don't collect doesn't either, and voiding an invoice doesn't give the unit back. | Plan | Included per month | Each additional one | | --- | ---: | ---: | | Free | Not included | — | | Starter | 10 | 15.00 MXN · 0.75 USD · 0.70 EUR | | Professional | 25 | 15.00 MXN · 0.75 USD · 0.70 EUR | | Scale | 60 | 15.00 MXN · 0.75 USD · 0.70 EUR | | Developer | 150 | 15.00 MXN · 0.75 USD · custom in EUR | When you reach your allowance, Cord tells you before you save or send the document. If overage billing for this allowance isn't enabled on your account yet, automatic calculation stops until next month or until you upgrade; meanwhile you can enter the rate manually by turning it off in **Settings › Taxes**. A sale that arrives without allowance isn't lost: it waits and is recorded automatically once there is room, and **Settings › Plans & subscription** shows how many are waiting. ## Change plan or billing cycle 1. Open **Settings › Plans & subscription** and select **Change plan**. 2. Choose the **Monthly** or **Annual** cycle (**2 months free**). 3. Select **Choose** on the plan you want. For Developer, the button takes you to sales. 4. Review the summary, currency and total, and confirm the payment. What happens depending on the change: - **Upgrading** applies immediately. Cord charges the prorated difference for the current period right away, and the new capabilities turn on once the payment is confirmed. - **Downgrading** or **changing only the cycle** (for example, monthly to annual on the same plan) is scheduled for the end of your paid period. You keep your current plan until that date. - **Canceling** is done from **Billing** and takes effect at the end of what you already paid for: on the annual plan, at the end of the year, even though overage is billed monthly. Any scheduled plan change is dropped. You can resume the subscription before that date; while it's set to cancel, you need to resume it before changing plans. ## What happens when you downgrade **Your data is not deleted.** Quotes, clients, products, invoices, members and settings are kept. What changes is what can keep operating: - **Resources over the cap** (active quotes, products, clients, active workflows): existing ones are kept, but you cannot create more (or activate more workflows) until you are below the new plan's limit. - **Team:** if the new plan includes fewer users, the owner and the first members that fit in the plan, by seniority, keep operating. The others keep their membership but cannot operate until you regain seats. - **Plan features** (collections, recurring invoices, SSO, approvals, custom domain, audit log...): they stop operating, with their configuration saved, until you return to an eligible plan. - **Cord branding:** if you downgrade to Free, it shows on your links again. - **Custom domain:** links with your domain redirect to `cordhq.app`. See [Custom domain](/en/docs/cuenta/dominio-propio). - **Issued invoices** remain available for download and payment. Issuing a new tax invoice requires Starter or higher. ## Past-due payment If a subscription charge fails, your paid plan is not guaranteed: Cord only grants paid capabilities with an active subscription and a period covered by a paid invoice. Until it is resolved, your account operates with Free permissions. From **Billing** you can settle the past-due charge without leaving Cord; once paid, you get your plan back. ## Billing and receipts In **Settings › Plans & subscription**, **Go to Billing →** opens [billing.cordhq.app](https://billing.cordhq.app), where you manage your card, review charges and download receipts. A charge receipt and a tax invoice are different documents. In Mexico you can request the CFDI for a subscription payment from Billing, with your tax details complete. Only a paid charge with an amount is invoiced; a 0 MXN charge does not generate a CFDI. Outside Mexico, the charge receipt is your proof of payment. ## Commercial and tax documents Free includes **10 commercial invoices per calendar month (UTC)**, independent of its five quote sends; from Starter on they are unlimited. Tax-valid invoices start on Starter: **30, 200 and 500** per month on Starter, Professional and Scale, and **1,000** on Developer. Each type has its own allowance. In Mexico and Spain, the commercial option generates **pro forma** documents labeled as such; they do not replace a tax invoice. Integrated tax issuing (CFDI 4.0 in Mexico) requires Starter or higher and your issuer details configured; each payment complement Cord stamps also uses one tax invoice. In Spain, invoice registration with the AEAT (Verifactu, in beta) requires Starter and your electronic certificate uploaded. In Argentina, Brazil, Chile, Colombia, and Peru, when issuing through the tax authority is active on your account, the authorized invoice also requires Starter and uses the same tax-invoice allowance, and the commercial option becomes a pro forma. In the other markets, Cord issues commercial invoices without integration with the local tax authority. Creating drafts, downloading and resending do not consume another document. A successful issuance consumes one unit of its allowance; test documents do not. Reaching the limit does not disable downloads or payments of existing documents. ## Common problems **I don't see the button to change plans.** You need the Settings permission and to be outside the test environment. **I paid but still see Free.** Wait for the payment to be confirmed and reload the page. If the charge is pending, finish the payment from Billing. **The summary currency is not what I expected.** If you already have a contract, Cord keeps its currency. If this is your first subscription and it doesn't match your country, reload the page before paying and check the country in **Settings › General**. **I downgraded and a teammate can no longer work.** Your plan includes fewer users. Upgrade or, from Professional, add extra users. ## Related pages - [Team, permissions and security](/en/docs/cuenta/equipo-seguridad) - [Custom domain](/en/docs/cuenta/dominio-propio) - [Client portal](/en/docs/cuenta/portal-cliente) - [Invoicing by country](/en/docs/pagos/facturacion) - [All products and their minimum plan](/en/docs/productos) --- # API Keys URL: https://docs.cordhq.app/en/docs/desarrolladores/empezar/apikey Last updated: 2026-10-07 Manage the cryptographic keys that grant access to the platform. ## How Keys Work Every programmatic request to the Cord API requires an **API Key**. You can manage, revoke, and monitor their usage from the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) — the "Developers" pill in the bottom-right corner of the app, which appears once you turn on **Developer mode** in **Your account › Preferences**. For security, Cord's systems store your API Key as an irreversible Hash (`sha-256`). The plain text key (the string starting with `sk_...`, `rk_...` or `pk_...`) will only be shown to you **once** upon creation. If you lose it, there is no way to recover it; you must revoke it and generate a new one. ## Security Best Practices ### Do not commit secret keys to repositories Never commit (e.g., in Git) a key starting with `sk_live_`. If a public repository exposes your key, anyone can use it with the same permissions as your backend until you manually revoke it from the Workbench — Cord does not detect or suspend it for you. Use environment variables (like unversioned `.env` files) on your servers, and check the key's activity log if you suspect it leaked. ### Use the correct scope (Publishable vs Secret) - **Secret Keys (`sk_`):** Access the whole API, read-only or read and write depending on the scope you choose when creating them. They should only live on backend servers under your control. - **Restricted Keys (`rk_`):** Also server-side, but with a permission per resource (`none`, `read`, or `write`). See [restricted keys](/en/docs/desarrolladores/esenciales/autenticacion#restricted-keys). - **Publishable Keys (`pk_`):** Designed to be safely injected into web applications (frontend). Cord will automatically apply restrictions on what these keys can see or hide sensitive fields (such as the cost/margin of [products](/en/docs/desarrolladores/funciones/productos)) when receiving a request signed with them. ## Real-Time Activity The **Logs** tab of the Workbench is a live audit log of every key's usage: filter by method or status class, search by route, and select any request to see which IP, which key, and which flow (REST API or MCP) originated it. MCP calls show up with the tool that was invoked, for example `/mcp/tools/call:listar_productos`. --- # Quickstart URL: https://docs.cordhq.app/en/docs/desarrolladores/empezar/inicio-rapido Last updated: 2026-10-07 Create a test key, call /api/v1/me, create a client and a quote, send it and receive the webhook on your machine with the signature verified in Node. In this guide you create a test key, confirm which account it belongs to, add a client, build a quote for them, send it, and receive Cord's notifications on your `localhost` with the signature verified. Nothing you do here touches your real data: an `sk_test_` key works on your account's [test environment](/en/docs/desarrolladores/empezar/pruebas). Sending a test quote emails the client for real, with the subject marked as a test. Use your own email address in step 4. 1. **Create a test key.** In the app, turn on **Developer mode** in **Your account › Preferences** and open the **Developers** pill in the bottom-right corner. In the **API keys** tab, create a read and write **Secret Key** in **test mode** (if the app is already in test mode, the key is created as a test key). It starts with `sk_test_` and is shown only once: copy it. Store it in a terminal variable. The Cord CLI reads it from there too: ```bash export CORD_API_KEY="sk_test_..." ``` 2. **Check the key.** `GET /api/v1/me` returns the key's organization, permission and mode: ```bash curl https://cordhq.app/api/v1/me \ -H "Authorization: Bearer $CORD_API_KEY" ``` ```json { "data": { "org": { "id": "5b1f7d9e-3c2a-4e8b-9f61-0a7c4d2e8b13", "nombre": "Aceros del Norte", "plan": "pro" }, "scope": "write", "mode": "test" } } ``` If you see `"mode": "test"`, everything that follows happens in your test environment. A `401` with `code: "invalid_key"` means the key was copied wrong or was revoked. 3. **Listen for webhooks on your machine.** Cord can't call your `localhost`, so the [CLI](/en/docs/desarrolladores/herramientas/cli) opens a listening session and forwards each event to you with the real signature headers. First, the server that receives them. Install the SDK in an empty folder: ```bash npm init -y && npm install @flouviahq/node ``` Save this as `server.mjs`: ```js import { createServer } from 'node:http'; import { constructEvent, CordWebhookSignatureError } from '@flouviahq/node'; createServer(async (req, res) => { if (req.method !== 'POST' || req.url !== '/webhooks/cord') { res.writeHead(404).end(); return; } // The signature is computed over the RAW body: don't parse it before verifying. const chunks = []; for await (const chunk of req) chunks.push(chunk); try { const event = await constructEvent(Buffer.concat(chunks), req.headers, process.env.CORD_WEBHOOK_SECRET); console.log(event.event, event.id, event.data.id); res.writeHead(200).end('ok'); } catch (err) { if (err instanceof CordWebhookSignatureError) { console.error('Signature rejected:', err.code); res.writeHead(400).end(err.code); return; } throw err; } }).listen(3000, () => console.log('Listening on http://localhost:3000/webhooks/cord')); ``` In a second terminal (with the same `CORD_API_KEY`), open the listening session: ```bash npx @flouviahq/cli listen --forward-to http://localhost:3000/webhooks/cord ``` The CLI prints the session **secret** (`whsec_…`). Start your server with it in the first terminal: ```bash CORD_WEBHOOK_SECRET="whsec_..." node server.mjs ``` Leave both running. The session expires in 24 hours and Ctrl+C closes it. 4. **Create a client.** With an email address of yours: ```bash curl https://cordhq.app/api/v1/clientes \ -H "Authorization: Bearer $CORD_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "empresa": "Ferretería La Prueba", "contacto": "Ana Torres", "email": "your-email@example.com" }' ``` ```json { "data": { "id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90" } } ``` Your server prints the first event: ```text client.created evt_4c1e9a7b2d5f8e0a3b6c9d2e5f8a1b4c 0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90 ``` 5. **Create the quote.** Use the client's `id`. Without `tax_rate`, each line takes the default rate from your account's tax catalog; without `base_currency`, the quote uses your account's currency. ```bash curl https://cordhq.app/api/v1/cotizaciones \ -H "Authorization: Bearer $CORD_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 6a1d3f5e-8b2c-4e7a-9d0f-1c3e5a7b9d2f" \ -d '{ "cliente_id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90", "items": [ { "descripcion": "Window frame installation", "cantidad": 1, "precio_unitario": 12000 } ], "vigencia_dias": 15 }' ``` ```json { "data": { "id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10", "token": "3f9a1c2e7b4d6f8a0b1c2d3e4f5a6b7c", "folio": "COT-0001", "link_publico": "https://cordhq.app/q/3f9a1c2e7b4d6f8a0b1c2d3e4f5a6b7c", "needs_approval": false, "motivo": null } } ``` The quote starts as a draft and your server receives `quote.created`. The `Idempotency-Key` header makes retrying safe: with the same key and the same body, Cord returns this same response instead of creating a second quote. Generate a new key (for example with `uuidgen`) for each different quote. 6. **Send it.** Sending generates the link and emails the client: ```bash curl https://cordhq.app/api/v1/cotizaciones/8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 \ -H "Authorization: Bearer $CORD_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "action": "send" }' ``` ```json { "data": { "ok": true, "status": "sent", "email": { "sent": true } } } ``` If the client had no email, `email` would come back as `{ "sent": false, "skipped": "el cliente no tiene correo" }` and the quote would still be sent. Your server receives: ```text quote.sent evt_9d2a6c4e1f8b3a5d7c0e2f4a6b8d1c3e 8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 ``` 7. **Simulate the client.** Open the link from the email or trigger the view with a simulator. In another terminal: ```bash npx @flouviahq/cli simulate quote 8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 vista ``` `quote.viewed` arrives. To close the loop, approve it through the API (`{ "action": "approve" }`) and `quote.approved` arrives. ## What each notification contains Every delivery is a `POST` with this body. `id` is the **event's** identity (the same on every retry: deduplicate with it) and `data` is the quote summary: ```json { "id": "evt_9d2a6c4e1f8b3a5d7c0e2f4a6b8d1c3e", "event": "quote.sent", "created_at": "2026-10-07T17:04:12.318Z", "data": { "id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10", "folio": "COT-0001", "status": "sent", "moneda": "MXN", "total": 13920, "cliente": "Ferretería La Prueba", "cliente_id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90", "link_publico": "https://cordhq.app/q/3f9a1c2e7b4d6f8a0b1c2d3e4f5a6b7c" } } ``` The `total` in this example includes the 16% VAT of a Mexican account; yours will use your rates. Every amount travels with its `moneda` (currency). ## The same with the Node SDK ```js import { Cord } from '@flouviahq/node'; const cord = new Cord(process.env.CORD_API_KEY); const me = await cord.me(); const cliente = await cord.clients.create({ empresa: 'Ferretería La Prueba', email: 'your-email@example.com' }); const cotizacion = await cord.quotes.create({ cliente_id: cliente.id, items: [{ descripcion: 'Window frame installation', cantidad: 1, precio_unitario: 12000 }], }); await cord.quotes.send(cotizacion.id); console.log(me.mode, cotizacion.folio, cotizacion.link_publico); ``` The SDK sends an `Idempotency-Key` on every write and repeats it on its retries. See [Node SDK](/en/docs/desarrolladores/herramientas/sdks). ## Next steps - [Webhooks](/en/docs/desarrolladores/herramientas/webhooks): register a real endpoint, retries, secret rotation and manual signature verification. - [Events](/en/docs/desarrolladores/funciones/eventos): the 41 event types and the history API. - [Quotes API](/en/docs/desarrolladores/funciones/cotizaciones): approve, reject, mark as paid and delete. - [Error handling](/en/docs/desarrolladores/esenciales/errores): every code and when to retry. - Before going live, create an `sk_live_` key and register your endpoint in the Workbench: the `cord listen` secret only works for its session. --- # Test Environments URL: https://docs.cordhq.app/en/docs/desarrolladores/empezar/pruebas Last updated: 2026-10-07 Learn how to isolate your development using the Cord Sandbox. ## Why use Test Environments? When integrating financial APIs, it is critical to test your application's logic without generating real transactions or sending emails to real customers. Cord solves this by providing you with a completely isolated **Test Environment (Sandbox)**. Data created in test mode (quotes, clients, webhooks) never interacts with your live data. ## Identifying Test Mode 1. **In the Dashboard:** When Test Mode is active, you will see a visual orange indicator in the interface. All manual actions you perform will occur within the isolated environment. 2. **In the API:** Your secret API keys automatically determine which environment you are calling. A test key will interact with the Sandbox, while a live key will touch your real data. **Important:** Never use real keys in your unit or integration test suites. ## Quick Reset (Sandbox Reset) During integration development, you will often generate thousands of garbage records. Cord has a radical tool to return your environment to a clean slate: the Reset Endpoint. ### Clearing test environment data You can invoke a destructive cleanup (which will cascade delete clients, quotes, products, and events from the test environment) by making a POST to the following internal endpoint (requires an active browser session in Test Mode): ```bash POST /api/test-mode/reset ``` **Warning:** This endpoint contains strict database protections (`sandbox_of is not null`). Even if you call it by mistake in your live environment, the database will abort the transaction to protect your real data. It only works within Sandbox environments. ## Simulators (test helpers) With an `sk_test_` key you can trigger what a third party does in production: the SAT responding, time passing, or the client opening the link. Each simulator runs the same code as production, so webhooks, history and emails come out exactly as they would live. With a live key they respond `test_mode_only`, and the database rejects any simulation on a real organization. ### Force the next stamping result ```bash curl -X POST https://cordhq.app/api/v1/test_helpers/fiscal \ -H "Authorization: Bearer sk_test_..." -H "Content-Type: application/json" \ -d '{ "siguiente_resultado": "pac_caido" }' ``` Results: `exito`, `pac_caido` (the invoice stays as a draft and can be retried), `receptor_invalido`, `certificado_vencido` and `timbre_duplicado`. It is consumed by the next issuance; with none pending, the simulated issuance succeeds. ### Simulate the client and time ```bash curl -X POST https://cordhq.app/api/v1/test_helpers/cotizaciones/8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 \ -H "Authorization: Bearer sk_test_..." -H "Content-Type: application/json" \ -d '{ "accion": "vista" }' ``` `vista` records the client opening the quote (`quote.viewed`) and `vencer` expires it (`quote.expired`). Approve, reject and mark as paid are already in `POST /api/v1/cotizaciones/{id}`. ### Trigger a webhook ```bash curl -X POST https://cordhq.app/api/v1/test_helpers/webhooks \ -H "Authorization: Bearer sk_test_..." -H "Content-Type: application/json" \ -d '{ "evento": "quote.approved", "objeto_id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10" }' ``` Accepts any event in the catalog. With the `objeto_id` of a test quote or invoice it uses its real data; without it, sample data with `test_…` ids. The `objeto_id` must match the event type: a quote for `quote.*`, `payment.*`, `invoice.stamped` and `invoice.issued`, and an invoice for the other `invoice.*` events. Client, product, task, promise, dispute, refund, payout and account events always use sample data. Delivery goes through the real outbox: signature, retries and history in the endpoint's deliveries, in the **Webhooks** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). With `objeto_id` the event also lands in the event history and the **Events** tab; with sample data it doesn't, because it isn't an event of your business. --- # Cord Developers URL: https://docs.cordhq.app/en/docs/desarrolladores/empezar/resumen Last updated: 2026-10-07 Integrate Cord with your systems: v1 REST API, signed webhooks, Node SDK, CLI, MCP server, OAuth and Cord Elements. Full index of the developer documentation. Cord's API is resource-oriented, responds with JSON and standard HTTP status codes, and is available on every plan. Every response carries a `Cord-Request-Id`, every write accepts `Idempotency-Key`, and every key is pinned to an API version. Start with the [Quickstart](/en/docs/desarrolladores/empezar/inicio-rapido): in five minutes you create a quote and receive its webhook on your machine. ## What you can build - **Sync your ERP or CRM:** keep your catalog and clients up to date with the [Products API](/en/docs/desarrolladores/funciones/productos) and the [Clients API](/en/docs/desarrolladores/funciones/clientes). - **React to events:** mark an order as paid when `quote.paid` arrives by [webhook](/en/docs/desarrolladores/herramientas/webhooks), or reconcile with the [event history](/en/docs/desarrolladores/funciones/eventos). - **Invoice from your system:** create, issue and collect invoices with the [Invoices API](/en/docs/desarrolladores/funciones/facturas). - **Connect AI agents:** give Claude or ChatGPT access to your data with the [MCP server](/en/docs/desarrolladores/herramientas/mcp), or let them propose an account's setup with [assisted setup](/en/docs/desarrolladores/herramientas/configuracion-asistida). - **Embed the close in your product:** quote, invoice and tax form with [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen). - **Ship an app for many businesses:** connect it with [OAuth](/en/docs/desarrolladores/herramientas/oauth) instead of asking for keys. ## SDKs and tools | Tool | Install | What for | |---|---|---| | [v1 REST API](/en/docs/desarrolladores/referencia) | — | `https://cordhq.app/api/v1`, with any HTTP client. | | [Node SDK](/en/docs/desarrolladores/herramientas/sdks) | `npm install @flouviahq/node` | The full API from your server, with retries, idempotency and webhook verification. Node, Bun, Deno and edge. | | [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen) | `npm install @flouviahq/elements` | Quote, invoice and tax form in the browser: React, Vue, Web Components and headless. | | [CLI](/en/docs/desarrolladores/herramientas/cli) | `npx @flouviahq/cli` | Browser sign-in, AI setup, project integration and webhooks on your `localhost`. | | [MCP server](/en/docs/desarrolladores/herramientas/mcp) | — | Tools for AI agents over your data. | | [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) | — | Keys, endpoints, events and the log of every request, inside the app. | | Python and PHP | — | **Not published yet.** Use the REST API directly. | ## Specification and machine-readable resources | Resource | Address | |---|---| | OpenAPI 3.1 (JSON) | [`https://cordhq.app/openapi.json`](https://cordhq.app/openapi.json) | | OpenAPI 3.1 (YAML) | [`https://cordhq.app/openapi.yaml`](https://cordhq.app/openapi.yaml) | | Summary for AI assistants | [`https://cordhq.app/llms.txt`](https://cordhq.app/llms.txt) | | All the documentation in one file | [`https://cordhq.app/llms-full.txt`](https://cordhq.app/llms-full.txt) | | Browsable reference | [API Reference](/en/docs/desarrolladores/referencia) | ## Test environments Every account has an isolated test environment: what you create with an `sk_test_` key or with the app's test mode doesn't touch your real data. With a test key you get simulators to trigger stamping, expirations and webhooks, and `cord listen` to receive them on your machine. The exception is [assisted setup](/en/docs/desarrolladores/herramientas/configuracion-asistida) proposals, which always go to your real account and are only applied if a person approves them. See [Test environments](/en/docs/desarrolladores/empezar/pruebas). ## All pages **Get started** - [Create your API Key](/en/docs/desarrolladores/empezar/apikey) - [Quickstart](/en/docs/desarrolladores/empezar/inicio-rapido) - [Test environments](/en/docs/desarrolladores/empezar/pruebas) **Tools** - [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) - [Webhooks](/en/docs/desarrolladores/herramientas/webhooks) - [CLI](/en/docs/desarrolladores/herramientas/cli) - [Node SDK](/en/docs/desarrolladores/herramientas/sdks) - [MCP Server](/en/docs/desarrolladores/herramientas/mcp) - [Assisted setup](/en/docs/desarrolladores/herramientas/configuracion-asistida) - [OAuth for apps](/en/docs/desarrolladores/herramientas/oauth) - [Integrations](/en/docs/desarrolladores/herramientas/integraciones) **Cord Elements** - [Overview](/en/docs/desarrolladores/herramientas/elements/resumen) - [React and Next.js](/en/docs/desarrolladores/herramientas/elements/react) - [Web Components and Vue](/en/docs/desarrolladores/herramientas/elements/web-components) - [Headless](/en/docs/desarrolladores/herramientas/elements/headless) - [Tax form](/en/docs/desarrolladores/herramientas/elements/fiscal) - [Server proxy](/en/docs/desarrolladores/herramientas/elements/server) - [Appearance](/en/docs/desarrolladores/herramientas/elements/apariencia) - [Events](/en/docs/desarrolladores/herramientas/elements/eventos) - [CSP Security](/en/docs/desarrolladores/herramientas/elements/seguridad) **Essentials** - [Authentication](/en/docs/desarrolladores/esenciales/autenticacion) - [Pagination](/en/docs/desarrolladores/esenciales/paginacion) - [Error handling](/en/docs/desarrolladores/esenciales/errores) - [API Versions](/en/docs/desarrolladores/esenciales/versiones) - [Security](/en/docs/desarrolladores/esenciales/seguridad) - [API Reference](/en/docs/desarrolladores/referencia) **Features** - [Quotes API](/en/docs/desarrolladores/funciones/cotizaciones) - [Clients API](/en/docs/desarrolladores/funciones/clientes) - [Products API](/en/docs/desarrolladores/funciones/productos) - [Collections API](/en/docs/desarrolladores/funciones/cobranza) - [Invoices API](/en/docs/desarrolladores/funciones/facturas) - [Tasks API](/en/docs/desarrolladores/funciones/tareas) - [Events API](/en/docs/desarrolladores/funciones/eventos) **Security & Privacy** - [SSO & SAML](/en/docs/desarrolladores/seguridad/sso) --- # Authentication URL: https://docs.cordhq.app/en/docs/desarrolladores/esenciales/autenticacion Last updated: 2026-10-07 How to authenticate your requests to the Cord API using Bearer Tokens. ## Bearer Tokens The Cord API uses Bearer Tokens to authenticate incoming requests. You must send the API Key you generated in the dashboard as an HTTP `Authorization` header. All requests must be made over HTTPS. Requests without authentication or sent via plain HTTP will fail. **Request Example:** ```bash curl -X GET "https://cordhq.app/api/v1/cotizaciones" \ -H "Authorization: Bearer sk_live_tU..." ``` ## Secret vs Publishable Keys Cord has three kinds of key: 1. **Secret (`sk_`):** only on your servers. Read-only or read and write across the whole API. 2. **Restricted (`rk_`):** only on your servers, with a permission per resource (`none`, `read` or `write`). Use them to give a third-party integration exactly what it needs. See [restricted keys](#restricted-keys). 3. **Publishable (`pk_`):** for the browser, with a fixed list of routes. ### Automatic Data Masking Publishable keys have automatic security restrictions imposed by the API. For example, if you query the [Products API](/en/docs/desarrolladores/funciones/productos) using a publishable key, the Cord server will automatically omit the `costo` (margin) field to ensure your website visitors cannot discover your profit margins. A Publishable Key can also only be used on four routes: `GET /api/v1/productos`, `POST /api/v1/cotizaciones`, `GET /api/v1/elements/config` and `POST /api/v1/elements/ai-draft`. Any other responds `403 insufficient_scope`. The request must also send an `Origin` or `Referer` header matching your organization's allowed domains, configured in **Settings › Embeddable quote builder**. A `pk_live_` key with no domains configured responds `403 origin_allowlist_required`; a `pk_test_` key is accepted from any origin. **Caution:** **Never expose your Secret Keys.** If your secret key is compromised, you must immediately revoke it from the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). ## Restricted keys An `rk_` key carries a level per resource. Cord derives the resource from the route, so a new API route starts out forbidden for existing restricted keys until you grant it. | Resource | Routes | |---|---| | `cotizaciones` | `/api/v1/cotizaciones/*` | | `clientes` | `/api/v1/clientes/*` | | `productos` | `/api/v1/productos/*` | | `facturas` | `/api/v1/facturas/*` | | `cobranza` | `/api/v1/cobranza` | | `tareas` | `/api/v1/tareas` | | `eventos` | `/api/v1/events` | | `webhooks` | `/api/v1/webhooks/*` | | `elements` | `/api/v1/elements/*` | | `test_helpers` | `/api/v1/test_helpers/*` | | `setup` | `/api/v1/setup/*` | `read` allows `GET`; `write` also allows creating, editing and actions. `GET /api/v1/me` answers to any secret or restricted key. On the MCP server, a restricted key applies the same per-resource level to each tool (see [permissions per tool](/en/docs/desarrolladores/herramientas/mcp#permissions-per-tool)). Without permission the response is `403 insufficient_permissions` and names the resource. ## Allowed IPs You can pin up to 20 IPs or CIDR ranges (IPv4 or IPv6) on an `sk_` or `rk_` key. Cord checks the source IP recorded by its delivery network, not a header the client can write, so `X-Forwarded-For` can't bypass the list. A request from another IP responds `403 ip_not_allowed` and is recorded in your organization's audit log, once per hour per IP. Publishable Keys are limited by domain in **Settings › Embeddable quote builder**, not by IP. ## Expiration and rolling When you create a key you can make it expire in 7, 30, 90 or 365 days; after that it responds `401 key_expired`. **Rolling** creates a new key with the same permissions, IPs and API version, and keeps the old one alive for the time you choose (immediately, 1 hour, 24 hours or 7 days) while you update your systems. The key in its grace period no longer counts against your plan's limit. Creating, editing, rolling and revoking keys is recorded in the audit log with who did it and from which IP. ## Keys included per plan Each plan includes a maximum number of active keys: 2 on Free, 5 on Starter, 20 on Professional, 50 on Scale and 200 on Developer. Secret, restricted and publishable keys that aren't revoked, expired or in a rolling grace period count; connections authorized through OAuth (Zapier, Make) don't. Once you reach the cap, the Workbench won't let you create another until you revoke one. If your organization ends up with more active keys than its plan includes (for example, after a downgrade), the oldest ones keep working and the ones over the allowance respond `402 subscription_key_limit` until you revoke keys or upgrade. ## Quick Identity Check If you need to test if your API key is working correctly and which account it belongs to, you can use the `me` endpoint: ```bash curl -X GET "https://cordhq.app/api/v1/me" \ -H "Authorization: Bearer sk_live_tU..." ``` --- # Error Handling URL: https://docs.cordhq.app/en/docs/desarrolladores/esenciales/errores Last updated: 2026-10-07 Understand the status codes and error responses of the Cord API. ## HTTP Status Codes The Cord API always returns standard HTTP status codes. As a general rule: - **`2xx`** indicates success. - **`4xx`** indicates an error originating from the provided information (e.g., missing parameters, invalid token). - **`5xx`** indicates an error on Cord's servers (these are very rare). ### Code Summary | Code | Description | |---|---| | **200 OK** | Everything worked as expected. | | **400 Bad Request** | The request was unacceptable. Usually means `invalid_request` (missing fields) or `invalid_json`; also `invalid_cursor` or `invalid_api_version`. | | **401 Unauthorized** | Your API Key is missing, incorrect, or was revoked. | | **402 Payment Required** | The operation requires a higher plan (`subscription_required`), exceeds a limit on your current plan (`plan_limit_reached`, e.g. number of clients or products), or the key exceeds the number of keys your plan includes (`subscription_key_limit`). | | **403 Forbidden** | You have insufficient permissions (e.g., trying to write with a read-only key, or a Publishable Key attempting an action outside its scope). | | **404 Not Found** | The resource (quote, client, invoice) does not exist. | | **409 Conflict** | An invalid state transition for the resource (`invalid_state`) — for example, approving a quote that is still a draft, or trying to delete test data (`/api/test-mode/reset`) without being in a Sandbox organization. Also returned while another request with the same `Idempotency-Key` is still running (`idempotency_in_progress`), or when a stamped invoice needs a credit note instead of being voided (`credit_note_required`). | | **413 Payload Too Large** | The body exceeds 1 MB (`payload_too_large`); on `POST /api/v1/elements/ai-draft`, the file exceeds 4 MB, and on `POST /api/v1/setup/plans`, the file exceeds 3 MB. | | **415 Unsupported Media Type** | The body wasn't sent as `application/json` (`unsupported_media_type`). | | **422 Unprocessable Entity** | You reused an `Idempotency-Key` with a different request (`idempotency_key_reused`), or the AI found no products in the text (`no_items`). | | **429 Too Many Requests** | You exceeded a requests-per-minute limit (`rate_limited`, see [Rate limits](#rate-limits)), your plan's monthly API quota (`api_quota_exceeded`), or its AI quota (`ai_quota_exceeded`). Respect the `Retry-After` header. | | **502 Bad Gateway** | An external provider rejected or didn't complete the operation: the tax provider when issuing (`provider_error`) or sending an email (`send_failed`). | | **503 Service Unavailable** | A dependency the operation needs didn't respond — for example, an exchange rate could not be obtained (`fx_unavailable`) or the tax catalog (`tax_catalog_unavailable`), or your subscription couldn't be verified (`subscription_verification_unavailable`). Cord never invents a rate: if it can't prove one, the operation fails closed. Retry later. | ## Error Object Structure When a `4xx` or `5xx` error occurs, Cord always responds with a **flat** (not nested) JSON object with two fields: `error` (a human-readable message you can show or log) and `code` (a stable string for your handling logic). Some errors add extra fields depending on the case (see examples below). **Error Response Example:** ```json { "error": "The company name is required", "code": "invalid_request" } ``` **Example with extra fields (plan limit, 402):** ```json { "error": "Your plan allows 50 clients. Free up space or upgrade your plan to continue.", "code": "plan_limit_reached", "resource": "clients", "limit": 50, "plan": "starter" } ``` Don't rely on the nested `error.code` / `error.message` shape to parse the response: `error` is always the message string, and `code` is a sibling field at the same level, not a property of `error`. Every `/api/v1` response carries the `Cord-Request-Id` header (`req_…`). On an error, the body repeats it as `request_id` and adds `doc_url`, a link to that code's explanation on this page. Include the `request_id` when you contact support: it lets us find your exact request. ```json { "error": "API key inválida o revocada.", "code": "invalid_key", "request_id": "req_3f9c2a1b7d4e6f8a0b1c2d3e", "doc_url": "https://docs.cordhq.app/docs/desarrolladores/esenciales/errores#invalid_key" } ``` ### Common Error Codes (`code`) - `invalid_json`: Your `POST` request body is not valid JSON, or `Content-Type: application/json` wasn't sent. - `invalid_request`: A business validation failed (missing field, discount out of range, a quote without a valid client). The `error` field explains the exact reason. - `invalid_fiscal_data` (400): The tax details in `cliente.fiscal` fail the country's validation. The response includes `issues`, a list of `{ field, code }`. See [Tax form](/en/docs/desarrolladores/herramientas/elements/fiscal#validation-codes). - `missing_key` / `invalid_key`: The `Authorization: Bearer` header is missing, or the key doesn't exist / was revoked. - `token_expired`: The credential of an authorized connection (Zapier, Make) expired. The app renews it on its own with its refresh token. - `insufficient_scope`: Your key doesn't have the required scope (a read-only key tried to write, or a Publishable Key tried a route outside its allowed list). - `insufficient_permissions` (403): A restricted key (`rk_`) has no permission for that route's resource, or was used with MCP. The `error` field names the resource. - `ip_not_allowed` (403): The key has allowed IPs and the request came from another one. The `error` field includes the IP Cord saw. - `key_expired` (401): The key expired, or it was rolled and its grace period ended. Use the new key or create another. - `not_found`: The requested resource doesn't exist in your organization. - `subscription_required`: The capability requires a higher plan. The response includes `plan` (your current one) and `plan_required`. - `plan_limit_reached`: You hit a hard limit on your plan (clients, products, or active quotes). The response includes `resource`, `limit`, and `plan`. - `integration_limit_reached` (403): your integrations already created the 100 webhook subscriptions allowed per organization. Delete the ones you no longer use. - `rate_limited` / `api_quota_exceeded`: Requests-per-minute or monthly API quota limit. Retry while respecting `Retry-After`. - `fx_unavailable` / `tax_catalog_unavailable`: A third-party data point (exchange rate or tax catalog) could not be obtained with certainty. The operation did not complete — don't assume it did. - `subscription_key_limit` (402): Your organization has more active keys than its plan includes (for example, after a downgrade) and this key falls outside the allowance; the oldest ones keep working. Revoke keys you no longer use or upgrade. The allowance counts active secret, restricted, and publishable keys, excluding connections authorized through OAuth: 2 on Free, 5 on Starter, 20 on Professional, 50 on Scale, and 200 on Developer. - `subscription_verification_unavailable` (503): Cord couldn't verify your subscription or record the call's usage. The operation didn't run; retry. - `invalid_api_version` (400): The `Cord-Version` header asks for a version that doesn't exist. The message lists the available ones. See [API Versions](/en/docs/desarrolladores/esenciales/versiones). - `invalid_cursor` (400): The `cursor` isn't valid. Use the previous response's `next_cursor` exactly as it came. - `payload_too_large` (413): The JSON body exceeds 1 MB, or the file sent to `POST /api/v1/elements/ai-draft` exceeds 4 MB. - `unsupported_media_type` (415): The body isn't sent as `application/json` (or as `multipart/form-data` on `POST /api/v1/elements/ai-draft`). - `test_mode_only` (403): The `/api/v1/test_helpers` simulators only work with an `sk_test_` key and against the test environment. - `credit_note_required` (409): The invoice is already stamped and can't be voided directly. Issue a credit note with `action: "credit_note"`. - `provider_error` (502): The tax provider rejected or didn't complete issuing. The `error` field explains why. - `send_failed` (502): The invoice email couldn't be sent. Retry sending. - `ai_quota_exceeded` (429) / `no_items` (422) / `ai_unavailable` (502 or 503) / `missing_text` / `text_too_long` (400): Errors from the AI routes (`POST /api/v1/cotizaciones/ia` and `POST /api/v1/elements/ai-draft`): your plan's AI allowance ran out, the text had no products, AI isn't available or couldn't process the request, or the text is missing or over the maximum. On `ai-draft` these codes arrive as an `error` event inside the stream. - `invalid_state`: The resource is not in a status that allows the operation, or it changed while we were processing it. Nothing was applied. - `invalid_url`: A webhook URL is not `https://` or points to an internal host. - `invalid_idempotency_key` / `idempotency_key_reused` / `idempotency_in_progress` / `idempotency_unavailable`: See the next section. - `secret_key_in_browser` (403): A Secret Key arrived from a browser. It is already exposed in the page source: revoke it in the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) and call the API only from your server. - `missing_origin` / `unauthorized_origin` / `invalid_origin` (403): A Publishable Key arrived without `Origin`, or from a domain that is not in your organization's allowed domains (Settings › Embeddable quote builder). - `origin_allowlist_required` (403): A live Publishable Key only works once allowed domains are set in **Settings › Embeddable quote builder**. `pk_test_` keys work from any origin. ## Rate limits Cord applies these limits per one-minute window unless stated otherwise. When you exceed one it responds `429` with `code: "rate_limited"`, generally with the `Retry-After` header in seconds. Those marked strict don't let requests through when Cord can't count them: on `/api/v1/cotizaciones/{id}` and `/api/v1/elements/ai-draft` they then respond `503` with `error: "access_temporarily_unavailable"`. | Limit | Scope | Applies to | |---|---|---| | 120 per minute | Per source IP | Every request to `/api/v1` and to the MCP server, with any key, before the key is validated. | | 600 per minute | Per secret key (`sk_`, `rk_`, or OAuth connection) | Every request to `/api/v1` and to the MCP server. | | 120 per minute | Per publishable key (`pk_`) | The four routes a `pk_` accepts. | | 120 per minute (strict) | Per organization | `POST` and `DELETE` on `/api/v1/cotizaciones/{id}` and the MCP tools that change a quote's state. | | 20 per minute | Per key | `POST /api/v1/webhooks`. | | 20 per minute | Per organization | `POST /api/v1/cotizaciones/ia`. | | 6 per minute per IP, 60 per minute and 500 per day per organization (strict) | IP and organization | `POST /api/v1/elements/ai-draft`. | | 6 per day (strict) | Per organization | `POST /api/v1/setup/plans` and `proponer_configuracion` in MCP. | Because the per-IP limit is lower than a secret key's, a server that sends everything from a single IP hits 120 per minute first. Apart from these limits, live keys consume your plan's monthly API quota (`api_quota_exceeded`). ## Safe retries with `Idempotency-Key` If a request that creates or changes something (`POST`, `PATCH`, `DELETE`) is cut off by the network or a timeout, you do not know whether Cord applied it. Send the `Idempotency-Key` header with a unique value per operation (for example, a UUID you generate) and retry with **the same key and the same body**: ```bash curl -X POST "https://cordhq.app/api/v1/clientes" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 5d9c2b7e-6f1a-4c3d-9e8b-2a1f0c7d6e5b" \ -d '{ "empresa": "ACME Corp" }' ``` - **Retry with the same key and body:** Cord returns the original response without running the operation again or counting it against your quota. The repeated response includes the `Idempotent-Replayed: true` header. - **Same key with a different body, method, or route:** `422 idempotency_key_reused`. Use a new key for each different operation. - **The first request has not finished:** `409 idempotency_in_progress`. Wait and retry. - **`5xx` and `429` errors:** are not stored, so you can retry with the same key. - The key is scoped to your API key, accepts 1 to 255 visible characters (`invalid_idempotency_key` otherwise), and expires after **24 hours**. - If Cord cannot reserve the key, it returns `503 idempotency_unavailable` **without running** the operation. The header is optional: without it, every request runs as it arrives. --- # Pagination URL: https://docs.cordhq.app/en/docs/desarrolladores/esenciales/paginacion Last updated: 2026-10-07 Which Cord API lists paginate by cursor and which by offset, the shape of meta on each, complete loops in curl and Node, and the invalid_cursor error. ## What paginates how | Endpoint | Cursor | Offset | Order | `meta` | |---|---|---|---|---| | `GET /api/v1/cotizaciones` | Yes | Yes | Newest first | `limit`, `offset`, `total`, `next_cursor` | | `GET /api/v1/clientes` | Yes | Yes | By `empresa` (A to Z) | `limit`, `offset`, `total`, `next_cursor` | | `GET /api/v1/productos` | Yes | Yes | Active first, then by `nombre` | `limit`, `offset`, `total`, `next_cursor` | | `GET /api/v1/facturas` | Yes | No | Newest first | `next_cursor` | | `GET /api/v1/events` | Yes | No | Newest first | `next_cursor` | | `GET /api/v1/webhooks` | No | No | Newest first | No `meta`: returns all of the key's endpoints. | | `GET /api/v1/cobranza` | No | No | — | No `meta`: returns the full receivables portfolio. | On every paginated list, `limit` goes from 1 to 200 and defaults to 50. ## Use the cursor Request the first page without a cursor. If `meta.next_cursor` has a value, repeat the same request, with the same filters, adding `cursor=`. When it comes back `null`, there's nothing left. ```bash curl "https://cordhq.app/api/v1/clientes?limit=2" \ -H "Authorization: Bearer sk_test_..." ``` ```json { "data": [ { "id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90", "empresa": "Aceros Monterrey", "email": "compras@acerosmty.mx" }, { "id": "7a2d4c19-5e8b-4f3a-a1d6-9c0e2b4f6d81", "empresa": "Bodega Central", "email": "" } ], "meta": { "limit": 2, "offset": 0, "total": 142, "next_cursor": "WyJCb2RlZ2EgQ2VudHJhbCIsIjdhMmQ0YzE5LTVlOGItNGYzYS1hMWQ2LTljMGUyYjRmNmQ4MSJd" } } ``` ```bash curl "https://cordhq.app/api/v1/clientes?limit=2&cursor=WyJCb2RlZ2EgQ2VudHJhbCIsIjdhMmQ0YzE5LTVlOGItNGYzYS1hMWQ2LTljMGUyYjRmNmQ4MSJd" \ -H "Authorization: Bearer sk_test_..." ``` The example trims each client to three fields; the real response has the full object. The cursor is an **opaque token**: don't interpret it, don't build it and don't keep it for another list. Send it back as is, URL-encoded (the examples below do that for you). With `cursor`, `offset` is ignored and `meta.offset` comes back `null`. ## Why cursor and not offset With `offset`, a quote created while you walk the list shifts everything by one position: the next page repeats a record, and if one is deleted, you skip another without noticing. The cursor points at the last row you saw, so the next page starts exactly after it, whether or not there were writes. `offset` still works on quotes, clients and products for compatibility. `meta.total` counts every record matching the filter: it's for showing "142 clients", not for deciding when to stop. Use `next_cursor` for that. ## Walk a complete list ```bash #!/usr/bin/env bash # Requires jq. Prints the id and company of every client. set -euo pipefail args=(-sSG "https://cordhq.app/api/v1/clientes" -d limit=200 -H "Authorization: Bearer $CORD_API_KEY") cursor="" while :; do if [ -n "$cursor" ]; then page=$(curl "${args[@]}" --data-urlencode "cursor=$cursor") else page=$(curl "${args[@]}") fi echo "$page" | jq -r '.data[] | [.id, .empresa] | @tsv' cursor=$(echo "$page" | jq -r '.meta.next_cursor // empty') [ -z "$cursor" ] && break done ``` ```js import { Cord } from '@flouviahq/node'; const cord = new Cord(process.env.CORD_API_KEY); // listAll() requests pages of 200 and follows next_cursor for you. for await (const cliente of cord.clients.listAll()) { console.log(cliente.id, cliente.empresa); } // With filters: for await (const factura of cord.invoices.listAll({ estado: 'open' })) { console.log(factura.numero, factura.saldo, factura.moneda); } ``` ```js const base = 'https://cordhq.app/api/v1/events'; let cursor = null; do { const url = new URL(base); url.searchParams.set('limit', '200'); url.searchParams.set('type', 'quote.paid'); if (cursor) url.searchParams.set('cursor', cursor); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.CORD_API_KEY}` } }); if (!res.ok) throw new Error(`${res.status} ${(await res.json()).code}`); const page = await res.json(); for (const event of page.data) console.log(event.created_at, event.type, event.object_id); cursor = page.meta.next_cursor; } while (cursor); ``` `listAll()` exists on `quotes`, `clients`, `products`, `invoices` and `events`, and always paginates by cursor since version 1.1.0 of the SDK. See [Node SDK](/en/docs/desarrolladores/herramientas/sdks#lists-and-automatic-pagination). ## Errors | Situation | Response | |---|---| | A `cursor` that isn't from quotes, clients or products | `400`, `code: "invalid_cursor"`, `error: "El cursor no es válido. Usa el next_cursor de la respuesta anterior."` | | A `cursor` that isn't from events | `400`, `code: "invalid_request"`, `error: "cursor inválido"` | | `limit` out of range | Not an error: it's clamped to 1 or 200. | ```json { "error": "El cursor no es válido. Usa el next_cursor de la respuesta anterior.", "code": "invalid_cursor", "request_id": "req_5d2b8f1a4c7e0b3d6a9f2c5e", "doc_url": "https://docs.cordhq.app/docs/desarrolladores/esenciales/errores#invalid_cursor" } ``` A cursor doesn't carry across lists or filters: if you change `status`, `type` or any other filter, start again without a cursor. --- # Security URL: https://docs.cordhq.app/en/docs/desarrolladores/esenciales/seguridad Last updated: 2026-10-11 How Cord protects your organization's data: encryption, identity, isolation, API, webhooks, payments, payout identity and retention. This page describes controls that exist in the product today. If your team needs something that isn't here, write to us. ## Data in transit and at rest - All traffic goes over HTTPS. Cord sends `Strict-Transport-Security` with `includeSubDomains` and `preload`, a content security policy and `X-Content-Type-Options: nosniff`. - The secrets Cord stores on your behalf (integration credentials, webhook signing secrets) are encrypted with AES-256-GCM before they reach the database. The encryption key can be rotated without losing what was encrypted with the previous one. - Passwords are stored with Argon2id. Session tokens and API keys are stored only as hashes: someone reading the database would not get a usable credential. ## Where the data lives and who stamps invoices - **Database:** PostgreSQL on Neon, AWS region `us-east-1` (Virginia, United States). - **Compute:** functions run on Vercel, region `iad1` (Washington D.C., United States). - **Invoicing in Mexico:** CFDI 4.0 stamping is done by Facturapi as the PAC, with each business's CSD. Cord cancels CFDIs with their SAT reason and issues credit sales with the PPD method. For each MXN payment on a PPD invoice, Cord automatically stamps its payment receipt complement (type P CFDI), idempotent per payment. - **Invoicing in Spain:** Cord generates the chained Verifactu records and submits them to the AEAT, separately from issuing, with each business's certificate (in beta). Without a certificate, the invoice is issued as a pro forma. - **Certifications:** Cord has no SOC 2 or ISO 27001 today. See [security audits](https://cordhq.app/en/support/auditorias-seguridad). ## Identity and access - Sign-in with password, Google or passkeys, and SAML SSO for teams. Apple is coming soon. - A new password has at least 10 characters, does not contain the account email and does not appear in public data breaches. That check uses k-anonymity: only the first 5 characters of the password's SHA-1 hash leave Cord and the comparison happens in Cord, so the password never travels. - Two-step verification (TOTP). The organization can require it for the whole team and set a maximum idle time. - Sensitive actions (changing the payout account or payout identity details) require signing in again. - Roles per team member, and allowed domains for invitations. ## Isolation between organizations Every query on an organization's data runs in a context that declares which organization it works for, and an automated check in CI blocks adding a query outside that context. Public links (quote, invoice, mobile capture) resolve the organization with a token and then query inside that same context: the token never grants access on its own. ## API - Keys are shown once and stored as hashes. - Three kinds: secret, [restricted per resource](/en/docs/desarrolladores/esenciales/autenticacion#restricted-keys) and publishable. Secret and restricted keys accept a list of allowed IPs, can expire and are rolled with a grace period. - A Secret Key arriving from a browser is rejected. Publishable keys can only use a fixed list of routes and, in live mode, only from the domains you registered. - Rate limits per key and per IP, and `Idempotency-Key` to retry without duplicates. ## Webhooks - Every event is signed with HMAC-SHA256 over the body and a timestamp (`X-Cord-Signature-V1`), so your server can reject altered or replayed events. The SDKs check the signature and its age for you. - Cord only delivers to `https://` URLs on public hosts, never to internal addresses. ## Embedded quote (Cord Elements) - The quote lives in a Cord iframe with its own origin: your page can't read or modify it, and Cord can't read your page. - Only the domains you register can frame it. With no registered domains it renders read-only, without approve, sign or pay, and without sending data to the host page. - Custom styles go through a validator with closed lists: it accepts no external URLs and no rules that hide or cover content. ## Payments Card details are captured by the payment processor's form on its own domain. Cord never receives or stores the card number. ## Identity verification for payouts - ID photos are checked on the device before they are sent, and their metadata (including GPS location) is removed, keeping only the orientation. - The link to take the photo from a phone is bound to the first device that uses it, has an attempt cap and is never recorded in analytics. ## Audit log Creating, editing, rolling and revoking keys, organization security changes, payments and other sensitive actions are recorded with who, when, the IP and the browser. Admins review it in **Settings › Advanced › Audit log**. ## Retention | Data | How long it is kept | |---|---| | Webhook delivery history | 30 days (failed ones, 90) | | Identity capture sessions from a phone | Deleted one hour after they close | | Identity verification evidence for payouts | 5 years from submission | You can export your organization's data from Settings and delete your account at any time. ## Report a vulnerability Write to `security@flouvia.com`. Scope, commitments and safe harbor in [Report vulnerabilities](https://cordhq.app/en/support/reportar-vulnerabilidades); the contact is also in [`/.well-known/security.txt`](https://cordhq.app/.well-known/security.txt). --- # API Versions URL: https://docs.cordhq.app/en/docs/desarrolladores/esenciales/versiones Last updated: 2026-10-07 Cord's current API version, how it's pinned per key, per webhook endpoint and per request with Cord-Version, what changes without a new version, and the invalid_api_version error. ## Current version The current version is **`2026-10-01`**. It's also the only one: the baseline that fixed the shape of the API when Cord started versioning it. Each version is named after the date it's published. | Version | Changes | |---|---| | `2026-10-01` | Baseline: the shape of the API when versioning was introduced. | ## How a request's version is chosen Cord resolves the version of each request to `/api/v1` in this order: 1. **The `Cord-Version` header** on the request, if you send it. 2. **The key's pinned version.** Every key is pinned to the version that's current on the day it's created. Rotating a key keeps the previous key's version. 3. **The baseline version** (`2026-10-01`), for keys created before versioning existed. Cord produces every response in its newest shape and converts it, change by change, to the resolved version. Every response carries the `Cord-Version` header with the version it was answered in. ```bash curl -i https://cordhq.app/api/v1/me \ -H "Authorization: Bearer sk_test_..." \ -H "Cord-Version: 2026-10-01" ``` ```text HTTP/2 200 content-type: application/json cord-request-id: req_3f9c2a1b7d4e6f8a0b1c2d3e cord-version: 2026-10-01 ``` There's currently no way to change the pinned version of an existing key. To move to a new version, send the `Cord-Version` header on your requests or create a new key. ## In the SDKs and the CLI The official clients always send the version they were built with, so a Cord update doesn't change what they read: | Client | Version it sends | How to change it | |---|---|---| | `@flouviahq/node` | `CORD_API_VERSION` (`2026-10-01`) | `new Cord(sk, { apiVersion: '2026-10-01' })` | | `@flouviahq/elements` | `CORD_API_VERSION` (`2026-10-01`) | Updates with the package. | | `@flouviahq/cli` | `2026-10-01` | Updates with the package. | ```ts import { Cord, CORD_API_VERSION } from '@flouviahq/node'; const cord = new Cord(process.env.CORD_SECRET_KEY!, { apiVersion: CORD_API_VERSION }); ``` ## Webhooks Every webhook endpoint is pinned to the version that's current on the day it's created, whether from the Workbench, through `POST /api/v1/webhooks` or with a `cord listen` session. Each delivery's `data` is converted to **that endpoint's** version, not to the version of the key that triggered the event. If you have two endpoints on different versions, both receive the same event, with the same `id`, each in its own shape. Deliveries don't carry the `Cord-Version` header, and there's no header to request another version per delivery: to receive a different shape, create a new endpoint. ## Invalid version A version that doesn't exist returns `400` with `code: "invalid_api_version"`. Cord never silently falls back to another version. The message lists the available versions: ```bash curl https://cordhq.app/api/v1/me \ -H "Authorization: Bearer sk_test_..." \ -H "Cord-Version: 2025-01-01" ``` ```json { "error": "Cord-Version \"2025-01-01\" no existe. Versiones disponibles: 2026-10-01.", "code": "invalid_api_version", "request_id": "req_8a1c4e7b2d9f3a6c0e5b8d1f", "doc_url": "https://docs.cordhq.app/docs/desarrolladores/esenciales/errores#invalid_api_version" } ``` The format matters too: `Cord-Version: 2026-10` or `latest` return the same error. ## Change policy **Requires a new version** (never reaches your integration unless you ask for it): - removing or renaming a field in a response or a webhook; - changing a field's type or meaning; - changing an error code. **Ships without a new version**, because it doesn't break a well-written integration: - new fields in a response or in a webhook's `data`; - new event types; - new endpoints and new optional parameters. The text of the `error` field is a message for people and may improve at any time: code against `code`, never against the text. Your integration should ignore fields it doesn't know and treat an unknown event type as something it can discard. If you left an endpoint's events unchecked, you receive **all** of them, including the ones Cord adds later. When a new version exists, it will show up in the table above with what changed. --- # Clients API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/clientes Last updated: 2026-10-13 Synchronize and manage the client directory from your accounting systems. ## Overview The `Client` object contains the master commercial record of the people or organizations you bill. Synchronizing clients via the API is the foundation for keeping Cord perfectly aligned with your ERP or CRM (like Salesforce or HubSpot). ## Creating a Client Create a new client by sending a `POST /api/v1/clientes`. The only strictly required field is the company name (`empresa`); everything else is optional and depends on your business and country. `rfc` is the Mexican tax ID (Registro Federal de Contribuyentes) — it only applies if your client is invoiced in Mexico. If your business or your client is in another country, just omit the field; Cord doesn't require an `rfc` to create or invoice a client outside Mexico. **Request:** ```bash curl -X POST "https://cordhq.app/api/v1/clientes" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -d '{ "empresa": "Stark Industries", "contacto": "Tony Stark", "email": "tony@stark.com", "rfc": "STA120412XYZ", "terminos": "net30", "limite": 500000, "nivel": "oro", "descuento_pct": 15 }' ``` **Successful Response:** ```json { "data": { "id": "8f7b2c1e-4d3a-4b9f-a6e2-1c5d7e9f0a3b" } } ``` ### Automated Business Rules When you create clients via API, Cord applies real-time logical constraints: - Payment terms (`terminos`) must be valid: `contado` or `net7`, `net15`, `net30`, `net45`, `net60`, `net90` (N days of credit). If you pass an invalid term, it defaults to `contado`. - Partnership level (`nivel`) is restricted to `estandar`, `plata`, `oro`, or `distribuidor`. - The RFC (if you send one) is normalized to uppercase automatically. - The discount (`descuento_pct`) is mathematically bounded between 0 and 100. ## Listing Clients Retrieve the complete catalog using [Pagination](/en/docs/desarrolladores/esenciales/paginacion). ```bash curl -X GET "https://cordhq.app/api/v1/clientes?limit=100" \ -H "Authorization: Bearer sk_live_tU..." ``` ```json { "data": [ { "id": "8f7b2c1e-4d3a-4b9f-a6e2-1c5d7e9f0a3b", "empresa": "Stark Industries", "contacto": "Tony Stark", "email": "tony@stark.com", "telefono": "", "rfc": "STA120412XYZ", "terminos": "Net 30", "terminosCode": "net30", "limite": 500000, "nivel": "oro", "descuentoPct": 15, "countryCode": "", "direccionLine1": "", "ciudad": "", "region": "", "language": "en", "createdAt": "2026-08-01T10:00:00.000Z", "nCotizaciones": 4, "cerrado": 32000 } ], "meta": { "limit": 100, "offset": 0, "total": 1, "next_cursor": null } } ``` When **creating** a client, `POST /api/v1/clientes` also accepts the recipient's address and tax details: `country_code` (ISO 3166-1 alpha-2), `direccion_line1` and `direccion_line2` (up to 200 characters), `ciudad` and `region` (up to 100), and for Mexico `regimen_fiscal`, `uso_cfdi`, and `cp_fiscal`. On reads they come back as `countryCode`, `direccionLine1`, `direccionLine2`, `ciudad`, `region`, `regimenFiscal`, `usoCfdi`, and `cpFiscal`. When **updating** with `PATCH`, only `country_code` from that group can be changed; the address and tax details are edited from the client's record in the app. When creating you can also send `buyer_reference`: the buyer reference their European e-invoices carry by default (in Germany, a public body's Leitweg-ID). An invoice can carry its own; see the [Invoices API](/en/docs/desarrolladores/funciones/facturas). ### Validated tax ID Cord validates `rfc` with the check digits of the client's country or, if you don't send `country_code`, your account's country: RFC in Mexico, NIF/NIE/CIF in Spain, EIN in the United States, CNPJ or CPF in Brazil, NIT in Colombia, CUIT in Argentina, RUT in Chile, RUC in Peru, SIREN, SIRET, or TVA in France, USt-IdNr. or Steuernummer in Germany, VAT or UTR in the United Kingdom, and Business Number in Canada. One that fails responds `422` with `code: "invalid_tax_id"` and a reason that names the local ID. When updating, it's only validated if you change the ID or the country: an old value doesn't block you from fixing the phone or the email. ### Document language `language` is the language in which the client receives their quotes, invoices, PDFs, emails, and links: `es`, `en`, `pt`, `fr`, or `de`; `null` means your organization's. Send it when creating and when updating. In `PATCH`, omitting it keeps it, and sending `null` or an empty string goes back to your organization's. Any other value returns `400` with `code: "invalid_request"` and `field: "language"`. Changing it doesn't rewrite what was already sent: each quote and invoice keeps the language it was sent or issued in. ### Searching clients `q` searches company, contact, email, and RFC. `email` matches the exact email, case-insensitive; use it to avoid duplicates before creating a client from another tool. ```bash curl -X GET "https://cordhq.app/api/v1/clientes?email=tony@stark.com" \ -H "Authorization: Bearer sk_live_tU..." ``` ## Retrieving a Client `GET /api/v1/clientes/{id}` returns the same object as the list. An id from another organization returns `404`. ## Updating a Client `PATCH /api/v1/clientes/{id}` changes only the fields you send: `empresa`, `contacto`, `email`, `telefono`, `rfc`, `terminos`, `country_code`, and `language`. Everything else is kept. Credit limit, level, and discount can't be changed through this endpoint even if you send them. Requires a key with write permission. ```bash curl -X PATCH "https://cordhq.app/api/v1/clientes/8f7b2c1e-4d3a-4b9f-a6e2-1c5d7e9f0a3b" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -d '{ "email": "procurement@stark.com" }' ``` ```json { "data": { "ok": true } } ``` Every change emits the `client.updated` event. --- # Collections API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/cobranza Last updated: 2026-10-07 Query the aging of your client portfolio and accounts receivable. ## Overview The Collections API is an analytical, mass-read endpoint specifically designed for recovery workflows. Instead of forcing you to download thousands of quotes and calculate dates manually, Cord performs the complete aging and balance calculations on the backend. This endpoint is perfect for being consumed by a Cron job (`node-cron` or Github Actions) to trigger SMS reminders, or to feed a PowerBI dashboard. ## Retrieving Portfolio Status The `GET /api/v1/cobranza` endpoint returns a master summary of the organization's financial health. **Requires the Professional plan or higher.** Collections is a paid capability. Without the required plan, the endpoint responds `402 Payment Required` with `code: "subscription_required"` instead of data — see [Error Handling](/en/docs/desarrolladores/esenciales/errores). **Request:** ```bash curl -X GET "https://cordhq.app/api/v1/cobranza" \ -H "Authorization: Bearer sk_live_tU..." ``` **Response (Analytical Snapshot):** The response is structured for immediate use, stripping each account's secret public `token` for security — publishing it in a list would turn any read-only key into a payment-link dispenser. Each `total` is the quote total in its own sale currency, unconverted; the response doesn't include each account's currency. `resumen`, `aging`, and `clientes` add those totals as they are, so if your business quotes in more than one currency those sums mix currencies. The portfolio includes approved or invoiced quotes (`approved`, `invoiced`) that aren't recurring retainers; Cord Invoicing invoices are read with the [Invoices API](/en/docs/desarrolladores/funciones/facturas). ```json { "data": { "resumen": { "totalPorCobrar": 450000, "totalVencido": 150000, "totalVigente": 300000, "nPorCobrar": 24, "nVencidas": 12, "nClientes": 9, "nExcedidos": 1, "interesTotal": 3200, "interesPct": 3, "avgDelay": 6, "esperado7": 80000, "esperado30": 220000 }, "aging": [ { "key": "vigente", "label": "Not yet due", "monto": 300000, "n": 12, "color": "#3b82f6" }, { "key": "d30", "label": "1–30 days", "monto": 50000, "n": 6, "color": "#f59e0b" }, { "key": "d60", "label": "31–60 days", "monto": 20000, "n": 3, "color": "#f97316" }, { "key": "d60p", "label": "60+ days", "monto": 80000, "n": 3, "color": "#ef4444" } ], "items": [ { "id": "2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f", "folio": "COT-00104", "empresa": "Stark Industries", "clienteId": "8f7b2c1e-4d3a-4b9f-a6e2-1c5d7e9f0a3b", "status": "invoiced", "total": 5000, "overdue": true, "diasVencido": 14, "interes": 42 } ], "clientes": [ { "empresa": "Stark Industries", "saldo": 55000, "limite": 500000, "n": 3, "excede": false, "uso": 11 } ] } } ``` `aging` is an array of 4 fixed buckets, not an object keyed by day range: `vigente` (not yet due), `d30` (1 to 30 days overdue), `d60` (31 to 60), and `d60p` (more than 60). `status` in `items` is the real quote state (`approved` or `invoiced`); when it's overdue, `overdue` comes back `true` and `diasVencido` counts the days. --- # Quotes API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/cotizaciones Last updated: 2026-10-13 Create, update, and send quotes programmatically. ## Overview The `Quote` (`cotizacion`) object represents a commercial proposal to a client. Using the Cord API, you can inject quotes directly from an ERP, CRM, or generate automated shopping cart workflows. All quotes generated via API are recorded in the audit log (`audit_log`), automatically tagged as originating from your API Key. ## Creating a Quote To create a draft quote, you must perform a `POST /api/v1/cotizaciones` sending the commercial details. **Request:** ```bash curl -X POST "https://cordhq.app/api/v1/cotizaciones" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -d '{ "cliente_id": "8f7b2c1e-4d3a-4b9f-a6e2-1c5d7e9f0a3b", "terminos": "net30", "vigencia_dias": 15, "notas": "Annual project", "base_currency": "EUR", "items": [ { "descripcion": "Annual license — Pro plan", "cantidad": 12, "precio_unitario": 500 } ] }' ``` Every line in `items` requires `descripcion`, `cantidad`, and `precio_unitario` — field names stay in Spanish regardless of the request's language, since they are the API's canonical schema. `producto_id` is optional (it references a product from your [catalog](/en/docs/desarrolladores/funciones/productos) to inherit its name and list price), and `precio_negociado` lets you capture a discounted price different from the list price. There is no `sku` field: to link a line to a product, use its `producto_id`. ### Quote fields | Field | Details | |---|---| | `items` | Required. The lines (see the next table). | | `cliente_id` or `cliente` | A client from your directory, or the details to create one (`empresa`, plus optional `email`, `contacto`, `telefono`, `rfc`, and `fiscal`). | | `terminos` | `contado`, `net7`, `net15`, `net30`, `net45`, `net60`, or `net90` (N calendar days). Without it, the client's terms or your account's. | | `vigencia_dias` | Days the quote is valid from when it's sent. | | `notas` | Notes for the client. | | `base_currency` | Sale currency (ISO 4217). | | `fiscal_currency` | Accounting currency; if it differs from the sale currency, the invoice declares the exchange rate. | | `iva_incluido` | `true` if prices already include tax. | | `descuento` | Document discount before tax: `{ "tipo": "porcentaje", "valor": 10 }` or `{ "tipo": "monto", "valor": 2500 }`. Cord calculates the amount and spreads it across the lines; an amount is capped at the subtotal. `null` removes it. See [Discounts and coupons](/en/docs/cotizacion/descuentos). | | `cupon` | A coupon code from your account (for example, `"WELCOME10"`). Cord validates its dates, currency, and uses; if present, it wins over `descuento`. | | `send` | `true` to send it on creation. Secret key only. | | Line field | Details | |---|---| | `descripcion`, `cantidad`, `precio_unitario` | Required. | | `producto_id` | Catalog product. | | `precio_negociado` | The line's final price, if different from the list price. | | `costo_unitario` | Internal cost to calculate margin. The client never sees it. | | `tax_rate` | Fraction from 0 to 1 (`0.16`, not `16`), validated against your tax catalog. `0` means deliberately exempt. | | `exemption_reason` | Only with `tax_rate` 0. Spain: the Verifactu exemption or non-subject reason (E1–E6, N1, N2, S2). Rest of the EU: the e-invoice VATEX code. | | `clave_sat`, `clave_unidad_sat` | Mexico only: the SAT product or service key (8 digits) and unit key for that line. They win over the product's; a key with an invalid format responds `400`. Ignored outside Mexico. | ```bash curl -X POST "https://cordhq.app/api/v1/cotizaciones" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: quote-order-4471" \ -d '{ "cliente_id": "8f7b2c1e-4d3a-4b9f-a6e2-1c5d7e9f0a3b", "terminos": "net45", "base_currency": "MXN", "cupon": "WELCOME10", "items": [ { "descripcion": "Gray cement CPC 30R", "cantidad": 400, "precio_unitario": 245, "tax_rate": 0.16, "clave_sat": "30111601", "clave_unidad_sat": "H87" } ] }' ``` With a **publishable key** (your website's), Cord ignores `descuento`, `precio_negociado`, and `costo_unitario`: the only discount it accepts is a `cupon`. A coupon that doesn't exist responds `404` with `code: "coupon_no_existe"`; an inactive, expired, exhausted, wrong-currency, or per-client coupon without a client responds `409` with `coupon_inactivo`, `coupon_vencido`, `coupon_aun_no_vigente`, `coupon_agotado`, `coupon_agotado_cliente`, `coupon_moneda`, or `coupon_requiere_cliente`. `base_currency` is the currency the client sees and pays the quote in (ISO 4217, e.g. `MXN`, `USD`, `EUR`, `GBP`). It's optional — omit it and Cord falls back to your organization's accounting currency — but the API is country-agnostic: an account in Madrid, Austin, or Bogotá quotes in its own currency with no extra parameter. **Successful Response:** Cord returns the quote `id` (a UUID), its public `token`, and the public link (`link_publico`) already built as an absolute URL, so you can immediately send it to your client via WhatsApp, SMS, or an external email engine. If your organization has an active custom domain, the link uses that domain instead of `cordhq.app`. ```json { "data": { "id": "2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f", "folio": "COT-00104", "token": "9f3b6c2a7e1d4f8b0a5c3e7d1b9f2a46", "link_publico": "https://cordhq.app/q/9f3b6c2a7e1d4f8b0a5c3e7d1b9f2a46", "needs_approval": false } } ``` If the quote requires internal approval before it can be sent (for example, a discount outside the allowed threshold), `needs_approval` comes back `true` and `motivo` describes the reason. ## Listing Quotes You can retrieve your paginated quote history or filter by status (for example, finding all `sent` or `paid` quotes). **Request:** ```bash curl -X GET "https://cordhq.app/api/v1/cotizaciones?status=paid&limit=10" \ -H "Authorization: Bearer sk_live_tU..." ``` The `status` value is the internal state as-is (English, never translated): `draft`, `sent`, `viewed`, `approved`, `rejected`, `expired`, `paid`, or `invoiced`. To find a quote by its number, use `folio=COT-00104`: it matches the full number, case-insensitive. To list only one client's quotes, use `cliente_id=`. ```json { "data": [ { "id": "2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f", "folio": "COT-00104", "cliente": "Stark Industries", "status": "paid", "total": 6000, "moneda": "MXN", "terminos": "Net 30", "terminos_codigo": "net30", "vigencia": "10 sep 2026", "creada": "20 ago 2026", "link_publico": "https://cordhq.app/q/9f3b6c2a7e1d4f8b0a5c3e7d1b9f2a46", "language": "es" } ], "meta": { "limit": 10, "offset": 0, "total": 1, "next_cursor": null } } ``` In the list and the detail, `terminos` comes as a label in your account's language (`Due on receipt` or `Contado`, `Net 45`) and `vigencia` and `creada` as display dates (`Sep 10, 2026`), not as ISO dates. Don't parse them: to compare the term use `terminos_codigo` (`contado`, `net7`, `net15`, `net30`, `net45`, `net60`, or `net90`), which doesn't change with the language; for the exact time of each change, use `created_at` from the [event history](/en/docs/desarrolladores/funciones/eventos) with `object_id`. In the list, `link_publico` is also an absolute URL, just like in the creation response. For the detail of a single quote (line items, event timeline, approval), use `GET /api/v1/cotizaciones/{id}`. `language` is the language in which the client receives the quote: `es`, `en`, `pt`, `fr`, or `de`. It's read-only: the quote takes it when sent, from the client or, if they have none, from your organization, and a new version keeps it. It's `null` while the quote is a draft. To send it in another language, change the [client's](/en/docs/desarrolladores/funciones/clientes) `language` before sending. The detail also includes `descuento`: `null` if there's none, or the document discount with its definition, the coupon it came from, and the calculated amount before tax: ```json "descuento": { "tipo": "porcentaje", "valor": 10, "cupon": "WELCOME10", "monto": 9800, "moneda": "MXN" } ``` `total` already includes the discount. ## Proposing lines with AI `POST /api/v1/cotizaciones/ia` takes `{ "texto": "..." }` (the client's order, up to 6000 characters) and returns the lines matched to your catalog, without creating anything: ```json { "data": { "moneda": "MXN", "items": [{ "id": "7e3c9a1f-2b4d-4c6e-8f0a-b1d3e5f7a9c2", "nombre": "Gray Cement 50kg", "unidad": "sack", "lista": 185, "negociado": null, "cantidad": 5 }] } } ``` `id` is `null` when the item is not in your catalog. Prices are in `moneda`. To create the quote, send those lines to `POST /api/v1/cotizaciones`. It needs a write key and uses one AI unit from your plan: when none are left you get `429` with `code: "ai_quota_exceeded"`; if the text has no products, `422` with `code: "no_items"`. ## Changing a quote status With a write key (`write`) you can move a quote through its lifecycle with `POST /api/v1/cotizaciones/{id}`: ```bash curl -X POST "https://cordhq.app/api/v1/cotizaciones/2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: approve-COT-00104" \ -d '{ "action": "approve" }' ``` | `action` | From status | Result | |---|---|---| | `send` | `draft` | Sends the quote to the client (email and link) in their document language, which the quote saves in `language`. On the Free plan it uses one of the monthly sends. | | `resend` | `sent`, `viewed`, `expired` | Sends it to the client again. | | `approve` | `sent`, `viewed` | Marks it as approved. | | `reject` | `sent`, `viewed` | Marks it as rejected. | | `mark_paid` | `approved`, `invoiced` | Records the payment. Accepts an optional `payment_method` (defaults to `transferencia`). Pending online payments for that quote are canceled. | The response is `{ "data": { "ok": true, "status": "approved" } }`. If the quote is not in a status the action can apply to, or another request changed it at the same time, you get `409` with `code: "invalid_state"` and nothing is applied. Every change is recorded in the audit log with your key as the actor and fires its [webhook](/en/docs/desarrolladores/herramientas/webhooks) event. Issuing the invoice is not available on this route: invoices are created and issued with `POST /api/v1/facturas` and `POST /api/v1/facturas/{id}`. ## Deleting a draft `DELETE /api/v1/cotizaciones/{id}` deletes a quote that was **never sent** (`draft`). Any other status returns `409`. --- # Events API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/eventos Last updated: 2026-10-08 Cord's 41 event types with their object and when they're emitted, the shape of data per object, actor values, the GET /api/v1/events history and key verification with /me. Every relevant change in Cord produces an **event**: a record with a type, an object, data and who caused it. The same events are delivered to your [webhooks](/en/docs/desarrolladores/herramientas/webhooks), trigger Cord Workflows and stay in a history you query with `GET /api/v1/events`, whether or not any endpoint is subscribed. ## Event catalog There are 41 types. The **Object** column is the value of `object` in the history and determines the shape of `data` (see the next section). | Event | Object | Emitted when… | |---|---|---| | `quote.created` | `quote` | A quote is created from the app, the API, MCP or Cord Elements. | | `quote.sent` | `quote` | The quote is sent to the client. | | `quote.viewed` | `quote` | The client opens the public link for the first time. The seller's own views don't count. | | `quote.updated` | `quote` | The seller edits and resends it. | | `quote.approved` | `quote` | The client approves it (fully or partially), or it's marked approved through the API. | | `quote.rejected` | `quote` | The client rejects it, or it's marked rejected through the API. | | `quote.expired` | `quote` | Its validity passes without a decision (it was sent or viewed). | | `quote.deleted` | `quote` | A draft that was never sent is deleted. | | `quote.paid` | `quote` | Full payment is received, or the last pending charge of a deposit or installment plan. | | `quote.approval_requested` | `quote` | A quote is held for internal approval because of discount, amount or margin. | | `quote.approval_decided` | `quote` | Management approves or rejects that request. | | `quote.comment_added` | `quote` | The client or the seller writes in the quote's conversation. | | `payment.partial` | `quote` | A partial charge (deposit, balance or installment) arrives without completing the total. | | `payment.failed` | `quote` | A recurring charge of a retainer fails. | | `invoice.stamped` | `quote` | A quote's CFDI is stamped (Mexico). | | `invoice.issued` | `quote` | A quote's commercial invoice is issued outside Mexico. | | `invoice.finalized` | `invoice` | A Cord Invoicing invoice is issued. | | `invoice.sent` | `invoice` | That invoice is sent to the client. | | `invoice.paid` | `invoice` | The invoice is fully paid. | | `invoice.payment_failed` | `invoice` | A charge against the invoice fails. | | `invoice.voided` | `invoice` | The invoice is voided. | | `invoice.marked_uncollectible` | `invoice` | The invoice is marked uncollectible. | | `invoice.overdue` | `invoice` | Its due date passes without it being settled. | | `client.created` | `client` | A client is created. | | `client.updated` | `client` | A client's details are edited. | | `client.deleted` | `client` | A client is deleted. | | `product.created` | `product` | A product is created. | | `product.updated` | `product` | A product is edited. | | `product.deleted` | `product` | A product is deleted. | | `task.created` | `task` | A task is created from the app, the API, MCP, or a workflow, or by Cord on its own (chargeback, SPEI refund). Carries `cotizacion_id` and `factura_id` (or `null`). | | `task.completed` | `task` | A task is marked done. | | `promise.created` | `promise` | A payment promise is recorded. | | `promise.kept` | `promise` | The promise is kept. | | `promise.broken` | `promise` | The promise is broken. | | `dispute.created` | `dispute` | A client opens a chargeback on a Cord Payments charge. | | `dispute.closed` | `dispute` | The chargeback closes with its outcome. | | `refund.succeeded` | `refund` | A refund completes. | | `refund.failed` | `refund` | A refund fails. | | `payout.paid` | `payout` | A payout reaches your bank account. | | `payout.failed` | `payout` | A payout fails. | | `account.updated` | `account` | What your payments account can do changes. Only emitted when a field changes. | `ping` isn't a catalog event: it's the test delivery from the Workbench's **Test** button and never shows up in the history. Besides the 41 types, the history may show `quote.expiring`, `invoice.due_soon`, `invoice.past_due` and `schedule.tick`. They're internal signals Cord Workflows use to act before a deadline; they aren't delivered by webhook and aren't part of the catalog. If you walk the full history, ignore types you don't know. ## Shape of `data` per object Every amount travels with its currency in `moneda`. Field names are the server's, in Spanish. | Object | `data` fields | |---|---| | `quote` | `id`, `folio`, `status`, `moneda`, `total`, `cliente`, `cliente_id`, `link_publico` | | `invoice` | `id`, `object`, `numero`, `folio_fiscal`, `estado`, `estado_fiscal`, `pais`, `tipo`, `moneda`, `total`, `pagado`, `saldo`, `vence`, `cliente`, `cotizacion_id`, `link_publico` | | `client` | `id`, `object`, `empresa`, `contacto`, `email`, `telefono`, `rfc`, `terminos`, `country_code` | | `product` | `id`, `object`, `sku`, `nombre`, `unidad`, `precio_lista`, `activo` (never the cost or margin) | | `task` | `id`, `object`, `titulo`, `due_date`, `done`, `cotizacion_id` (no assignee, priority, or notes) | | `promise` | `id`, `object`, `cotizacion_id`, `fecha_promesa`, `monto`, `moneda`, `estado` | | `dispute` | `id`, `object`, `monto`, `moneda`, `motivo`, `estado`, `fecha_limite`, `referencia`, `cotizacion_id`, `folio`, `cliente` | | `refund` | `object`, `monto`, `moneda`, `motivo`, `motivo_falla`, `referencia`, `cotizacion_id`, `folio`, `cliente` | | `payout` | `id`, `object`, `monto`, `moneda`, `llegada`, `metodo`, `motivo_falla`, `referencia` | | `account` | `object`, `puede_cobrar`, `puede_depositar`, `motivo_bloqueo`, `pendientes` | Extra fields per event: | Event | Adds | |---|---| | `payment.partial` | `tipo` (`anticipo`, `saldo` or `cuota`), `monto` (of this charge), `numero_cuota`, `saldo_pendiente`, `payment_method` | | `quote.approval_requested` | `motivo` | | `quote.approval_decided` | `decision` (`approved` or `rejected`) | | `quote.comment_added` | `autor` (`cliente` or `vendedor`), `mensaje`, `item_id` when it's about a line; a client counteroffer carries `tipo: "contraoferta"` and `propuesta` | | `client.updated` | `empresa_anterior`, `email_anterior`, `terminos_anterior` when they changed | | `product.updated` | `precio_lista_anterior`, `activo_anterior` when they changed | | `client.deleted` | Only `id`, `object` and `empresa` | | `product.deleted` | Only `id`, `object` and `nombre` | On an invoice, `estado` is its lifecycle (`draft`, `open`, `paid`, `void` or `uncollectible`) and `estado_fiscal` its registration with the tax provider (`pending`, `issued`, `cancelled` or `error`). On a quote, `status` is `draft`, `sent`, `viewed`, `approved`, `rejected`, `expired`, `invoiced` or `paid`. The `data` stored in the history is the webhook's **without** `link_publico`: the link is a client credential and isn't stored. ## Who caused the event: `actor` | Value | Meaning | |---|---| | `user:` | A person on your team, signed in to the app. | | `api:` | An API request with that key (or an OAuth connection). | | `mcp:` | An MCP server tool. | | `client` | Your client, from the public link of the quote or invoice. | | `workflow:` | A Cord Workflows action. | | `integration::` | An integration syncing into Cord, for example HubSpot. | | `slack`, `slack:`, `shopify` | An action from those integrations. | | `system`, `system:cron` | Cord itself: an expiration, a charge from the payment processor or a scheduled job. | Treat `actor` as text with a prefix: decide by what comes before the colon and don't assume the list won't grow. ## History: `GET /api/v1/events` Returns your organization's events, newest first. If your server was down longer than the retries cover, this is where you recover what you missed. | Parameter | What it does | |---|---| | `type` | An event type, for example `quote.approved`. An unknown type returns `400`. | | `object_id` | The object's UUID: the full history of a quote, an invoice or a client. | | `limit` | From 1 to 200; defaults to 50. | | `cursor` | The `next_cursor` from the previous page. | ```bash curl "https://cordhq.app/api/v1/events?object_id=8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10&limit=10" \ -H "Authorization: Bearer sk_test_..." ``` ```js import { Cord } from '@flouviahq/node'; const cord = new Cord(process.env.CORD_API_KEY); const page = await cord.events.list({ object_id: '8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10', limit: 10 }); for (const event of page.data) console.log(event.created_at, event.type, event.actor); ``` ```json { "data": [ { "id": "e81c5a3f-7d2b-4e9a-b6c1-0f4d8a2e5c71", "type": "quote.approved", "object": "quote", "object_id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10", "data": { "id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10", "folio": "COT-0001", "status": "approved", "moneda": "MXN", "total": 13920, "cliente": "Ferretería La Prueba", "cliente_id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90" }, "actor": "client", "created_at": "2026-10-07T17:31:44.208Z" }, { "id": "3a7f1c9e-2b4d-4a6e-8c0f-5d9b3e7a1c24", "type": "quote.sent", "object": "quote", "object_id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10", "data": { "id": "8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10", "folio": "COT-0001", "status": "sent", "moneda": "MXN", "total": 13920, "cliente": "Ferretería La Prueba", "cliente_id": "0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90" }, "actor": "api:2c6e0a9d-4f1b-4c3e-8a7d-9b5f1e3c7a20", "created_at": "2026-10-07T17:04:12.318Z" } ], "meta": { "next_cursor": null } } ``` - The history's `id` is the record's own UUID. It is **not** the `evt_…` of the webhook delivery: to deduplicate across the two, use `object_id` plus `type` plus `created_at`. - `object_id` is `null` for events without an object that has a UUID, such as `account.updated`. - Pagination is by cursor and stable: a new event doesn't shift the page you're reading. See [Pagination](/en/docs/desarrolladores/esenciales/paginacion). - An `object_id` that isn't a UUID or an invalid `cursor` returns `400` with `code: "invalid_request"`. ### Retention The history is append-only: an event isn't edited after it's written. It's kept for 90 days and then a daily process deletes it; an event that started a workflow run is kept as long as that run exists, and a run is deleted one year after it finishes. The webhook delivery log has its own period (30 days; 90 for failed ones). Everything is deleted along with the organization. ## Verify a key: `GET /api/v1/me` It's the simplest call in the API: it confirms the key is valid and says which organization it belongs to, its permission and its mode. It answers with any secret key, restricted key or OAuth connection, regardless of per-resource permissions. ```bash curl https://cordhq.app/api/v1/me \ -H "Authorization: Bearer sk_test_..." ``` ```js import { Cord } from '@flouviahq/node'; const cord = new Cord(process.env.CORD_API_KEY); const me = await cord.me(); console.log(me.org.nombre, me.scope, me.mode); ``` ```json { "data": { "org": { "id": "5b1f7d9e-3c2a-4e8b-9f61-0a7c4d2e8b13", "nombre": "Aceros del Norte", "plan": "pro" }, "scope": "write", "mode": "test" } } ``` | Field | Content | |---|---| | `org.id` | The id of the organization the key operates on. With a test key it's your test environment's id, different from the real account's. | | `org.nombre` | The organization's name. | | `org.plan` | Current plan: `free`, `starter`, `pro`, `scale` or `developer`. | | `scope` | `read` or `write`. On a restricted key, per-resource permissions take precedence over this value. | | `mode` | `test` or `live`. | Use it to test a credential before saving it in your integration. --- # Invoices API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/facturas Last updated: 2026-10-13 List, create, issue, send, collect and void invoices from your system with Cord's API v1: drafts, irreversible issuing, partial payments and credit notes. ## Overview An invoice is born as a **draft** and only becomes final when you issue it. Issuing is an explicit, irreversible action: it uses your plan's stamping when it applies (CFDI in Mexico) and gives the invoice its number. Creating never issues on its own. The invoices API is available on every plan, including Free, with standard invoices (pro forma in Mexico and Spain). Integrated tax issuing (CFDI in Mexico, and Verifactu in Spain with the electronic certificate uploaded) requires Starter or higher: requesting `document_mode: "fiscal"` without that plan responds `400 invalid_request`. ## List invoices `GET /api/v1/facturas` with these optional filters: | Parameter | What it does | |---|---| | `estado` | `draft`, `open`, `paid`, `void`, `uncollectible` or `overdue` (open and past their due date). | | `cliente` | Client id. | | `desde`, `hasta` | Range by creation date, `YYYY-MM-DD`, both ends inclusive. | | `q` | Searches by number, tax folio, originating quote folio or client name. | | `limit` | From 1 to 200; defaults to 50. | | `cursor` | The previous page's `next_cursor`. | Pagination is cursor-based, not offset-based: a new invoice never shifts the page you are reading. ```bash curl "https://cordhq.app/api/v1/facturas?limit=20" \ -H "Authorization: Bearer sk_live_tU..." ``` ```json { "data": [ { "id": "f3a1c7e9-2b4d-4f6a-8c0e-5d7b9a1c3e24", "numero": "F-0231", "folio_fiscal": "6F1C2A9E-7B4D-4E6A-8C2F-1D5B9E3A7C40", "cliente": "Aceros del Norte", "estado": "open", "estado_fiscal": "issued", "pais": "MX", "tipo": "cfdi_40", "moneda": "MXN", "total": 184300, "pagado": 0, "saldo": 184300, "vence": "2026-10-15", "vencida": false, "cotizacion_id": "2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f", "creada": "15 sep 2026", "language": "es" } ], "meta": { "next_cursor": null } } ``` `creada` comes as a display date (`15 sep 2026`), not an ISO date; `vence` is `YYYY-MM-DD`. | Field | Values | |---|---| | `estado` | `draft`, `open` (issued and awaiting payment), `paid`, `void` or `uncollectible`. | | `estado_fiscal` | `pending`, `issued` (registered with the tax provider), `cancelled` or `error`. | | `tipo` | `cfdi_40` (income CFDI, Mexico), `cfdi_egreso` (CFDI credit note), `proforma` (commercial document in Mexico, Spain, and countries with authorized invoices), `commercial_invoice` (commercial invoice), `commercial_credit_note` (commercial credit note), `verifactu_invoice` or `verifactu_credit_note` (Spain with Verifactu). With issuing through the tax authority active: `arca_invoice` (Argentina), `nfse_invoice` and `nfe_invoice` (Brazil), `sii_invoice` (Chile), `dian_invoice` (Colombia), and `sunat_invoice` (Peru), with their `*_credit_note` credit notes and, in Chile, `sii_debit_note`. | | `language` | Read-only. The language in which the client receives the invoice, its PDF, its link, and its emails: `es`, `en`, `pt`, `fr`, or `de`. The invoice takes it when issued, from the client or, if they have none, from your organization; a credit note inherits its invoice's. `null` on a draft. | ## Create a draft `POST /api/v1/facturas` creates a draft. It needs a write key and accepts `Idempotency-Key`. | Field | Required | Detail | |---|---|---| | `cliente_id` | Yes | A client in your organization. | | `items` | Yes | From 1 to 200 line items. Each with `descripcion` and `cantidad`; optional `precio_unitario`, `precio_negociado`, `producto_id`, `costo_unitario`, `tax_rate`, `exemption_reason` and, in Mexico, `clave_sat` and `clave_unidad_sat`. | | `currency` | No | Invoice currency; defaults to your account's. | | `due_date` | No | Due date as `YYYY-MM-DD`. | | `notas` | No | Up to 1000 characters. | | `iva_incluido` | No | `true` if prices already include tax. | | `document_mode` | No | `commercial` or `fiscal`. Without it, Cord issues a tax document if your plan includes it and your country has it enabled, and a commercial one otherwise. `fiscal` without the plan or an enabled country responds `400 invalid_request`. | | `fx_buffer_pct` | No | Coverage in percentage points over the reference exchange rate when `currency` differs from your accounting currency (`2` = +2%, capped at 25). Defaults to `0`. | | `descuento` | No | Document discount before tax: `{ "tipo": "porcentaje", "valor": 10 }` or `{ "tipo": "monto", "valor": 2500 }`. Cord calculates the amount and spreads it across the line items. See [Discounts and coupons](/en/docs/cotizacion/descuentos). | | `cupon` | No | A coupon code from your account. It wins over `descuento`. Its use is counted when the invoice is issued. | | `service_date`, `service_date_end` | No | Date or period of supply, `YYYY-MM-DD`. The end requires the start and can't be earlier. Without it, the invoice says it matches the issue date (required in Germany). | | `buyer_reference` | No | Buyer reference (BT-10 of the European e-invoice; in Germany, the public body's Leitweg-ID). Without it, the client's. If the client's electronic address is a Leitweg-ID, its check digits are verified and one that fails responds `400`. | | `purchase_order` | No | The client's purchase order number (BT-13). | `tax_rate` is a fraction (`0.16`, not `16`) and is validated against your tax catalog: you cannot declare an exempt line on a taxed sale. `0` means deliberately exempt; omitting it uses your account's rate. `clave_sat` and `clave_unidad_sat` win over the product's keys; with neither, the CFDI uses 01010101 and H87. A key with an invalid format responds `400`. ```bash curl -X POST "https://cordhq.app/api/v1/facturas" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: invoice-order-8812" \ -d '{ "cliente_id": "9b2e4c6a-8d1f-4a3b-b5c7-0e2d4f6a8c91", "currency": "USD", "due_date": "2026-10-15", "items": [{ "descripcion": "Rebar 3/8\"", "cantidad": 120, "precio_unitario": 4.2, "tax_rate": 0.0825 }] }' ``` ```json { "data": { "id": "f3a1c7e9-2b4d-4f6a-8c0e-5d7b9a1c3e24" } } ``` If the invoice is in a currency other than your ledger currency and no verifiable exchange rate can be obtained, it responds `503` with `code: "fx_unavailable"`: retry later, Cord never makes up a rate. ## Get an invoice `GET /api/v1/facturas/{id}` returns the list fields plus `subtotal`, `impuestos`, `moneda_contable`, `tipo_cambio`, `total_contable`, `notas`, `nota_credito_de`, `emisor`, `receptor`, `descuento`, `conceptos` and `pagos`. | Field | Details | |---|---| | `descuento` | `null`, or `{ tipo, valor, cupon, monto, moneda }`: the definition, the coupon it came from, and the amount before tax. `subtotal` is already net. | | `conceptos[].precio_unitario` | **Net** unit price, after the document discount, before tax. | | `conceptos[].subtotal` | The line's net base. | | `conceptos[].descuento` | The share of the document discount that went to that line; `0` if there's none. | | `conceptos[].clave_sat`, `conceptos[].clave_unidad_sat` | Mexico: the SAT keys the line was stamped with; `null` outside Mexico. | | `pagos` | Each payment with `monto`, `moneda`, `metodo`, `referencia`, and `cuando`. A charge that paid several invoices shows up on each one with its share. | ## Change status `POST /api/v1/facturas/{id}` with `action`: | `action` | What it does | Fields | |---|---|---| | `finalize` | Issues the invoice. Irreversible; stamps the CFDI in Mexico when it applies. | — | | `send` | Emails the invoice with its PDF to the client, in the invoice's language (`language`). Requires an issued invoice and a client with an email. | — | | `payment` | Records a full or partial payment. | `monto`, `moneda`, `metodo` (defaults to `manual`), `referencia` | | `void` | Voids the invoice. | `motivo` | | `credit_note` | Issues a credit note against the invoice. | `monto` (optional; without it, for the total), `motivo` | `payment` responds with the amount paid, the balance and the resulting status. A payment that settles the invoice fires the `invoice.paid` event. If an already stamped invoice cannot be voided directly, `void` responds `409` with `code: "credit_note_required"`: issue a credit note instead. In Mexico: - `void` requests the CFDI's cancellation under SAT reason **02**. If the SAT hasn't confirmed it yet, it responds `202` with `{ "data": { "id": "…", "estado": "open", "cancelacion": "pendiente" } }` and the invoice stays valid; `invoice.voided` isn't fired until it's confirmed. Replacement under reason 01 and the global invoice are only in the app. - `payment` on a **PPD** CFDI triggers the [automatic payment complement](/en/docs/pagos/facturacion#automatic-payment-complement) for that payment. ## Common errors | Code | When | |---|---| | `invalid_request` (400) | `cliente_id` or `items` is missing, a line has no description or quantity, `due_date` is not `YYYY-MM-DD`, the discount isn't shaped `{ tipo, valor }`, or a Leitweg-ID fails its check digits. | | `coupon_no_existe` (404) | The coupon doesn't exist on your account. | | `coupon_inactivo`, `coupon_vencido`, `coupon_aun_no_vigente`, `coupon_agotado`, `coupon_agotado_cliente`, `coupon_moneda`, `coupon_requiere_cliente` (409) | The coupon doesn't apply to this invoice; the message says why. | | `invalid_state` (409) | The action does not apply to the current status (for example, sending a draft). Sending to a client with no email responds `400` with this same code. | | `credit_note_required` (409) | The invoice is already stamped and can't be voided directly: issue a credit note. | | `not_found` (404) | The invoice doesn't exist in your organization. | | `provider_error` (502) | The tax provider rejected issuing; the message says why. | | `send_failed` (502) | The invoice email couldn't be sent. Retry `send`. | | `fx_unavailable`, `tax_catalog_unavailable` (503) | No verifiable exchange rate, or your tax catalog could not be read. Retry. | --- # Products API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/productos Last updated: 2026-10-08 Feed and query your product and service catalog. ## Overview The `Product` object contains the elements of your price list (SKU, name, base price, and unit metric). Cord's products API is secure enough that you can consume it not only from your internal servers, but also directly from your clients' browsers. ## Creating a Product Use your **Secret API Key** (`sk_`) to mass-feed the catalog. Ideal for nightly integrations or webhooks originating from inventory management systems. **Request:** ```bash curl -X POST "https://cordhq.app/api/v1/productos" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -d '{ "sku": "LIC-PRO-24", "nombre": "Professional Annual License", "unidad": "license", "precio": 12000, "activo": true }' ``` **Successful Response:** ```json { "data": { "id": "7e3c9a1f-2b4d-4c6e-8f0a-b1d3e5f7a9c2" } } ``` ### Optional tax and invoicing fields | Field | What it is | Validation | |---|---|---| | `tax_rate` | The tax the product **suggests** when added to a quote or invoice, as a fraction (`0.08` = 8%). Without it, the line uses your default rate. | Must be a rate in your tax catalog (or `0`); otherwise `400`. | | `clave_sat` | SAT product or service key (c_ClaveProdServ) for the CFDI in Mexico. | 8 digits (`81111500`); otherwise `400`. | | `clave_unidad_sat` | SAT unit key (c_ClaveUnidad). Without it, it's derived from `unidad` when stamping (`hora` → `HUR`). | 1 to 3 letters or digits (`E48`), stored uppercased; otherwise `400`. | In the list they come back as `taxRate`, `claveSat`, and `claveUnidadSat` (`null` when not set). ## Listing Products & Data Security The listing API (`GET /api/v1/productos`) features a Dynamic Masking mechanism based on the trust level of the API key you authenticate with. If you use a **Secret Key (`sk_`)**: Cord assumes you are a trusted internal system and returns the complete object, **including hidden costs and profit margins (`costo`)**. If you use a **Publishable Key (`pk_`)**: Publishable keys are exposed in the browser (for example, to render a pricing list on a public React website). Cord assumes risk and **automatically removes the `costo` field from all results in memory** before serializing the JSON. This way, your margins are never leaked to the public frontend. ```bash curl -X GET "https://cordhq.app/api/v1/productos?limit=50" \ -H "Authorization: Bearer pk_live_yX..." ``` With `sk_live_...` the same product includes `costo`: ```json { "data": [ { "id": "7e3c9a1f-2b4d-4c6e-8f0a-b1d3e5f7a9c2", "sku": "LIC-PRO-24", "nombre": "Professional Annual License", "unidad": "license", "precio": 12000, "costo": 4000, "activo": true, "taxRate": null, "claveSat": "43231500", "claveUnidadSat": null } ] } ``` With `pk_live_...`, `costo` simply isn't present on the object (not `null` or `0` — the key doesn't exist): ```json { "data": [ { "id": "7e3c9a1f-2b4d-4c6e-8f0a-b1d3e5f7a9c2", "sku": "LIC-PRO-24", "nombre": "Professional Annual License", "unidad": "license", "precio": 12000, "activo": true, "taxRate": null, "claveSat": "43231500", "claveUnidadSat": null } ] } ``` Note: a Publishable Key can only be used on four routes: `GET /api/v1/productos`, `POST /api/v1/cotizaciones`, `GET /api/v1/elements/config`, and `POST /api/v1/elements/ai-draft`. Any other route (creating products, reading clients, collections) responds `403 insufficient_scope`. It also requires an `Origin` or `Referer` header matching your organization's allowed domains, configured in **Settings › Embeddable quote builder**. A `pk_live_` key with no domains configured responds `403 origin_allowlist_required`; a `pk_test_` key works from any origin. --- # Tasks API URL: https://docs.cordhq.app/en/docs/desarrolladores/funciones/tareas Last updated: 2026-10-08 Create follow-up tasks for your team from other tools. ## What the API offers The Tasks API has a single method: `POST /api/v1/tareas`, to create a task. There are no endpoints to list, edit, complete, or delete tasks through the API; that's done from the app. To learn about changes, listen to the `task.created` and `task.completed` events with [webhooks](/en/docs/desarrolladores/herramientas/webhooks) or read them from the [event history](/en/docs/desarrolladores/funciones/eventos). ## Creating a Task `POST /api/v1/tareas` creates a task in the team's inbox. Requires a key with write permission (for a restricted key, `write` on the `tareas` resource) and accepts `Idempotency-Key`. | Field | Required | Detail | |---|---|---| | `titulo` | Yes | Task text. The first 200 characters are stored; the rest is dropped without an error. | | `due_date` | No | Due date formatted as `YYYY-MM-DD`. | | `cotizacion_id` | No | UUID of a quote from your organization to link the task to. | | `factura_id` | No | UUID of an invoice from your organization (the `id` from [`/api/v1/facturas`](/en/docs/desarrolladores/funciones/facturas)) to link the task to. It can go together with `cotizacion_id`. | Any other field in the body (for example `asignado_a`, `prioridad`, or `notas`) is ignored without an error: assignee, priority, and notes can't be set through the API. ```bash curl -X POST "https://cordhq.app/api/v1/tareas" \ -H "Authorization: Bearer sk_live_tU..." \ -H "Content-Type: application/json" \ -H "Idempotency-Key: follow-up-cot-00104" \ -d '{ "titulo": "Call Stark Industries about COT-00104", "due_date": "2026-09-20", "cotizacion_id": "2a9d8e4f-6b1c-4d7a-9e3f-5c8b1a2d4e6f" }' ``` ```json { "data": { "id": "7c1e0b4a-3f2d-4e8c-9a6b-5d1f0e2c3b4a" } } ``` The task is created **unassigned** with normal priority. In the app, its assignee, priority, and notes are set from **Tasks**; while it has no assignee, the morning [email reminder](/en/docs/gestion/tareas#email-reminder) goes to the account owner. With a test key (`sk_test_`) the task is created in test mode, which doesn't send reminders. Every new task emits the `task.created` event, with `cotizacion_id` and `factura_id` (or `null`). Tasks Cord creates on its own (chargeback and SPEI refund) emit it too. When someone marks it done in the app, `task.completed` is emitted. ## Possible errors | Code | When | |---|---| | `invalid_request` (400) | `titulo` is missing (or empty), or `due_date` isn't a real date formatted as `YYYY-MM-DD` (for example, `2026-02-30` is rejected). | | `not_found` (404) | `cotizacion_id` or `factura_id` isn't a UUID, or isn't a quote or invoice from your organization. The message is in your account's language. | | `invalid_json` (400) | The body isn't valid JSON. | | `insufficient_scope` / `insufficient_permissions` (403) | The key is read-only, or it's a restricted key without `write` on `tareas`. | The rest of the common codes are in [Error Handling](/en/docs/desarrolladores/esenciales/errores). --- # Cord CLI URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/cli Last updated: 2026-10-07 Every command in the Cord CLI (@flouviahq/cli): wizard, login, whoami, logout, setup, init, listen, trigger, simulate and events tail, with their options and environment variables. `@flouviahq/cli` is a development tool: **it only accepts test keys** (`sk_test_` or `rk_test_`), so nothing you do with it touches real data. The exception is `cord setup`, which proposes the setup of your real account and applies nothing without your approval. ## Install Use it without installing: ```bash npx @flouviahq/cli ``` Or install it globally to get the `cord` command: ```bash npm install -g @flouviahq/cli cord --version ``` The examples on this page use `cord`; with `npx` it's the same, prefixed with `npx @flouviahq/cli`. ## Commands | Command | What it does | |---|---| | `cord` | With no command and in an interactive terminal, opens the wizard. Outside a terminal it prints the help. | | `cord wizard` | Opens the wizard explicitly. | | `cord login` | Signs in from the browser and stores a test key. | | `cord whoami` | Shows the organization, mode, permission and key in use. | | `cord logout` | Deletes the key stored on your machine. | | `cord setup` | Proposes your account's setup with AI; you approve it. | | `cord init` | Detects your framework and leaves the integration ready. | | `cord listen` | Forwards test webhooks to your local server. | | `cord trigger` | Triggers a test webhook. | | `cord simulate` | Forces the outcome of the next tax issuance, or simulates the client or time passing. | | `cord events tail` | Shows events as they happen. | | `cord help` | The help. Also `--help` or `-h`. | ## Global options and variables | Option | Variable | Detail | |---|---|---| | `--api-key ` | `CORD_API_KEY` | The test key to use. Takes precedence over the stored one. | | `--base-url ` | `CORD_BASE_URL` | Cord's origin. Default `https://cordhq.app`. | | `--version`, `-v` | — | Prints the version. | | `--help`, `-h` | — | Prints the help. | The key is looked up in this order: `--api-key`, `CORD_API_KEY`, and the one stored by `cord login` in `~/.config/cord/config.json` (or `$XDG_CONFIG_HOME/cord/config.json`), with `0600` permissions. A live key (`sk_live_`, `rk_live_`) or a publishable one (`pk_`) is rejected before calling Cord. Options accept both `--option value` and `--option=value`. ## The wizard ```bash npx @flouviahq/cli ``` 1. **Connect your terminal.** If there's no valid session, it opens the browser sign-in. If the wizard is going to integrate your project, on the same screen you can create a test Secret Key for it. 2. **Choose what to do** with the arrows and the space bar: set up your account with AI, integrate Cord into the project and test webhooks on your localhost. 3. Each step runs like its standalone command (`setup`, `init`, `listen`), and at the end you see a summary of what's ready and the next step. The wizard needs an interactive terminal. In scripts and CI, use the standalone commands. ## `cord login` ```bash cord login ``` It opens your browser with a confirmation code (for example `WXYZ-2346`). Check it matches the one in your terminal and authorize with your Cord session: the terminal receives a key on its own and you copy nothing. - The key is **restricted and for testing**: it can only use the simulators (`test_helpers`, write), read events (`eventos`, read) and propose setups (`setup`, write). - It expires in 90 days and shows up in **Developers › API keys** as `CLI · `, where you can revoke it. Reconnecting the same machine revokes the previous key. - The code expires in 10 minutes and the key is handed out only once. - The CLI only opens browser addresses on the same origin as `--base-url`. | Variant | What it does | |---|---| | `cord login --no-browser` | Prints the address so you can open it on another machine (for example, a server over SSH). | | `cord login --api-key` | Asks you to paste a test key of yours and verifies it before storing it. | | `cord login --api-key sk_test_...` | Stores that key without asking, after verifying it. | A regular test Secret Key also works for `cord listen` and `cord init`: put it in `CORD_API_KEY`. ## `cord whoami` and `cord logout` ```bash cord whoami ``` ```text Empresa Aceros del Norte Modo prueba Permiso write Llave sk_test_…9f2a ``` The CLI's interface is in Spanish. `cord logout` deletes the configuration file. It doesn't revoke the key in Cord: for that, revoke it in **Developers › API keys**. ## `cord setup` ```bash cord setup --sitio materialesdelvalle.mx --descripcion "Building materials on 30-day credit" --archivo prices.xlsx ``` | Option | Detail | |---|---| | `--sitio ` | Your website: name, branding and contact details. | | `--descripcion ` | What the business does, how it gets paid and which taxes it handles. | | `--archivo ` | Price list: `.csv`, `.xlsx`, `.pdf` or a photo, up to 3 MB. | Without options, it asks the same things step by step. Cord builds the proposal, opens it in your browser and waits for your approval (up to 30 minutes; Enter stops waiting). **Nothing is applied until you approve it.** The proposal always configures your real account, even with a test key, and counts toward the limit of 6 proposals per day. Details in [Assisted setup](/en/docs/desarrolladores/herramientas/configuracion-asistida). ## `cord init` ```bash cord init ``` It detects the framework in the current folder, tells you exactly what it's going to do and, if you accept, does it. It never overwrites an existing file. | Framework | Installs | Creates or suggests | Env file | |---|---|---|---| | Next.js (App Router) | `@flouviahq/node` and `@flouviahq/elements` | `app/api/webhooks/cord/route.ts` and the proxy `app/api/cord/[...path]/route.ts` (under `src/` if `src/app` exists) | `.env.local` | | Astro | `@flouviahq/node` and `@flouviahq/elements` | `src/pages/api/webhooks/cord.ts` | `.env.local` | | Next.js (Pages Router), Express | `@flouviahq/node` and `@flouviahq/elements` | Shows you the webhook route to paste | `.env` | | Laravel, Django, Flask, FastAPI | Nothing: the PHP and Python SDKs aren't published yet | Shows you a route that verifies the signature with no dependencies | `.env` | - It installs with your project's package manager based on the lockfile: pnpm, yarn, bun or npm. - It writes `CORD_SECRET_KEY` only to an env file your `.gitignore` ignores. If there isn't one, it doesn't write keys and tells you so. - The generated route verifies the signature with `CORD_WEBHOOK_SECRET`. ## `cord listen` ```bash cord listen --forward-to http://localhost:3000/api/webhooks/cord --env-file .env.local ``` | Option | Detail | |---|---| | `--forward-to ` | **Required.** `http://` or `https://` URL of your local server. | | `--events ` | Only those events, comma-separated: `--events quote.paid,invoice.paid`. Without it, all of them. | | `--env-file ` | Stores the session secret there as `CORD_WEBHOOK_SECRET`, without touching the other lines. | | `--allow-remote` | Allows forwarding to a host that isn't your machine. | Cord can't make requests to your machine, so the CLI opens a **listening session** in your test environment and polls it every second and a half. Events go through the same engine as production (signature, API version, history) and the CLI forwards them with the real signature headers. Verify with `constructEvent` and the session secret, just like in production. ```text │ 17:04:12 200 quote.sent evt_9d2a6c4e1f8b3a5d7c0e2f4a6b8d1c3e 41 ms ``` - By default it only forwards to `localhost`, `127.0.0.1`, `::1` and `*.localhost` hosts. The URL can't carry a username or password, and a redirect from your server isn't followed. - The session expires in 24 hours and Ctrl+C closes it. You can have up to 3 open sessions per key. - The session secret changes every time and only works for that session. - An event counts as delivered when the CLI picks it up. If your server doesn't respond, the CLI shows it and doesn't retry: trigger it again with `cord trigger`. ## `cord trigger` ```bash cord trigger invoice.paid cord trigger quote.approved --objeto 8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 ``` It triggers any of the 41 catalog events to your test endpoints and your `cord listen` sessions. Without `--objeto`, with sample data; with the UUID of a test quote or invoice, with its real data. Delivery goes through the real engine: signature, retries and history in the Workbench. ## `cord simulate` ```bash cord simulate fiscal pac_caido cord simulate quote 8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 vista cord simulate quote 8b0c6f0e-2d55-4c1e-9a43-6a2f1c7d9e10 vencer ``` | Form | Effect | |---|---| | `simulate fiscal ` | The next test tax issuance results in `exito`, `pac_caido`, `receptor_invalido`, `certificado_vencido` or `timbre_duplicado`. | | `simulate quote vista` | The client opens the link: emits `quote.viewed`. | | `simulate quote vencer` | The quote expires: emits `quote.expired`. Only for a sent or viewed quote. | They're the same API [simulators](/en/docs/desarrolladores/empezar/pruebas). ## `cord events tail` ```bash cord events tail --type quote.paid ``` It polls the [event history](/en/docs/desarrolladores/funciones/eventos) every 2 seconds and shows new events as they happen, from the moment you start it. `--type` filters by one type. Ctrl+C to exit. ## Common errors The CLI's messages are in Spanish. | Message | What to do | |---|---| | `No hay sesión. Corre cord login…` | There's no key in `--api-key`, `CORD_API_KEY` or the configuration. | | `Esa es una llave en vivo…` | The CLI only uses test keys. Create an `sk_test_` key or use `cord login`. | | `Falta --forward-to…` | `cord listen` needs your server's URL. | | `--forward-to apunta a …` | To forward outside your machine, add `--allow-remote`. | | `Ya hay 3 sesiones de escucha abiertas con esta llave…` | Close one with Ctrl+C or wait for it to expire. | API errors include the `request_id` in parentheses: look it up in **Developers › Logs**. --- # Assisted setup URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/configuracion-asistida Last updated: 2026-10-07 Propose a Cord account's setup from a website, a description and a price list with POST /api/v1/setup/plans: states, limits, review_url and human approval. Cord reads a business's website, a description in its own words and its price list, and builds a setup proposal: profile details, branding, taxes, product catalog, message templates and quote preferences. It's the same assistant as onboarding and **Settings**, exposed through three doors for developers: | Door | How | |---|---| | REST API | `POST /api/v1/setup/plans` and `GET /api/v1/setup/plans/{id}` | | CLI | `cord setup` (see [CLI](/en/docs/desarrolladores/herramientas/cli)) | | MCP server | The `proponer_configuracion` and `estado_configuracion` tools (see [MCP Server](/en/docs/desarrolladores/herramientas/mcp)) | None of the three doors changes the account. All of them return a `review_url`: an app page where a signed-in person with **Settings** permission reviews the proposal, can edit it, and applies or discards it. The proposal always configures the **real account** the key belongs to, even when the key is a test key. ## Propose a setup Send at least one of the three fields: | Field | Type | Detail | |---|---|---| | `sitio` | string | The business's website, for example `materialesdelvalle.mx`. Cord reads its text, colors, logo, emails and phone numbers. Up to 300 characters. | | `descripcion` | string | What the business does, how it gets paid and which taxes it charges or withholds, in its own words. Up to 4,000 characters; the rest is trimmed. | | `archivo` | object | The price list: `{ "nombre": "prices-2026.csv", "base64": "..." }`. Excel (`.xlsx`), CSV, PDF or a photo (PNG or JPG), up to **3 MB** before encoding. | ```bash curl https://cordhq.app/api/v1/setup/plans \ -H "Authorization: Bearer sk_test_..." \ -H "Content-Type: application/json" \ -d '{ "sitio": "materialesdelvalle.mx", "descripcion": "We sell building materials on 30-day credit and withhold 4% VAT on freight." }' ``` To include the price list from the terminal: ```bash curl https://cordhq.app/api/v1/setup/plans \ -H "Authorization: Bearer sk_test_..." \ -H "Content-Type: application/json" \ -d "{\"sitio\":\"materialesdelvalle.mx\",\"archivo\":{\"nombre\":\"prices.csv\",\"base64\":\"$(base64 < prices.csv | tr -d '\n')\"}}" ``` The response is `201 Created`: ```json { "data": { "object": "setup_plan", "id": "c7a2e9d1-4b6f-4f0a-8e3c-2d9b1a5f7e64", "estado": "propuesto", "review_url": "https://cordhq.app/app/setup/c7a2e9d1-4b6f-4f0a-8e3c-2d9b1a5f7e64", "resumen": "Building materials distributor with 30-day credit and VAT withholding on freight.", "conteos": { "perfil": 3, "marca": 2, "cotizaciones": 1, "impuestos": 1, "productos": 42, "plantillas": 2 }, "avisos": [], "descartado": [ { "campo": "perfil.telefono", "motivo": "No es un teléfono válido." } ] } } ``` | Field | What it is | |---|---| | `review_url` | The page where a person reviews and applies the proposal. Share it with whoever manages the account. | | `resumen` | One line with what Cord understood about the business. It's written in the account's language. | | `conteos` | How many changes each section brings. | | `avisos` | What couldn't be read, for example a website that didn't respond or a list whose columns weren't recognized. The proposal still comes out with the rest. | | `descartado` | Data the AI proposed that didn't pass Cord's validation (tax format, rates, prices). It never reaches the proposal. | Cord only proposes what the source supports: a tax ID only if it appears verbatim, a product only if it has a price, and a tax only if it isn't already in your catalog. Every value goes through the same country rules as Settings. ## Check the status ```bash curl https://cordhq.app/api/v1/setup/plans/c7a2e9d1-4b6f-4f0a-8e3c-2d9b1a5f7e64 \ -H "Authorization: Bearer sk_test_..." ``` ```json { "data": { "object": "setup_plan", "id": "c7a2e9d1-4b6f-4f0a-8e3c-2d9b1a5f7e64", "estado": "aplicado", "review_url": "https://cordhq.app/app/setup/c7a2e9d1-4b6f-4f0a-8e3c-2d9b1a5f7e64", "resultado": [ { "seccion": "perfil", "ok": true, "detalle": "6 ajustes" }, { "seccion": "impuestos", "ok": true, "detalle": "1 de 1" }, { "seccion": "productos", "ok": true, "detalle": "40 nuevos, 2 actualizados" }, { "seccion": "plantillas", "ok": true, "detalle": "2 de 2" } ], "created_at": "2026-10-07T16:20:41.512Z", "aplicado_at": "2026-10-07T16:24:03.007Z", "expira_at": "2026-10-14T16:20:41.512Z" } } ``` | `estado` | Meaning | |---|---| | `generando` | Cord is still building the proposal. | | `propuesto` | Ready and waiting for a person to review it at `review_url`. | | `aplicado` | A person applied it. `resultado` has one row per section with `ok` and `detalle`; if one section failed, the others are still applied. | | `descartado` | A person discarded it. Nothing changed. | | `fallido` | The proposal couldn't be finished, or every section failed when applying it. | `resultado` is `null` until the proposal is applied. To wait for the decision, poll every few seconds (the CLI polls every 3) and stop at `aplicado`, `descartado` or `fallido`. ## Limits | Limit | Value | |---|---| | Proposals per organization | 6 per day, adding up the API, the CLI, MCP and the app. The seventh returns `429` with `code: "rate_limited"`. | | Validity | 7 days (`expira_at`). An expired proposal can no longer be applied; generate a new one. | | File | 3 MB before base64 encoding. Larger returns `413`. | | Proposed catalog | Up to 500 products, 6 taxes and 4 templates. | ## Errors | Situation | Response | |---|---| | You didn't send `sitio`, `descripcion` or `archivo` | `400`, `code: "invalid_request"` | | The file isn't Excel, CSV, PDF or a photo, or it's empty | `400`, `code: "invalid_request"`, with the reason in `error` | | The file is larger than 3 MB | `413`, `code: "invalid_request"` | | 6 proposals were already generated today | `429`, `code: "rate_limited"` | | Cord couldn't finish the proposal | `502` with the message in `error`; the proposal is left as `fallido` | | The `id` doesn't exist in your account | `404`, `code: "not_found"` | ## Keys and permissions - Proposing requires write permission on the `setup` resource; checking status, read. A [restricted key](/en/docs/desarrolladores/esenciales/autenticacion#restricted-keys) with only `setup` is enough. The key `cord login` hands out already includes it. - The review page requires a session with **Settings** permission on that account. Nobody else can apply. - Applying is recorded in the organization's audit log with who did it. ## From the CLI ```bash npx @flouviahq/cli setup --sitio materialesdelvalle.mx --archivo prices.xlsx ``` The CLI sends the proposal, opens `review_url` in your browser and waits for your decision. Once you approve, it prints the result per section. Enter stops waiting without cancelling anything: the proposal keeps waiting for you at the link for 7 days. ## From an agent (MCP) `proponer_configuracion` takes `sitio`, `descripcion`, `archivo_base64` and `archivo_nombre` and returns the same as the API (`id`, `estado`, `review_url`, `resumen`, `conteos`, `avisos`, `descartado`). `estado_configuracion` takes the `id` and returns `estado`, `review_url`, `resultado`, `creada`, `aplicada` and `vence`. The agent must share the `review_url` with the person: it has no way to apply the proposal on its own. --- # Elements Appearance URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/apariencia Last updated: 2026-10-07 Customize Cord Elements with themes, more than twenty variables, per-component rules, layout and fonts, validated on the server. ## The Appearance API A single `appearance` object controls how the embedded quote and the native components look. It has five parts: `theme`, `variables`, `rules`, `layout` and `fonts`. **Same object, two mechanisms.** For the **iframe** (`embed.js`, ``, ``) the object travels to Cord's server, which validates it and renders the CSS inside its own origin: your page never writes styles inside the iframe. For the **native components** (`` through ``) the SDK applies the variables as CSS on your page. `rules` and `layout` only apply to the iframe; `elements` and `baseTheme` only to native components. ```html
``` With the Web Component, the same JSON goes in the `appearance` attribute or the `element.appearance` property; in React, in the `appearance` prop of ``. ## Themes (`theme`) | Theme | What it does | |---|---| | `light` | Default. | | `dark` | Full dark palette: background, surfaces, text, borders and fields. `night` is an alias. | | `auto` | Follows the visitor's `prefers-color-scheme`. | | `flat` | No shadow and visible borders, for sites that don't use elevation. | The theme is applied first, and your `variables` always win over it. ## Variables (`variables`) Written in `camelCase`. Each one reaches a real surface of the quote; a variable you don't set keeps Cord's value. | Variable | Type | Where it shows | |---|---|---| | `colorPrimary` | color | Primary button, accents, your own chat bubbles | | `colorOnPrimary` | color | Text on the primary color | | `colorBackground` | color | Card background | | `colorSurface` | color | Inner panels: notes, total, chat, notices | | `colorText` | color | Main text and amounts | | `colorTextSecondary` | color | Labels, tax ID, notes | | `colorTextPlaceholder` | color | Table headers, hints, placeholders | | `colorBorder` | color | Dividers and borders | | `colorDanger` | color | Reject and errors | | `colorSuccess` | color | Confirmations | | `colorInput` | color | Field background | | `colorInputText` | color | Field text | | `colorInputBorder` | color | Field border | | `colorFocus` | color | Focused field border | | `fontFamily` | family | The whole card | | `fontSize` | length | Line items | | `fontWeightBold` | weight | Buttons | | `borderRadius` | length | Card | | `borderRadiusButton` | length | Buttons | | `borderRadiusInput` | length | Fields | | `spacingCard` | spacing | Card padding (`2rem` or `1.5rem 2rem`) | | `shadowCard` | `none` or `default` | Card shadow | A **color** accepts hex, `rgb()`, `hsl()`, `oklch()`, `oklab()`, `lab()`, `lch()` or a name. A **length** accepts `px`, `rem`, `em` or `%`. ## Per-component rules (`rules`) When variables aren't enough, `rules` applies properties to components with public names. They are not CSS selectors: they are stable names Cord maps to its markup, so they don't break when the markup changes. ```json "rules": { "Button": { "text-transform": "uppercase" }, "Button:hover": { "opacity": "0.9" }, "Input:focus": { "border-color": "#0f766e" }, "Bubble--mine": { "background-color": "#0f766e" } } ``` **Components:** `Card`, `Header`, `Total`, `Table`, `Row`, `SummaryRow`, `Notes`, `Button`, `Button:hover`, `ButtonSecondary`, `ButtonSecondary:hover`, `Input`, `Input:focus`, `Chat`, `Bubble`, `Bubble--mine`. **Properties:** `color`, `background-color`, `border-color`, `border-width`, `border-style`, `border-radius`, `font-size`, `font-weight`, `letter-spacing`, `text-transform`, `padding`, `box-shadow` (`none` or `default`) and `opacity`. ## Layout (`layout`) | Option | Effect | |---|---| | `compact: true` | Less whitespace in the card, for narrow columns. | | `hideChat: true` | Hides the conversation and per-line comments. | | `hideNotes: true` | Hides the quote's notes block. | Hiding is presentation only: the quote and its actions are the same on the public link. ## Fonts (`fonts`) Up to four stylesheets from `fonts.googleapis.com` or `fonts.bunny.net` over `https`. If you don't set `fontFamily`, Cord uses the first family of the first stylesheet. ## What Cord validates and why Every value that ends up as CSS goes through a validator with closed lists of keys, components and properties, and a grammar per value type. `url()`, `expression()`, `@`, `!important`, `;`, braces and `<` are dropped, and the whole object is ignored above 8 KB. Dropped values don't break the rest: they are ignored, the SDK warns about them in the console during development, and they show up in the [debug bar](/en/docs/desarrolladores/herramientas/elements/eventos#debug-bar) with a test key. This keeps appearance from being used to hide buttons, cover the total or load third-party resources inside the iframe: the design is yours, the integrity of the quote is Cord's. ## Native components ### Headless mode (`baseTheme: 'none'`) With `` or `useQuoteBuilder` and your own UI, `appearance={{ baseTheme: 'none' }}` on `` turns off the base stylesheet. The `.cord-*` classes stay in the markup and the look is up to you (Tailwind, CSS Modules or whatever you use). ### Per-element overrides (`elements`) Every node of `` carries a stable `.cord-` class (`builderRoot`, `formField`, `itemRow`, `summaryRoot`, `submitButton`...). `appearance.elements` adds your `className` and `style`: ```tsx ``` The base `.cord-` class is never replaced; yours is added on top. --- # Elements Events URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/eventos Last updated: 2026-10-11 Learn how to listen to client actions inside the iframe to build dynamic experiences. ## The Message Bridge The Cord Elements iframe is designed to never isolate your website from what happens inside it. Using a bidirectional bridge via `window.postMessage`, Cord "relays" card events directly to your parent `window` environment. This is incredibly powerful for triggering analytics pixels (like Meta Pixel or Google Analytics), launching confetti animations when a proposal is approved, or redirecting the user to a "Thank You" page after a successful payment. ## Listening to Events You can listen to events natively by attaching an `addEventListener` to the DOM node of the embedded element: ```javascript const container = document.querySelector('[data-cord-token]'); container.addEventListener('cord:approved', (event) => { console.log('The quote was approved!'); console.log('Approved by:', event.detail.signed_by); }); ``` ## Events Dictionary All events have the `cord:` prefix to avoid naming collisions with other libraries. Every event's `detail` always includes `token` (the quote's public token) and `folio` (e.g. `"COT-0148"`), in addition to the event-specific fields listed below. ### Component lifecycle - **`cord:ready`**: Fired at the exact moment the SDK finishes rendering content, calculating final height, and loading fonts. - **`cord:resize`**: Emitted continuously every time the iframe height changes (useful only if you write your own container and don't use `embed.js`). - **`cord:viewed`**: Fired together with `cord:ready`, as soon as the quote finishes rendering inside the iframe — it's the signal that the content is now visible to your host page. The official database record of the client viewing the quote runs through a separate internal mechanism that requires the tab to actually be visible (so the seller previewing their own link never counts as a "view"); don't assume the two happen at the same instant. ### Commercial interaction - **`cord:approved`**: Emitted the instant the user approves the terms of the commercial proposal. Returns useful data in the `detail` such as the validation hash and who signed (`signed_by`). - **`cord:signed`**: Fired at the SAME instant as `cord:approved`, with the same `detail` (`signed_by`, `hash`) — in Cord, approving and signing are a single client action, not two separate steps in time. Listen to whichever is more semantically clear for your code; don't expect one to arrive "after" the other. - **`cord:pay`**: Emitted when the user clicks the button to start their online payment flow (card, bank transfer, or the other methods the business has enabled). The `detail` carries the absolute `url` of the payment page. Cord already opens it in its own window (payment never runs inside the iframe): don't navigate your page to that URL, use it only for your analytics. - **`cord:rejected`**: Fired if the client explicitly marks the proposal as declined. The `detail` includes the `comentario` they left, if any. - **`cord:message`**: Triggered whenever the client leaves a general comment or counter-offer in the quote chat. - **`cord:item_comment`**: Fired when the user leaves a specific comment on an item (product line) of the quote, with the corresponding `item_id` in the `detail`. ### State - **`cord:updated`**: The quote changed while it was open (the seller edited lines, amounts or terms). The quote has already redrawn itself; use it to refresh whatever your page shows around it. - **`cord:status_changed`**: The status changed (`sent`, `viewed`, `approved`, `rejected`, `paid`, `expired`...). The `detail` carries the new `status` (and `saldo` on the invoice). - **`cord:paid`**: Only on ``: the invoice was settled. The `detail` carries `folio`, `moneda` and `saldo`. `cord:ready` also carries `status`, `moneda` and `total`, so your page can draw its own summary without another call. ## Read-only mode If your organization has no allowed domains in **Settings › Embeddable quote builder**, or the host page is not on that list, the quote renders **read-only**: it doesn't offer approve, sign, pay or chat, and its button opens the quote's public link in a new tab. In that mode events arrive **without `detail`**: a page that isn't on your list doesn't receive who signed, amounts or the payment URL. ## Debug bar With `debug` on, Elements draws a panel on your site with the iframe's events, every API request with its `request_id` and configuration warnings (for example, `appearance` values Cord dropped). ```html
``` In React, ``. The panel only shows with a `pk_test_` key; with `pk_live_` it is limited to a console warning. Without a key (Web Component or `embed.js`), it only shows on `localhost` or when the URL has `?cord_debug=1`, so a forgotten attribute never shows it to your customers. --- # Tax form (Fiscal Element) URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/fiscal Last updated: 2026-10-07 Capture RFC, tax regime, CFDI use and postal code (or NIF and EIN) with , CordFiscalForm, useCordFiscalForm or , with the same validation Cord applies when issuing. The Fiscal Element captures the **recipient's** tax details: who gets invoiced. It validates in the browser with the same code Cord's server uses before saving, so what the form accepts is exactly what Cord accepts. An RFC with a mistyped check digit is caught as it's typed, not days later when stamping rejects it. ## Which fields it asks for and what it validates | Country | Fields | Rules | |---|---|---| | Mexico (`MX`) | RFC, legal name, tax regime, CFDI use, tax postal code | RFC shape, date and check digit. The RFC type (12 characters, legal entity; 13, individual) filters the applicable regimes and uses. `XAXX010101000` and `XEXX010101000` (general public and foreigners) set regime `616` and use `S01`. A warning if a legal entity's name includes the corporate suffix ("S.A. de C.V."). 5-digit postal code. | | Spain (`ES`) | NIF / CIF, legal name, postal code | NIF and NIE control letter, and CIF control digit. 5-digit postal code. | | United States (`US`) | EIN, legal name, ZIP | Valid EIN. ZIP of 5 digits or `12345-6789`. | | Other country | Tax ID, name | Only presence is checked, with an `unsupported_country` warning. | Regimes in the catalog: `601`, `603`, `605`, `606`, `612`, `616`, `620`, `621` and `626`. CFDI uses: `G01`, `G03`, `I01`, `I02`, `I04`, `I08`, `S01` and `CP01`. When valid, the result is the normalized recipient: ```json { "country": "MX", "tax_id": "EKU9003173C9", "legal_name": "ESCUELA KEMPER URGATE", "regimen_fiscal": "601", "uso_cfdi": "G03", "cp_fiscal": "42501" } ``` Outside Mexico, `regimen_fiscal` and `uso_cfdi` come back `null`. ## Web Component: `` Importing `@flouviahq/elements` registers `` along with `` and ``. ```html
``` It's a **form-associated** element: inside a ``, it contributes its value under its `name` attribute (the normalized recipient as JSON) and blocks submission while there are errors, just like an ``. The browser shows the first error next to the field that causes it. In Safari before 16.4, which lacks that API, the form works but doesn't take part in submission: read `value` yourself. | Attribute | Values | |---|---| | `country` | `MX` (default), `ES`, `US` or another ISO code. Changing it keeps what's already typed. | | `lang` | `es`, `en`, `pt`, `fr` or `de`; any other value falls back to `en`. Without it, your page's `lang`. | | `name` | The name under which it contributes its value to the form. | | Property or method | What it does | |---|---| | `value` | The normalized recipient if valid; otherwise `null`. | | `state` | The full state: values, touched fields, visible errors, available regimes and uses. | | `setValues(data)` | Loads initial values, for example from a saved client. | | `submit()` | Shows every error and returns the recipient if valid, or `null`. | ```html ``` | Event | `detail` | |---|---| | `fiscalchange` | The full state, on every change. | | `fiscalvalid` | The normalized recipient, every time it becomes valid. | Errors only show on fields the person has already touched, or on all of them after `submit()`. ### Styling The form lives in a Shadow DOM. Customize it with parts and variables: ```css cord-fiscal-form::part(label) { font-weight: 500; } cord-fiscal-form::part(input) { min-height: 48px; } cord-fiscal-form::part(error) { font-size: 13px; } cord-fiscal-form { --cord-color-primary: #0a192f; --cord-border-radius: 10px; } ``` | Part | Element | |---|---| | `field` | Each field's container. | | `label` | The label. | | `input` | The text field or the select. | | `error` | A field's error message. | | `warning` | A field's warning (for example, the corporate suffix in the legal name). | Variables: `--cord-font-family`, `--cord-color-text`, `--cord-color-text-secondary`, `--cord-color-input`, `--cord-color-primary`, `--cord-color-danger` and `--cord-border-radius`. ## React: `` and `` ```tsx import { CordFiscalForm } from '@flouviahq/elements/react'; export function TaxDetails({ onReady }: { onReady: (recipient: unknown) => void }) { return ( ); } ``` | Prop | Detail | |---|---| | `country` | `MX` by default. | | `initial` | Initial values. | | `locale` | `es`, `en`, `pt`, `fr` or `de`. | | `title` | Section heading. | | `onValid` | Called with the normalized recipient every time it becomes valid. | | `className`, `style` | For the container. | Inside the Builder, `fiscal` adds the section and the recipient travels with the quote: ```tsx ``` The country comes from your organization's tax configuration. If the recipient isn't valid, the Builder doesn't submit and flags the fields with errors. To control the state yourself, `useFiscalForm()` returns the same state as the component. ## Vue: `useCordFiscalForm` ```vue ``` `state` is a `ShallowRef` with the form's state; `form` is the headless form (`set`, `touch`, `submit`). To render each error's text, use `fiscalText()` from [`@flouviahq/elements/headless`](/en/docs/desarrolladores/herramientas/elements/headless). ## Validation codes | Code | Meaning | |---|---| | `required` | The value is missing. | | `too_long` | Over the maximum (20 characters for the ID, 300 for the name). | | `invalid_tax_id` | The tax ID isn't valid for the country. | | `invalid_postal_code` | The postal code doesn't match the country's format. | | `regimen_not_for_persona` | The regime doesn't match the RFC type. | | `uso_not_for_persona` | The CFDI use doesn't match the RFC type. | | `generic_requires_616_s01` | A generic RFC requires regime `616` and use `S01`. | | `legal_name_has_regime_suffix` | Warning: the legal name includes the corporate suffix. | | `unsupported_country` | Warning: for that country only presence is checked. | ## On the server side - `POST /api/v1/cotizaciones` accepts the recipient in `cliente.fiscal`. If it isn't valid, it returns `400` with `code: "invalid_fiscal_data"` and the list in `issues`: ```json { "error": "Los datos fiscales del cliente no son válidos.", "code": "invalid_fiscal_data", "issues": [{ "field": "tax_id", "code": "invalid_tax_id" }] } ``` - `@flouviahq/node` exports `validateFiscalReceptor()`, `validRfc()`, `validSpainTaxId()` and `validEin()`, to validate on your server with the same code. - The [MCP server](/en/docs/desarrolladores/herramientas/mcp) has the `validar_datos_fiscales` tool. --- # Headless Elements URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/headless Last updated: 2026-10-07 Build your own interface on top of the Cord Elements core: an HTTP client with idempotency and ETag caching, a quote builder with the server's totals and a tax form, with no framework. `@flouviahq/elements/headless` is the core of Cord Elements. ``, the React and Vue hooks and the Web Components all consume this same core. Importing it doesn't register elements or touch the DOM: only state, validation and network. Use it when you want your own interface, in any framework or none. ```bash npm install @flouviahq/elements ``` ```ts import { createCordClient, createQuoteBuilder, createFiscalForm } from '@flouviahq/elements/headless'; ``` | Exports | What for | |---|---| | `createCordClient` | Browser HTTP client to Cord or to your proxy. | | `createQuoteBuilder` | The full state of building a quote: client, lines, taxes, totals, submission. | | `createFiscalForm` | The state of the recipient's [tax form](/en/docs/desarrolladores/herramientas/elements/fiscal). | | `createStore` | The observable store all three use (`get`, `subscribe`, `set`). | | `reduceQuoteView`, `INITIAL_QUOTE_VIEW` | The reducer for an embedded quote's live state. | | `calculateDocumentTotals`, `roundMoney` | The totals engine the server uses. | | `validateFiscalReceptor`, `validRfc`, `validSpainTaxId`, `validEin`, `fiscalText` | Tax validation and its texts in Spanish, English, Portuguese, French and German. | | `sanitizeAppearance`, `appearanceToCss` | The [Appearance API](/en/docs/desarrolladores/herramientas/elements/apariencia) validator. | | `CordError` | The typed error, with `code` and `requestId`. | ## `createCordClient` ```ts const client = createCordClient({ publishableKey: 'pk_test_...' }); // or, with your backend in between: const viaProxy = createCordClient({ proxyUrl: '/api/cord' }); ``` Pass **one** of the two: `publishableKey` (a `pk_` key, which can only use the Elements routes) or `proxyUrl` (the base of your [server proxy](/en/docs/desarrolladores/herramientas/elements/server), shaped like `/api/v1`). With both, or with an `sk_` key, it throws. | Option | Default | Detail | |---|---|---| | `publishableKey` | — | A `pk_live_` or `pk_test_` key. | | `proxyUrl` | — | For example `/api/cord`. Requests go with your site's cookies. | | `baseUrl` | `https://cordhq.app` | Cord's origin in publishable mode. | | `timeoutMs` | `15000` | Cuts each attempt off. | | `maxRetries` | `2` (max 5) | Retries on network failure, `429` and `5xx`, respecting `Retry-After`. | | `debug` | `false` | Logs every request with its `request_id` to the console. | | `fetch` | global `fetch` | For tests. | | Method | What it does | |---|---| | `config({ force? })` | `GET /elements/config`: your organization's currencies, country taxes, terms and validity. It's cached with its `ETag` and the next call sends `If-None-Match`: if nothing changed, Cord answers `304` and the copy is used. `force: true` requests it in full. | | `products()` | `GET /productos`: the catalog, without costs. | | `createQuote(input, { idempotencyKey? })` | `POST /cotizaciones` with an `Idempotency-Key` (yours or a new UUID). | | `aiDraft(input, onItem, { signal? })` | `POST /elements/ai-draft`: fills lines with AI from text (`texto`, up to 4,000 characters) or a file (`archivo`, JPG, PNG or PDF up to 4 MB). Calls `onItem` for each line as soon as it's read. | ```ts const config = await client.config(); console.log(config.org.moneda, config.impuestos.etiqueta, config.monedas); ``` ## `createQuoteBuilder` ```ts const builder = createQuoteBuilder({ client, onCreated: (quote) => console.log(quote.folio, quote.link_publico), }); const unsubscribe = builder.subscribe((state) => render(state)); builder.setCliente({ empresa: 'Acme', email: 'purchasing@acme.com' }); const key = builder.addItem({ descripcion: 'Installation', cantidad: 1, precio_unitario: 12500 }); builder.updateItem(key, { cantidad: 2 }); const quote = await builder.submit(); // null if there are errors or it failed ``` On creation, the builder loads the configuration and catalog on its own (`status` goes from `loading` to `ready`). Every change recomputes totals with the same engine as the server, and each line's rate comes from the organization's real tax catalog. | Method | What it does | |---|---| | `setCliente(patch)` | `empresa`, `email`, `contacto`, `telefono`. | | `setFiscal(recipient \| null)` | The tax recipient that travels with the quote. | | `setMoneda(code)`, `setTerminos(t)`, `setVigencia(days)`, `setNotas(text)`, `setPreciosIncluyenImpuesto(bool)` | The quote's conditions. | | `addItem(item?)` | Adds a line and returns its `key`. Without `tax_rate`, it uses the default rate. | | `addProduct(product, quantity?)` | Adds a catalog product. | | `updateItem(key, patch)`, `removeItem(key)` | Edits or removes a line by its `key`. | | `searchProducts(text, limit?)` | Searches the loaded catalog by name or SKU. | | `validate()` | Returns and stores the `issues`. | | `submit()` | Validates, creates the quote and returns the response, or `null`. | | `draftWithAi(input, { signal? })` | Fills lines with AI; each proposed line carries `sugerida`. | | `reset()`, `load()` | Empties the quote, or reloads configuration and catalog. | `submit()` uses **a single** `Idempotency-Key` per submission attempt: a double click or a network retry never creates two quotes. The key is renewed as soon as you change anything. The state (`builder.get()`) carries: | Field | Content | |---|---| | `status` | `loading`, `ready`, `submitting`, `success` or `error`. | | `config`, `products` | What it loaded from Cord. | | `cliente`, `fiscal`, `moneda`, `terminos`, `vigencia_dias`, `notas`, `precios_incluyen_impuesto` | What the person entered. | | `items` | The lines, each with its `key`. | | `totals` | `subtotal`, `impuestos`, `retencionTotal`, `total`, the breakdown by rate (`porTasa`), the `retenciones` and the computed `lineas`. | | `issues` | `{ field, code }` for each problem, for example `{ field: 'items', code: 'no_items' }`. | | `result`, `error` | The created quote, or the `CordError` from the last attempt. | | `ai` | `status`, `count` and `error` of the AI fill. | For your analytics, `onEvent(event, data)` receives `builder.loaded`, `builder.item_added`, `builder.item_removed`, `builder.submitted`, `builder.created`, `builder.failed` and `builder.ai_drafted`. The names are stable across versions. ## `createFiscalForm` ```ts const fiscal = createFiscalForm({ country: 'MX' }); fiscal.subscribe((s) => { console.log(s.visibleErrors, s.regimenes.map((r) => r.codigo)); }); fiscal.set('tax_id', 'EKU9003173C9'); fiscal.touch('tax_id'); const recipient = fiscal.submit(); // the normalized recipient, or null builder.setFiscal(recipient); ``` The state carries `values`, `touched`, `validation` (with `ok`, `value`, `errors`, `warnings` and `persona`), `visibleErrors`, the `regimenes` and `usosCfdi` that apply to the RFC type, and the country's `fields`. The rules are in [Tax form](/en/docs/desarrolladores/herramientas/elements/fiscal). ## With your framework The store follows the `get()` + `subscribe()` contract, so it plugs into any reactive system: ```tsx import { useSyncExternalStore } from 'react'; function useBuilderState(builder) { return useSyncExternalStore(builder.subscribe, builder.get, builder.get); } ``` ```ts import { useCordQuoteBuilder, useCordStore } from '@flouviahq/elements/vue'; // useCordStore(store) returns a ShallowRef that follows the store. ``` ```ts const total = document.querySelector('#total'); builder.subscribe((s) => { total.textContent = new Intl.NumberFormat(s.config?.org.locale ?? 'en', { style: 'currency', currency: s.moneda || 'USD', }).format(s.totals.total); }); ``` ## Live state of an embedded quote `reduceQuoteView(state, event)` turns the events relayed by ``'s iframe into a state (`ready`, `status`, `folio`, `moneda`, `total`, `approved`, `rejected`, `paid`, `signedBy`, `lastEvent`). It's what's behind the Web Component's `state` property and `statechange` event; see [Web Components](/en/docs/desarrolladores/herramientas/elements/web-components#live-state-state-and-statechange). --- # Elements in React and Next.js URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/react Last updated: 2026-10-07 Learn how to integrate the Cord SDK into React ecosystems using Components and Hooks. ## Installation Make sure you have installed the package in your project. ```bash npm install @flouviahq/elements ``` ## The Provider: `` To use any React component or hook provided by the SDK, your application (or the portion of your app that uses the quoter) must be wrapped in a `CordProvider`. There are two security modes to initialize the provider: **Publishable** and **Proxy**. These modes are mutually exclusive; you cannot pass both properties at the same time. ### Publishable Mode (Direct frontend) Use this mode if you want the React client to communicate directly with the Cord API. Publishable Keys (`pk_live_...` / `pk_test_...`) are highly restricted for security: they can create quotes and read the product catalog (omitting your cost), but they will **never** be able to read your CRM clients directory. ```tsx // app/layout.tsx import { CordProvider } from '@flouviahq/elements/react'; export default function Layout({ children }) { return ( {children} ); } ``` ### Proxy Mode (Backend intermediary) Use this mode if you do not want to expose any key in your client or if you need functionalities that require secret keys (like reading the CRM). The SDK will send requests to the proxy route you indicate, and your backend will be responsible for forwarding them to the Cord API using the Secret Key (`sk_live_...`). ```tsx {children} ``` --- ## ``: Iframe Viewer If you already have a quote `token` and just want to display it for the client to approve and pay, use the native viewer. This component renders an injected iframe under your brand securely. **Important:** `` is the only component that **does not require** being inside a `CordProvider`, as the quote token provides its own authentication context. ```tsx import { CordCotizador } from '@flouviahq/elements/react'; function QuotePage({ token }: { token: string }) { return ( console.log('Approved by', detail.signed_by)} onPay={(detail) => console.log('Payment opened at', detail.url)} /> ); } ``` ### `` The same for an invoice (`/i/{token}`). It takes the same props and adds `onPaid`: ```tsx import { CordInvoice } from '@flouviahq/elements/react'; console.log('Paid', d.folio)} /> ``` In Vue, `CordInvoice` from `@flouviahq/elements/vue` emits `paid`. --- ## ``: Quote Creator (Compound) If you want to build an interface to assemble new quotes and take advantage of the SDK's standardized interface, use the `CordBuilder`. It utilizes a compound components pattern, so you can reorder or omit parts of the form. ```tsx import { CordBuilder } from '@flouviahq/elements/react'; function NewQuote() { return ( console.log('Created:', q.folio)}> ); } ``` The components inject stable CSS classes (`.cord-*`) to facilitate modification. However, Cord never applies *inline styles*, ensuring your custom CSS (like Tailwind or CSS Modules) always takes precedence without having to use `!important`. --- ## `useQuoteBuilder`: Headless UI If `` doesn't adapt to the exact design needs of your interface, you can extract the entire state engine using the `useQuoteBuilder` hook and render the buttons, inputs, and tables entirely on your own. ```tsx import { useQuoteBuilder } from '@flouviahq/elements/react'; function MyOwnBuilder() { const { items, updateItem, removeItem, subtotal, iva, total, cliente, setCliente, notas, setNotas, handleSubmit, isLoading } = useQuoteBuilder({ catalog: myLocalProducts, onQuoteCreated: (q) => console.log('Link:', q.link_publico), }); return (
{/* Build the interface 100% yours using Cord's state */}

Total: ${total}

); } ``` **`ivaPct` is required, not an optional tweak.** The SDK no longer silently assumes 16% (Mexico) if you don't set it — `useQuoteBuilder` (and therefore ``) **throws** as soon as it mounts if it can't find an explicit rate, whether by prop or via ``. Set it once, globally — `` — instead of repeating it on every Builder instance: that way the total your client sees never drifts from what the server validates for your organization. A business outside Mexico must pass ITS OWN rate (or `0` if its sale carries no tax) — never assume 0.16 by default. --- # Cord Elements URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/resumen Last updated: 2026-10-07 Embed interactive quoting components directly into your web app using the official SDK. ## What are Elements? Cord Elements is the official SDK (`@flouviahq/elements`) that allows you to integrate the entire Cord commercial interaction experience directly into your own corporate web portal. Instead of sending the client to `cordhq.app`, your clients can view quotes, negotiate in the internal chat, approve and sign documents, or pay invoices without leaving your brand. Everything happens securely under your own domains. ## Integration Methods Depending on your tech stack, Cord offers three ways to consume Elements: ### 1. The NPM SDK (Recommended) For modern applications built in React, Next.js, Vue, or Nuxt, you can install the official NPM package. This package provides native components, headless hooks (`useQuoteBuilder`), and full TypeScript types. **Installation:** ```bash npm install @flouviahq/elements ``` Explore our specific guides: - **[React and Next.js Guide](/en/docs/desarrolladores/herramientas/elements/react)** - **[Web Components and Vue Guide](/en/docs/desarrolladores/herramientas/elements/web-components)** - **[Headless: your own interface](/en/docs/desarrolladores/herramientas/elements/headless)** - **[Tax form](/en/docs/desarrolladores/herramientas/elements/fiscal)** - **[Server proxy](/en/docs/desarrolladores/herramientas/elements/server)** ### 2. Script Tag (embed.js) For sites without bundlers, WordPress, or legacy architectures, you can load the environment using a single script tag and define `data-` attributes in your HTML. ```html
``` This script dynamically injects an iframe and automatically adjusts its height to avoid double scrollbars. ### 3. Framer and Webflow The SDK also exports specific wrappers ready to be pasted as *Code Components* in modern visual editors. Check the Web Components documentation for more details. ## Security Architecture Cord Elements uses bank-grade security. By default, your publishable key (`pk_live_...`) exposed on the frontend will **never** be able to read your clients directory (to prevent CRM data leaks). If you want advanced features, you can operate the SDK through a backend proxy. Explore the **[CSP Security](/en/docs/desarrolladores/herramientas/elements/seguridad)** section to configure your allowed domains (allowlist) and prevent Clickjacking attacks. --- # Elements CSP Security URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/seguridad Last updated: 2026-10-07 Allowed domains, read-only mode and key rules that protect Cord Elements from clickjacking. ## The Clickjacking Threat If any webpage on the Internet could simply create an `` pointing to your clients' private quotes, an attacker could build a fake overlaid page (UI Redressing or Clickjacking) and trick a client into clicking a fake payment button that actually clicks the accept button inside your invisible quote. Because of this, **Cord Elements' security is strict from day one.** ## Frame Ancestors and the Allowlist Cord mitigates this vulnerability through native HTTP headers known as Content Security Policy (CSP). Specifically, we use the `frame-ancestors` directive. For the Elements installation snippet to work on your corporate website, you must first register your origins in the dashboard. 1. Go to **Settings › Embeddable quote builder**, in the **Developers** section of the index (it shows up with **Developer mode** on in **Your account › Preferences**). 2. Look for the **Authorized domains** step. 3. Add the domains separated by line breaks. ### Valid examples The domain system allows strict origins or the use of wildcards: - `your-company.com` (Authorizes only the root). - `*.your-company.com` (Authorizes the root and any subdomain, like `app.your-company.com`). - `https://portal.your-company.com` (Highly specific). ## No domains: read-only If the domain list is empty, any site can embed the quote, but **only to display it**. Approving, signing and paying are not offered inside the iframe: instead, a button opens the proposal in a new tab on Cord's domain, where no third-party site can overlay anything. Events are sent without `detail` (no signer name, no payment URL). With at least one domain registered, `frame-ancestors` restricts every ancestor of the iframe and the quote is interactive. ## Events only reach your origin The SDK appends the `parentOrigin` parameter (your page's `window.location.origin`) to the iframe URL. If it matches your list, `window.postMessage` targets events **only at that origin**. Without a match, the iframe is still protected by `frame-ancestors`: only a page on your domains can be in the frame chain. ## Payment never runs inside the iframe The payment page can never be framed. When paying from an embed, Cord opens it in its own window and the `cord:pay` event carries its absolute URL. Card data never passes through a document that your site, or anyone else's, could cover. ## Keys - **Publishable Key (`pk_live_`)**: only works once allowed domains are configured. Without them, the API responds `origin_allowlist_required`. `pk_test_` keys work from any origin, including `localhost`. - **Secret Key (`sk_`)**: never in a browser. If one arrives from a browser, the API responds `secret_key_in_browser` and you should revoke it: it is already exposed in the page source. `@flouviahq/node` also refuses to run in a browser. --- # Server proxy URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/server Last updated: 2026-10-07 Use Cord Elements without a publishable key: your backend serves proxyUrl mode with createElementsProxy from @flouviahq/node, with a restricted key and only from your origin. Cord Elements works in two ways: with a publishable key (`pk_`) straight to Cord, or with `proxyUrl`, where your own backend serves the requests and calls Cord with a server key. Use the proxy when you want the Builder to read your client directory, email the quote or set negotiated prices: things a `pk_` key can never do. The proxy lives in [`@flouviahq/node`](/en/docs/desarrolladores/herramientas/sdks), the server SDK. That package replaces the old `@flouviahq/elements/server`, which still works but no longer receives changes. ## Mount it ```bash npm install @flouviahq/node ``` ```ts // app/api/cord/[...path]/route.ts (Next.js App Router) import { createElementsProxy } from '@flouviahq/node'; const proxy = createElementsProxy({ secretKey: process.env.CORD_SECRET_KEY!, authorizeClients: async (req) => Boolean(await getSession(req)), }); export const GET = proxy; export const POST = proxy; ``` ```tsx ``` `getSession` is your own session function. `createElementsProxy` returns a `(Request) => Promise` handler, so it works the same in Next.js, Astro, Remix, Hono, Bun or Cloudflare Workers. `cord init` creates it for you in a Next.js project. ## What it serves | Browser request | Calls Cord | Condition | |---|---|---| | `GET {proxyUrl}/elements/config` | `GET /api/v1/elements/config` | Always. | | `GET {proxyUrl}/productos` | `GET /api/v1/productos` | Always. | | `POST {proxyUrl}/cotizaciones` | `POST /api/v1/cotizaciones` | Always, with the body sanitized. | | `POST {proxyUrl}/elements/ai-draft` | `POST /api/v1/elements/ai-draft` | Always. The AI stream is forwarded as is; files up to 4 MB. | | `GET {proxyUrl}/clientes` | `GET /api/v1/clientes?limit=200` | Only if `authorizeClients` returns `true`. Otherwise `403` with `code: "clients_require_proxy"`. | Any other route or method returns `404`. The proxy doesn't retry: the browser already retries on its own. ## Options | Option | Detail | |---|---| | `secretKey` | **Required.** An `sk_` or `rk_` key. | | `allowedOrigins` | Origins allowed to use the proxy. By default, only the request's own origin: a proxy open to any site is the same as publishing your key. | | `authorizeClients(request)` | Authorizes reading the client directory. Without it, it's never read. | | `authorizeSellerFields(request)` | Authorizes seller fields on creation: `cliente_id`, `send` (email it), `fiscal_currency`, and on each line `precio_negociado` and `costo_unitario`. Without it, they're dropped and the quote is created as a draft, just like with a `pk_` key. | | `baseUrl` | Cord's origin. Default `https://cordhq.app`. | | `fetch` | For tests. | ```ts const proxy = createElementsProxy({ secretKey: process.env.CORD_PROXY_KEY!, allowedOrigins: ['https://portal.yourcompany.com'], authorizeClients: async (req) => (await getSession(req))?.role === 'seller', authorizeSellerFields: async (req) => (await getSession(req))?.role === 'seller', }); ``` The proxy forwards the browser's `Idempotency-Key` (the Builder sends one per submission attempt), and returns Cord's errors with their `code`, `request_id` and `doc_url`. ## Give the proxy a restricted key The proxy doesn't need a Secret Key with every permission. Create a **restricted key** (`rk_`) in **Developers › API keys** with only this: | Resource | Level | What for | |---|---|---| | `elements` | write | Configuration and AI line filling | | `productos` | read | The Builder's catalog | | `cotizaciones` | write | Creating the quote | | `clientes` | read | Only if you use `authorizeClients` | If your server is compromised, that key can't read invoices, collections or webhooks. You can also pin your server's IPs and set an expiration. See [Authentication](/en/docs/desarrolladores/esenciales/autenticacion#restricted-keys). ## Debugging Every call from the proxy to Cord shows up in the Workbench's **Developers › Logs** with its `request_id`, method, route, status, duration and IP. The same `request_id` reaches the browser in the `Cord-Request-Id` header and in an error's body. --- # Elements in Vue and Web Components URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/elements/web-components Last updated: 2026-10-07 Discover how to use Cord's native web components in Vue, pure HTML, PHP, or any other stack. ## Web Component (Vanilla JS, PHP, Rails) If you don't use React or Vue, or you are integrating Cord into a server-rendered site (like Laravel, Django, or WordPress), you can use the standard Web Component `` (`` still works as an alias). This component is compiled under web platform standards, meaning the browser understands it natively without the need for a bundler. ```html
``` **Events Note:** When using the native Web Component, events arrive **without** the `cord:` prefix. That is, instead of listening to `cord:approved`, you will simply listen to `approved` like any other DOM API event. ## The invoice: `` `` shows a Cord invoice (the one at `/i/{token}`) on your site: balance due, status, line items, totals and the PDF download. The token is the hosted invoice's, the same one in the email your customer receives. ```html ``` The pay button opens the hosted invoice in a Cord window: payment details are never captured inside the iframe. While the invoice is open, the embed checks its balance and emits `status_changed` when it changes and `paid` when it's settled. With `embed.js`, add `data-cord-document="invoice"` to the `div`. As with the quote, without allowed domains in **Settings › Embeddable quote builder** events arrive without data. `theme`, `variables` and `fonts` from the [Appearance API](/en/docs/desarrolladores/herramientas/elements/apariencia) apply to the invoice; `rules` and `layout` are for the quote. ## Live state: `state` and `statechange` `` and `` reduce the iframe's events to a state you can read at any time through the `state` property, and they emit `statechange` whenever it changes. That way you draw your own summary without listening event by event. ```html

``` | Field | Content | |---|---| | `ready` | The quote finished rendering. | | `status` | `sent`, `viewed`, `approved`, `rejected`, `paid`, `expired`… | | `folio`, `moneda`, `total` | From the document. The total always travels with its currency. | | `approved`, `rejected`, `paid` | Boolean shortcuts. `paid` is also true for a quote that was already invoiced. | | `signedBy` | Who approved, if they approved in this session. | | `lastEvent` | The last event received, for example `cord:approved`. | Without allowed domains in **Settings › Embeddable quote builder**, events arrive without data and `status`, `folio`, `moneda` and `total` stay `null`. In React it's `onStateChange` on ``; in Vue, the `@state` event. ## Styling: `::part` Both elements live in a Shadow DOM: your styles don't break them and theirs don't touch your page. To customize them from the outside: ```css cord-quote::part(frame) { border-radius: 24px; box-shadow: 0 12px 40px rgba(10, 25, 47, 0.08); } cord-quote::part(skeleton) { border-radius: 24px; } ``` | Part | Element | |---|---| | `root` | The element's container. | | `skeleton` | The loading placeholder shown while the document arrives. | | `frame` | The `` with Cord's document. | The content inside the iframe is customized with the [Appearance API](/en/docs/desarrolladores/herramientas/elements/apariencia) (the `appearance` attribute as JSON, or the `appearance` property as an object), not with your page's CSS. | Attribute | Detail | |---|---| | `token` | **Required.** The document's public token. | | `appearance` | Appearance as JSON. | | `min-height` | Minimum iframe height in pixels (420 by default). | | `base-url` | Cord's origin, if you use a custom domain. | | `debug` | Turns on the debug bar (see [Events](/en/docs/desarrolladores/herramientas/elements/eventos)). | ## Tax form `` captures your client's tax details with the same validation Cord uses and plugs into your HTML forms. See [Tax form](/en/docs/desarrolladores/herramientas/elements/fiscal). ## Vue and Nuxt The Cord SDK provides a native wrapper for Vue 3 that handles reactivity and events using the Vue paradigm (`@` or `v-on`). ### Installation ```bash npm install @flouviahq/elements ``` ### Usage Import the `` component from the `/vue` entrypoint and pass it to your template. ```vue ``` ## Framer If you are building your website in **Framer**, you can add Cord Elements as a drag-and-drop *Code Component*. Create a new code component in Framer and paste the following: ```tsx import { FramerCordCotizador } from '@flouviahq/elements/framer'; export default FramerCordCotizador; ``` This will register the property controls in Framer's visual interface (Property Controls), exposing the `Token` field in the right panel so your designers can modify it visually without touching code. ## Webflow Unlike Framer (a real React Code Component), Webflow doesn't run React components — that's why the SDK exposes a separate entrypoint (`@flouviahq/elements/webflow`) built for Webflow's visual editor: a self-initializing script that **requires no code**, just custom attributes. 1. In Webflow, add a **Div Block** wherever you want the quoter to appear. 2. In that element's **Settings** panel, add a **Custom Attribute**: `data-cord-token` with your quote's token as the value. (Optionally, `data-cord-base-url` if you use your own domain, and `data-cord-min-height` for the iframe's minimum height.) 3. Under **Page Settings › Custom Code** (or your site's settings if you want it on every page), add this script before ``: ```html ``` The script automatically finds every element with `data-cord-token` on the page (on load, and again if Webflow adds more later) and mounts the quoter there — it doesn't expose its own JS events like the native Web Component does; for that, use `` directly or Framer's Code Component. --- # Integrations and automation URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/integraciones Last updated: 2026-10-07 Which path to take to connect Cord with another system: no-code workflows, managed HubSpot sync, Zapier and Make, or the API with webhooks. ## Which one to use | Path | What for | Who sets it up | |---|---|---| | **Cord Workflows** | React inside Cord: create a task, email the team, post to Slack, or add a note in HubSpot. | Anyone on the team, from the app. | | **HubSpot** | Keep clients, contacts and Deals up to date without entering data twice. | Connected once in Settings. | | **Zapier and Make** | Connect Cord with another tool you already use, without running a server. | Whoever builds the Zap or scenario. | | **API v1 + webhooks** | Full control: your backend decides what to do with each event. | Your development team. | ## Cord Workflows It lives in the app, not in the API. A workflow listens to a Cord event, evaluates conditions, can wait for days, and runs actions. Every run is recorded with its result. Use it when the automation starts and ends inside Cord. If you need to touch another system, use one of the paths below. ## HubSpot Cord manages the sync: clients with Companies and Contacts both ways, and every quote creates and moves its Deal through the pipeline you choose. It needs no code and does not use your webhook allowance. ## Zapier and Make Both platforms talk to Cord's public API and connect through **OAuth 2.0**: the person authorizes on a Cord screen and there are no keys to create or paste. Each authorization becomes a short-lived credential that Cord renews with a refresh token, and it shows up in the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) as an **Authorized connection**. - **Events out:** a webhook subscription created with that connection's credential. They are created and deleted automatically when you turn the Zap or scenario on and off. - **Actions into Cord:** the `/api/v1` endpoints with that same credential. Cord registers OAuth clients on request; there is no self-service registration. Today there are registered clients for Zapier and Make, plus the Cord add-on for Gmail, which belongs to Cord itself. If you're building an app other businesses will connect, follow [OAuth for apps](/en/docs/desarrolladores/herramientas/oauth). For your own server, use a secret key. ## n8n The `n8n-nodes-cord` community node (on npm) uses a secret key in its **Cord API** credential: every n8n install has its own return address, so it does not connect through OAuth. Its trigger registers the webhook when the workflow is activated and verifies the `X-Cord-Signature-V1` signature. Today it installs on self-hosted n8n; version 1.1.0 was published with provenance and submitted to n8n's verification on September 21, 2026, and it will appear in n8n Cloud once n8n approves it. Subscriptions created through the API have their own allowance of 100 per organization, separate from the endpoints your team configures. The details are in [Webhooks](/en/docs/desarrolladores/herramientas/webhooks). If you prefer to build it by hand in Make, the [support guide](https://cordhq.app/en/support/conectar-make) walks through the Webhooks and HTTP modules. ## API v1 and webhooks The full path: authenticate with a secret key, listen to the events you care about, and respond from your backend. - [Authentication](/en/docs/desarrolladores/esenciales/autenticacion) - [Webhooks](/en/docs/desarrolladores/herramientas/webhooks), with the event list, the `X-Cord-Signature-V1` signature, and delivery history. - [MCP server](/en/docs/desarrolladores/herramientas/mcp), when an AI assistant is the one consuming Cord. --- # Cord MCP Server URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/mcp Last updated: 2026-10-15 Connect AI clients like Claude and Cursor to your company's financial system: 28 tools, permissions per tool, and a person who approves anything that leaves Cord. ## What is MCP? The Model Context Protocol (MCP) is a universal standard that allows Artificial Intelligence assistants to connect to secure data sources. By configuring the Cord MCP Server, you empower agents like Claude or IDE-integrated assistants (like Cursor) to organically interact with your company. **Questions you can ask the AI once connected:** - *"Extract the requirements from the attached PDF and generate a quote in Cord for this client."* - *"Review the overdue quotes from the last 30 days and draft friendly collection emails for me."* - *"Look up the client Distribuidora El Zarco and draft a quote with these 3 line items."* ## How to configure the connection Authentication for your AI client is performed using your standard Cord **API Key** (`sk_live_…` / `sk_test_…`) — the same one the REST API uses. 1. Navigate to **Settings › MCP** in the Cord interface. It's in the **Developers** section of the Settings index, which appears once you turn on **Developer mode** in **Your account › Preferences**. 2. A status card at the top tells you whether you already have an active key and, if an AI client is already connected, when it was last used. If you don't have one, the **"Create a key for MCP"** button generates a write key with the read and draft writing groups, without leaving the page — it's pasted automatically into the config below. **Copy it right then: it won't be shown again.** To pick groups or single tools, or to allow actions with external effects, create or edit the key in the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) (see [permissions per tool](#permissions-per-tool)). 3. Copy the MCP client JSON configuration provided on the screen. 4. Paste this configuration into the corresponding local path for your client (e.g., the `claude_desktop_config.json` file if you use the Claude for Desktop app). **Publishable** keys (`pk_…`, meant to live exposed in the browser) can't be used with MCP — they only cover creating quotes and reading the catalog via the REST API. Use a **Secret** key from your backend or desktop client instead. ## Two ways to connect **Streamable HTTP (recommended)** — `POST https://cordhq.app/api/mcp` with the header `Authorization: Bearer sk_live_…`. Sessionless: every JSON-RPC message is an independent HTTP request. This is what most modern MCP clients expect. **HTTP + SSE (legacy, kept for older clients)** — `GET https://cordhq.app/api/mcp/sse` opens a long-lived connection and returns where to send messages (`POST /api/mcp/message?sessionId=…`). Every POST message must carry the **same** `Authorization: Bearer` used to open the session — the `sessionId` in the URL alone isn't enough (it travels in plain text and can end up exposed in intermediate proxy logs), and the key must belong to the same organization that opened the session. ## Permissions per tool Every tool belongs to a group and a resource, with the same model as [restricted keys](/en/docs/desarrolladores/esenciales/autenticacion#restricted-keys): | Group | Tools | Key without a list | |---|---|---| | **Read** | `listar_cotizaciones`, `detalle_cotizacion`, `cartera_vencida`, `resumen_negocio`, `buscar_cliente`, `listar_productos`, `listar_facturas`, `detalle_factura`, `listar_workflows_manuales`, `listar_eventos`, `estado_configuracion`, `validar_datos_fiscales`, `validar_apariencia` | Allowed | | **Draft writing** | `crear_cotizacion_borrador`, `crear_factura_borrador`, `crear_cliente`, `crear_tarea`, `registrar_promesa_pago`, `proponer_configuracion` | Allowed with a write key | | **Actions with external effects** | `enviar_cotizacion`, `aprobar_cotizacion`, `rechazar_cotizacion`, `registrar_pago_cotizacion`, `actualizar_cliente`, `correr_workflow`, `simular_evento` | Blocked: only with explicit permission, and every call waits for approval | When you create or edit a key in the Workbench **API keys** tab, you pick whole groups or, inside a group, single tools. A group also covers the tools Cord adds to it later; a single tool covers only itself. A key without a list, like every key created before per-tool permissions, keeps read and draft writing according to its level and cannot ask for any action with external effects until someone allows it. - The level still rules: a read-only key can't use drafts even if they are on its list, and a restricted key (`rk_`) applies each resource's level to each tool (`listar_facturas` needs `facturas: read`; `crear_cotizacion_borrador`, `cotizaciones: write`). - `tools/list` only returns what the key can call. If a client calls another one, the response is a tool error that says which one is missing and where to allow it. - `contexto_cuenta` and `buscar_documentacion` are always available: they identify the account and search these docs, with no customer data. `actualizar_cliente` is among the actions with external effects even though it writes to no one: Cord uses the customer's email and tax details to send reminders, recurring invoices and collections without another review, so changing them has an effect outside Cord. ## Actions that wait for approval An action with external effects doesn't run when the agent calls it, even if the key allows it and the MCP client doesn't ask for confirmation. Cord stores a request and answers: ```json { "estado": "pendiente_de_aprobacion", "aprobacion_id": "7c1e4b2a-5d3f-4a8e-9b6c-2f1d0e3a4b5c", "aprobacion_url": "https://cordhq.app/app/ajustes/mcp/solicitudes?modo=vivo#sol-7c1e4b2a-5d3f-4a8e-9b6c-2f1d0e3a4b5c", "vence": "2026-10-18T16:04:00.000Z", "mensaje": "No se ejecutó todavía: una persona con acceso a Cord tiene que aprobarla. …" } ``` 1. The agent shares `aprobacion_url` with the user. 2. In **Settings › MCP › Requests**, a person with Settings permission and the permission for the action in the app (Quotes to send or record a payment, Approvals to approve or reject, Clients to update a customer, Quotes or Collections for a workflow depending on its object, Settings to simulate a webhook) sees the document, what would change and the data the agent sent, and approves or rejects. 3. On approval, Cord runs the action once, with the same handler as always. Two people approving at the same time don't run it twice. Rejecting runs nothing. 4. To learn the result, the agent repeats the call with the same `idempotency_key`: the response carries `estado` `ejecutada` (with what the action returned in `resultado`), `fallida` (with the reason in `error`), `rechazada` or `vencida`. The request expires after 72 hours without a decision. Repeating the same call with the same arguments returns the pending request instead of creating another, and an organization receives at most 30 requests per hour. If the key is revoked, expires or loses the tool before the decision, the request can no longer be approved. With a test key, the request lives in the test environment and the link says so with `?modo=prueba`. ## Available tools | Tool | What it does | Permission | |---|---|---| | `listar_cotizaciones` | Lists quotes, with an optional status filter. | read | | `detalle_cotizacion` | Full detail of a quote: line items, totals, timeline. | read | | `cartera_vencida` | OVERDUE accounts receivable: amount, aging, per-client detail. | read | | `resumen_negocio` | KPIs, conversion funnel, pipeline forecast, plan usage. | read | | `buscar_cliente` | Searches the directory by company/contact/RFC/email. Each client includes `language`, their document language (`null` = the organization's). Paginated. | read | | `listar_productos` | Product catalog (id, SKU, name, unit, list price). Paginated. | read | | `crear_cotizacion_borrador` | Creates a DRAFT quote (doesn't send it). Idempotent if you pass `idempotency_key`. | **drafts** | | `listar_facturas` | Lists **Cord Invoicing** invoices with their balance and state (`draft`\|`open`\|`paid`\|`void`\|`uncollectible`\|`overdue`). Filter by state, client, or free text. Paginated. | read | | `detalle_factura` | Full detail of ONE invoice: line items, issuer, recipient, taxes, declared FX rate, balance, and payments received. | read | | `crear_factura_borrador` | Creates a DRAFT invoice for a client, without needing a prior quote. Available on every plan, including Free. | **drafts** | | `enviar_cotizacion` | Asks to send a draft quote to the client (email with the link), in the client's document language. Waits for approval. On the Free plan it uses one of the monthly sends. | **needs approval** | | `aprobar_cotizacion` | Asks to mark a sent or viewed quote as approved. Waits for approval. | **needs approval** | | `rechazar_cotizacion` | Asks to mark a sent or viewed quote as rejected. Waits for approval. | **needs approval** | | `registrar_pago_cotizacion` | Asks to record that an approved quote was paid outside Cord; when it runs, it cancels its pending online payments. Accepts `metodo_pago`. Waits for approval. | **needs approval** | | `crear_cliente` | Creates a client (company, contact, email, phone, tax ID, terms, country, and document language: `es`, `en`, `pt`, `fr`, `de`, or `null`). | **drafts** | | `actualizar_cliente` | Asks to change a client's contact details, `language` included. Only updates what you send; never touches credit, tier, or discount. What was already sent keeps its language. Waits for approval. | **needs approval** | | `crear_tarea` | Creates a follow-up task: `titulo` (required), optional `fecha` due date `YYYY-MM-DD`, `cotizacion_id`, and `factura_id`. It's created unassigned with normal priority; those are changed in the app. | **drafts** | | `registrar_promesa_pago` | Records the date a client promised to pay a quote. It doesn't charge anything. | **drafts** | | `listar_workflows_manuales` | Lists the active "You run it" workflows, by object (`quote` or `invoice`). | read | | `correr_workflow` | Asks to run a "You run it" workflow on up to 50 quotes or invoices, with the published version and its rules. Waits for approval; when it runs, it says how many runs started. | **needs approval** | | `listar_eventos` | Business history (quotes, invoices, clients, tasks, promises), filterable by type or object. Paginated. | read | | `contexto_cuenta` | Business, country, currency, language, time zone, plan and whether the key is test or live. Call it first. | read | | `proponer_configuracion` | Proposes profile, branding, taxes, catalog and templates from the website, a description or the price list (base64, up to 3 MB). Applies nothing: returns `review_url` for a person to approve. | **drafts** | | `estado_configuracion` | Status of a proposal (`propuesto`, `aplicado`, `descartado`, `fallido`) and the result per section. | read | | `validar_datos_fiscales` | Validates RFC, tax regime, CFDI use and postal code (Mexico), NIF/NIE/CIF (Spain) or EIN (US) with the same rules used when issuing. | read | | `validar_apariencia` | Validates an Elements `appearance` object and reports which keys Cord would drop. | read | | `simular_evento` | Asks to fire a test webhook through the real delivery engine. Test keys only. Waits for approval. | **needs approval** | | `buscar_documentacion` | Searches these docs and returns the most relevant pages with an excerpt and URL. | read | Every tool declares standard MCP annotations (`readOnlyHint`, `idempotentHint`, `destructiveHint`) in `tools/list`. Read tools are `readOnlyHint: true` and the ones that change a quote's status are `destructiveHint: true`. Confirmation no longer depends on the MCP client honoring those annotations: Cord doesn't run any action with external effects until a person approves it (see [actions that wait for approval](#actions-that-wait-for-approval)). No tool issues or stamps invoices: that is still an action a person triggers from the app or the API. No tool changes account settings directly: `proponer_configuracion` leaves a proposal that a person with Settings permission reviews and approves in Cord, just like the one from onboarding or `cord setup`. Every tool declares an `outputSchema` and returns `structuredContent` (the validatable JSON) alongside the text. Amounts travel with their currency in `moneda`: never assume pesos. ## Pagination `listar_cotizaciones`, `buscar_cliente`, `listar_productos`, `listar_facturas`, and `listar_eventos` return pages, not the whole table. There are two response shapes. `buscar_cliente` and `listar_productos` return the list in `items`, with `total`, `has_more`, `next_cursor`, and the currency in `moneda`; `listar_cotizaciones` returns `total`, `has_more`, and `next_cursor` with the list in `cotizaciones`, and the currency goes on each quote: ```json { "items": [ { "id": "9a1c3e5f-7b2d-4f6a-8c0e-1d3b5f7a9c2e", "empresa": "Distribuidora El Zarco" } ], "total": 47, "moneda": "MXN", "has_more": true, "next_cursor": "20" } ``` `listar_facturas` and `listar_eventos` return only the list (in `facturas` or `eventos`) and `next_cursor`, without `total` or `has_more`: ```json { "eventos": [ { "id": "6b0e2f4a-8c1d-4e3b-9a5f-7d2c0e8b1a46", "type": "quote.approved" } ], "next_cursor": "MjAyNi0wOS0xNFQxODozMjowNC4xMjMwMDBafDZiMGUyZjRhLThjMWQtNGUzYi05YTVmLTdkMmMwZThiMWE0Ng" } ``` In every case, call the same tool again passing `cursor: next_cursor` for the next page. `next_cursor` is `null` once there are no more results. `listar_productos` **never** includes a product's internal cost/margin — only list price, SKU, name, and unit. That column is intentionally invisible from an API key, whether it has write permission or not. ## Safe-to-retry calls (idempotency) `crear_cotizacion_borrador`, `crear_cliente`, `crear_tarea`, `registrar_promesa_pago` and the seven actions with external effects accept an optional `idempotency_key` — a unique identifier **you generate** (a UUID, for example). If your MCP client needs to retry the call because it didn't get a response in time (network timeout), repeat the SAME `idempotency_key`: Cord returns the result of the first call instead of repeating the action. For an action with external effects, the same key returns the current state of its request (pending, done, rejected…). Reusing the same key with different arguments returns an error, and for the other tools the key expires after 24 hours. ```json { "name": "crear_cotizacion_borrador", "arguments": { "idempotency_key": "a1b2c3d4-…", "cliente_id": "9a1c3e5f-7b2d-4f6a-8c0e-1d3b5f7a9c2e", "items": [{ "descripcion": "Installation", "cantidad": 1, "precio_unitario": 4500 }] } } ``` Without `idempotency_key`, the tool still works normally — every call creates a new draft (it's not a required field, just recommended if your client retries automatically). `detalle_cotizacion` and `listar_eventos` can include text written by the **client** on the public link (comments, counteroffers). That text is marked with `origen: "cliente_externo"` and wrapped in `<<>>`: your agent should report it, never follow it as an instruction. ## Secure Tools Cord exposes "Tools" to the AI in a controlled manner. This means the AI does not have raw, unlimited access to your database; the AI can only invoke endpoints that Cord has approved and categorized, inheriting the permissions tied to the API Key. **Important:** Business rules are strictly applied. If the AI attempts to apply a 150% discount when building a quote, the API will reject the request by returning a `400 invalid_request` code to protect your business. ## Limits, metering, and activity Every real call (not protocol notifications like `notifications/initialized`) counts just like a REST API call against your plan's usage quota. Every HTTP request to the MCP server, notifications included, counts against the API's per-minute limits (600 per secret key and 120 per source IP), and the tools that change a quote's state also share the 120-per-minute limit per organization; see the [limits table](/en/docs/desarrolladores/esenciales/errores#rate-limits). Each call shows up in the **Logs** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench) with the tool that was called (e.g. `/mcp/tools/call:listar_productos`) — so you can see exactly what your agent is doing, with which key, and when. You can filter that log by method or status, or search for `mcp` in the route to isolate just what the AI did. Actions with external effects leave a full trail: each call shows up in **Logs** with the key that made it, the decision shows up in **Settings › Audit log** with the person who approved or rejected it, and the action that ran is audited as done by that key. --- # OAuth for apps URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/oauth Last updated: 2026-10-07 How an external app connects to Cord with OAuth 2.0 instead of asking for a key: client registration, authorization, code exchange, PKCE, refresh with rotation and revocation. ## When to use it If you are building an app that many businesses will connect to their Cord account —a connector, an add-on, an automation platform— use OAuth 2.0 instead of asking them for an API key. The person authorizes on a Cord screen, picks the workspace and can revoke access at any time. It is the same mechanism Cord's apps on Zapier and Make, and the Cord add-on for Gmail, use. For an integration of your own business, an [API key](/en/docs/desarrolladores/empezar/apikey) is simpler. ## Register your app OAuth client registration is not self-service yet. Email contacto@cordhq.app with your app name, its domain and the exact return addresses (`redirect_uri`). We give you a `client_id` and a `client_secret`. Keep the secret on your server: Cord only stores its fingerprint and cannot show it again. Return addresses must be `https` (or `http://localhost` for development) and are matched exactly, without wildcards. ## 1. Request authorization Send the person to: ```text https://cordhq.app/oauth/authorize ?response_type=code &client_id=cord_oc_... &redirect_uri=https://yourapp.com/cord/callback &scope=write &state=RANDOM_VALUE &code_challenge=... (optional, PKCE) &code_challenge_method=S256 (optional, PKCE) ``` | Parameter | Detail | |---|---| | `scope` | `read` for read-only; `write` for read and write (includes `read`). Without `scope`, Cord asks for `read`. You can separate values with a space, a comma or `+`; any other value returns `invalid_scope`. | | `state` | A random value your app checks on return. It prevents a third party from injecting an authorization. | | `code_challenge` | PKCE: `BASE64URL(SHA256(code_verifier))`, 43 characters without padding. Always recommended; only `code_challenge_method=S256` is accepted. | If the person is not signed in, Cord asks them to sign in and returns to the same screen. Only someone with the **Settings** permission in a workspace can authorize apps in it. The screen shows what your app will and will not be able to do. On approval, Cord returns to your `redirect_uri` with `?code=...&state=...`. If the person cancels, it returns with `?error=access_denied&state=...`. ## 2. Exchange the code The code lasts **5 minutes** and works **only once**. Exchange it from your server: ```bash curl -X POST "https://cordhq.app/api/oauth/token" \ -d grant_type=authorization_code \ -d code=cord_ac_... \ -d redirect_uri=https://yourapp.com/cord/callback \ -d client_id=cord_oc_... \ -d client_secret=cord_cs_... \ -d code_verifier=... ``` You can also send the client credentials with HTTP Basic authentication. ```json { "access_token": "cord_at_...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "cord_rt_...", "scope": "write" } ``` ## 3. Call the API The `access_token` works like a key across the whole [API v1](/en/docs/desarrolladores/empezar/resumen) and the [MCP server](/en/docs/desarrolladores/herramientas/mcp): ```bash curl "https://cordhq.app/api/v1/me" -H "Authorization: Bearer cord_at_..." ``` ## 4. Refresh access The access token lasts **1 hour**. Refresh it with the refresh token, which lasts **180 days**: ```bash curl -X POST "https://cordhq.app/api/oauth/token" \ -d grant_type=refresh_token \ -d refresh_token=cord_rt_... \ -d client_id=cord_oc_... \ -d client_secret=cord_cs_... ``` **Every refresh returns a new refresh token and the previous one stops working.** Always store the new one. If an already used refresh token is presented again after 30 seconds, Cord treats it as possible theft and revokes the whole connection; the person will have to authorize again. ## 5. Revoke ```bash curl -X POST "https://cordhq.app/api/oauth/revoke" \ -d token=cord_rt_... -d client_id=cord_oc_... -d client_secret=cord_cs_... ``` It responds `200` even if the token does not exist, so it never reveals which tokens are valid. The person can also revoke your app in the **API keys** tab of the [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench), where it shows up as an **Authorized connection**. ## PKCE PKCE prevents an intercepted code from being exchanged. Generate a random `code_verifier` of 43 to 128 characters (`A-Z`, `a-z`, `0-9`, `-`, `.`, `_`, `~`), keep it in your server's session and send its hash when authorizing: ```js import { createHash, randomBytes } from 'node:crypto'; const codeVerifier = randomBytes(48).toString('base64url'); // 64 characters const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url'); // 43 characters // On /oauth/authorize: code_challenge=&code_challenge_method=S256 // On /api/oauth/token: code_verifier= ``` If you sent `code_challenge` when authorizing, the exchange requires the matching `code_verifier`. If you didn't, the exchange must not carry a `code_verifier`: an unexpected one also returns `invalid_grant`. ## Authorization errors There are two kinds of error on `/oauth/authorize`, and they behave differently on purpose. **Cord doesn't return to your app** when it can't trust the return address. The person sees a Cord error page and nothing is redirected: | Situation | What happens | |---|---| | A `client_id` that doesn't exist | Cord error page (`unknown_client`). | | A `redirect_uri` that doesn't exactly match a registered one | Cord error page. Check case, trailing slash and port. | **Cord returns to your `redirect_uri`** with `error` and your `state` when the client and the address are valid but the request isn't: | `error` | When | |---|---| | `unsupported_response_type` | `response_type` isn't `code`. | | `invalid_scope` | `scope` carries a value other than `read` or `write`. | | `invalid_request` | A malformed `code_challenge`, or a `code_challenge_method` other than `S256`. | | `access_denied` | The person cancelled, or picked a workspace where they can't authorize apps. | ```text https://yourapp.com/cord/callback?error=invalid_scope&state=RANDOM_VALUE ``` These redirects don't carry `error_description`. Always check that `state` is the one you sent before showing the error. ## Exchange and refresh errors `POST /api/oauth/token` accepts the body as `application/x-www-form-urlencoded` or as JSON, and always responds with JSON containing `error` and `error_description`: ```json { "error": "invalid_grant", "error_description": "El código o el token no es válido, ya se usó o venció." } ``` | Status | `error` | `error_description` | When | |---|---|---|---| | `401` | `invalid_client` | Las credenciales de la aplicación no son válidas. | Wrong `client_id` or `client_secret`, via Basic or in the body. | | `400` | `invalid_request` | El cuerpo de la petición no se pudo leer. | The body isn't a valid form or JSON. | | `400` | `invalid_request` | Faltan code o redirect_uri. | Exchange without `code` or `redirect_uri`. | | `400` | `invalid_request` | Falta refresh_token. | Refresh without `refresh_token`. | | `400` | `invalid_request` | Este espacio ya tiene demasiadas conexiones de esta aplicación… | The workspace already has 25 live connections of your app. The person must revoke unused ones. | | `400` | `unsupported_grant_type` | Solo se admite authorization_code y refresh_token. | Any other `grant_type`. | | `400` | `invalid_grant` | El código o el token no es válido, ya se usó o venció. | Expired or used code, a `redirect_uri` different from the authorization's, a `code_verifier` that doesn't match, or a refresh token that's expired, used or from another client. | | `429` | — | — | More than 300 requests per minute from the same IP. Respect `Retry-After`. | `error_description` is in Spanish and may change: decide by `error`. `POST /api/oauth/revoke` returns `401` with `error: "invalid_client"` if the client credentials are invalid, and `200` in every other case. ## Quota Calls with an OAuth token count against the business plan's API quota, same as a key. The only exception is the Cord add-on for Gmail, which is a surface of Cord itself: its calls don't consume the monthly quota, though they do count against the per-minute limits. --- # Node SDK URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/sdks Last updated: 2026-10-07 Install @flouviahq/node and use the full v1 API from your server: configuration, resources and methods, automatic pagination, idempotency, typed errors and webhook verification. ## Official SDKs and tools | Package | What it's for | Status | |---|---|---| | `@flouviahq/node` | v1 API from your server, webhooks, Elements proxy | Published (1.1.0) | | `@flouviahq/elements` | Quote, invoice and tax form in the browser | Published (2.0.2). See [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen). | | `@flouviahq/cli` | Sign-in, simulators and webhooks on your `localhost` | Published (1.2.1). See [CLI](/en/docs/desarrolladores/herramientas/cli). | | Python and PHP | — | **Not published yet.** There is no package on PyPI or Packagist. | Until the Python and PHP SDKs exist, call the [REST API](/en/docs/desarrolladores/referencia) directly. To verify webhooks in Laravel, Django, Flask or FastAPI, `cord init` adds a dependency-free signature verifier to your project; you can also copy the [verification algorithm](/en/docs/desarrolladores/herramientas/webhooks#verify-the-signature-by-hand). ## Installation ```bash npm install @flouviahq/node ``` It runs on Node 20 or later, Bun, Deno, Cloudflare Workers and Vercel. It ships as ESM and CommonJS, with types. ```ts import { Cord } from '@flouviahq/node'; const cord = new Cord(process.env.CORD_SECRET_KEY!); ``` The SDK accepts a secret key (`sk_live_`, `sk_test_`) or a restricted one (`rk_live_`, `rk_test_`). It rejects a publishable key (`pk_`) and refuses to run in a browser: a secret key on a web page is exposed. ## Configuration ```ts const cord = new Cord(process.env.CORD_SECRET_KEY!, { apiVersion: '2026-10-01', timeoutMs: 15000, maxRetries: 3, appInfo: { name: 'my-erp', version: '4.2.0' }, }); ``` | Option | Default | What it does | |---|---|---| | `apiVersion` | `2026-10-01` (`CORD_API_VERSION`) | Sent in the `Cord-Version` header of every request. See [Versions](/en/docs/desarrolladores/esenciales/versiones). | | `baseUrl` | `https://cordhq.app` | Cord's origin. The SDK appends `/api/v1`. | | `timeoutMs` | `30000` | Cuts each attempt off. | | `maxRetries` | `2` (max 5) | Retries on network failure, `408`, `425`, `429`, `5xx` and `409 idempotency_in_progress`. | | `fetch` | global `fetch` | Inject your own `fetch` (tests, proxies). | | `appInfo` | — | Adds your app to the `User-Agent` (`cord-node/1.1.0 my-erp/4.2.0`). Useful when asking for support. | `cord.mode` is `'test'` or `'live'` depending on the key's prefix. ## Resources and methods Every method maps to a v1 API route and keeps the server's field names. Methods that read or write one object return the response's `data`; `list()` methods return `{ data, meta }`. | Resource | Methods | Route | |---|---|---| | `cord.me()` | — | `GET /me` | | `cord.quotes` | `list`, `listAll`, `retrieve`, `create`, `send`, `resend`, `approve`, `reject`, `markPaid`, `del`, `draftFromText` | `/cotizaciones`, `/cotizaciones/{id}`, `/cotizaciones/ia` | | `cord.clients` | `list`, `listAll`, `retrieve`, `create`, `update` | `/clientes`, `/clientes/{id}` | | `cord.products` | `list`, `listAll`, `create` | `/productos` | | `cord.invoices` | `list`, `listAll`, `retrieve`, `create`, `finalize`, `send`, `void`, `recordPayment`, `creditNote` | `/facturas`, `/facturas/{id}` | | `cord.collections` | `retrieve` | `GET /cobranza` (Professional plan or higher) | | `cord.events` | `list`, `listAll` | `GET /events` | | `cord.tasks` | `create` | `POST /tareas` | | `cord.webhookEndpoints` | `list`, `create`, `del` | `/webhooks`, `/webhooks/{id}` | | `cord.elements` | `config` | `GET /elements/config` | | `cord.testHelpers` | `fiscal.setNextOutcome`, `quotes.view`, `quotes.expire`, `webhooks.trigger` | `/test_helpers/*` (`sk_test_` only) | | `cord.webhooks` | `constructEvent`, `signPayload` | Local verification, no network | ```ts const quote = await cord.quotes.create({ cliente: { empresa: 'Acme', email: 'purchasing@acme.com' }, items: [{ descripcion: 'Installation', cantidad: 1, precio_unitario: 12500 }], base_currency: 'MXN', send: true, }); // quote: { id, token, folio, link_publico, needs_approval, motivo, email } await cord.quotes.markPaid(quote.id, { payment_method: 'transferencia' }); const factura = await cord.invoices.create({ cliente_id: '0e6f2b8a-91c4-4d7e-b3a5-6c2d8f1e4a90', items: [{ descripcion: 'Monthly maintenance', cantidad: 1, precio_unitario: 4500 }], currency: 'MXN', due_date: '2026-11-06', }); await cord.invoices.finalize(factura.id); // issues it: irreversible await cord.invoices.recordPayment(factura.id, { monto: 5220, moneda: 'MXN', metodo: 'transferencia' }); ``` `quotes.del()` only deletes drafts. `invoices.create()` creates a **draft**; `finalize()` issues it. `recordPayment()` requires `monto` (amount) and `moneda` (currency) together. ## Lists and automatic pagination ```ts const page = await cord.quotes.list({ status: 'sent', limit: 50 }); console.log(page.meta.total, page.meta.next_cursor); for await (const invoice of cord.invoices.listAll({ estado: 'open' })) { console.log(invoice.numero, invoice.saldo, invoice.moneda); } ``` `listAll()` requests pages of 200 and follows `next_cursor` until it comes back `null`: it never skips or repeats records even if others are created while you iterate. Invoices and events paginate by cursor only. In 1.0.0, `quotes.listAll()`, `clients.listAll()` and `products.listAll()` iterate by `offset`, and `list()` on those three resources doesn't accept `cursor`. Since 1.1.0 they iterate by cursor and `clients.list()` accepts `q` and `email`. Upgrade with `npm install @flouviahq/node@latest`. ## Idempotency and retries Every write (`POST`, `PATCH`, `DELETE`) carries an `Idempotency-Key`. If you don't pass one, the SDK generates a UUID per call and repeats it on every retry of that call: a network drop never creates two quotes or records two payments. To tie the operation to an identifier of yours that survives a restart of your process: ```ts await cord.invoices.recordPayment( facturaId, { monto: 5000, moneda: 'MXN', referencia: 'SPEI-88213' }, { idempotencyKey: `payment-${paymentId}` }, ); ``` Per-call options are `idempotencyKey`, `timeoutMs` and `signal` (an `AbortSignal`). Retries wait for whatever `Retry-After` says (up to 60 s) or an exponential backoff with jitter. ## Typed errors Every error response becomes a `CordError`: | Property | Content | |---|---| | `status` | HTTP status. `0` if there was no response (network down or timeout). | | `code` | The API's stable `code` (`invalid_request`, `insufficient_permissions`, `invalid_state`…). `network_error` if there was no response. | | `message` | The message from the `error` field. | | `requestId` | The `Cord-Request-Id` (`req_…`). Look it up in **Developers › Logs**. | | `docUrl` | Link to the explanation of the code. | | `raw` | The full body, with extra fields such as `limit` or `plan_required`. | ```ts import { Cord, CordError } from '@flouviahq/node'; try { await cord.quotes.approve(quoteId); } catch (err) { if (err instanceof CordError && err.code === 'invalid_state') { // The quote wasn't sent or viewed: nothing was applied. } else { throw err; } } ``` The full list of codes is in [Error handling](/en/docs/desarrolladores/esenciales/errores). ## Webhooks: `constructEvent` ```ts import { constructEvent, CordWebhookSignatureError } from '@flouviahq/node'; export async function POST(req: Request) { let event; try { event = await constructEvent(await req.text(), req.headers, process.env.CORD_WEBHOOK_SECRET!); } catch (err) { if (err instanceof CordWebhookSignatureError) return new Response(err.code, { status: 400 }); throw err; } switch (event.event) { case 'invoice.paid': console.log(event.data.numero, event.data.saldo, event.data.moneda); break; case 'payment.partial': console.log(event.data.tipo, event.data.monto, event.data.saldo_pendiente); break; } return new Response('ok'); } ``` `constructEvent(payload, headers, secret, options?)` uses WebCrypto, so it's the same function in every environment: - `payload` is the **raw** body (`string`, `Uint8Array` or `ArrayBuffer`). An object that was parsed and serialized again won't match the signature. - `headers` accepts a `Headers` object or a plain object such as Node's `req.headers`. - It requires `X-Cord-Signature-V1` and rejects a delivery more than 300 seconds off (`tolerance`, in seconds). During a secret rotation two signatures arrive: one matching is enough. - The legacy `X-Cord-Signature` signature, without a timestamp, is only accepted with `{ allowLegacySignature: true }`. - It returns `CordWebhookEvent`, a union discriminated by `event` with the exact `data` of the 41 events and of `ping`. | `CordWebhookSignatureError.code` | Cause | |---|---| | `missing_signature` | No signature arrived, or the secret is missing. | | `invalid_signature_header` | The header doesn't have the shape `t=,v1=`. | | `timestamp_out_of_tolerance` | The signature is older (or newer) than the tolerance: possible replay. | | `signature_mismatch` | The signature doesn't match that secret. | | `legacy_signature_rejected` | Only the legacy signature arrived and you didn't accept it. | | `invalid_payload` | The body isn't JSON with the shape `{ id, event, created_at, data }`. | `signPayload(body, secret, timestamp?)` signs a body the way Cord does, for your tests: ```ts import { signPayload, constructEvent } from '@flouviahq/node'; const body = JSON.stringify({ id: 'evt_test', event: 'quote.sent', created_at: new Date().toISOString(), data: {} }); const header = await signPayload(body, 'whsec_test'); const event = await constructEvent(body, { 'x-cord-signature-v1': header }, 'whsec_test'); ``` It also exports `WEBHOOK_EVENT_TYPES`, `WEBHOOK_EVENT_OBJECTS` and `isWebhookEventType()` with the event catalog. ## Test mode With an `sk_test_` key, `cord.testHelpers` triggers what a third party does in production, through the same code as production. With a live key it throws before calling Cord. ```ts await cord.testHelpers.fiscal.setNextOutcome('pac_caido'); await cord.testHelpers.quotes.view(quoteId); await cord.testHelpers.quotes.expire(quoteId); await cord.testHelpers.webhooks.trigger('invoice.paid'); ``` To receive the webhooks on your machine, use `cord listen` from the [CLI](/en/docs/desarrolladores/herramientas/cli). ## Other utilities - `createElementsProxy()`: the backend for Cord Elements' `proxyUrl` mode. See [Server proxy](/en/docs/desarrolladores/herramientas/elements/server). - `validateFiscalReceptor()`, `validRfc()`, `validSpainTaxId()` and `validEin()`: the same tax validation Cord applies when saving, so your server can validate before calling the API. See [Tax form](/en/docs/desarrolladores/herramientas/elements/fiscal). - `newIdempotencyKey()` and `CORD_API_VERSION`. ## Changes by version The full history lives in the package's `CHANGELOG.md`. A published version is never rewritten: every change bumps the number. --- # Cord Webhooks URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/webhooks Last updated: 2026-10-13 Build real-time integrations by reacting to events that occur in Cord — durable delivery with retries, event identity, and zero-downtime secret rotation. ## Why use Webhooks? Instead of your system (an ERP, a Zapier/Make flow, or your own backend) asking Cord every 5 minutes "has the client paid yet?", Cord's webhooks notify your system the moment the event happens, with a signed `POST` to your server. Common use cases: - Automatically provision a software license when a quote enters the `paid` state. - Send an internal Slack message the first time a client `views` a quote. - Trigger your ERP's billing process once a CFDI is stamped. ## Setting up an endpoint 1. Turn on **Developer mode** in **Your account › Preferences** — this reveals the **"Developers"** pill in the bottom-right corner, visible across the whole app. Click it or press `W` to open. See the full tour at [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). 2. Open the **Webhooks** tab of the panel. 3. Click **Add endpoint** — opens a full-screen wizard. 4. Pick the events you want to receive: they're grouped by family, with search and a checkbox per family. **All events** (or checking none) sends you **all** of them, including event types Cord adds in the future. See the [full catalog](#event-catalog) below. 5. Enter your URL — **it must be `https://`**; Cord rejects `http://` destinations, `localhost`, private/internal IPs, and `.internal`/`.local` hosts at creation time. 6. Save your **secret** (`whsec_…`) — it's shown in clear text **once**. After that it's masked. From that same screen you can **Send test event**. Your team can configure 16 endpoints on Free, Starter, and Professional, 32 on Scale, and 100 on Developer. Subscriptions created by integrations through the API have a separate allowance of 100 per organization on every plan. Webhooks are NOT gated behind a paid plan. ## The payload Every delivery is a `POST` with `Content-Type: application/json` and this body: ```json { "id": "evt_5f2a1c9e8b3d4a7f6e1c0d9b8a7f6e5c", "event": "quote.paid", "created_at": "2026-07-27T18:32:04.000Z", "data": { "id": "b3f1c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "folio": "COT-0148", "status": "paid", "moneda": "MXN", "total": 45200.00, "cliente": "Distribuidora El Zarco", "cliente_id": "9a1c3e5f-7b2d-4f6a-8c0e-1d3b5f7a9c2e", "link_publico": "https://cordhq.app/q/6f2a9c4e1b7d3f8a0c5e2b9d4f1a6c3e" } } ``` `id` is the **event's** identity, not the quote's — it stays the same across retries and a manual replay (see [event identity & idempotency](#event-identity--idempotency)). `data.id` is the quote's internal id. ## Signing and security Cord signs every delivery with two headers. Use `constructEvent` from `@flouviahq/node` (see the [Node SDK](/en/docs/desarrolladores/herramientas/sdks#webhooks-constructevent)) so you don't have to implement verification by hand. It requires `X-Cord-Signature-V1` with a timestamp, compares in constant time and rejects a delivery older than 5 minutes: ```ts import { constructEvent } from '@flouviahq/node'; const event = await constructEvent( await req.text(), req.headers, process.env.CORD_WEBHOOK_SECRET!, ); ``` Every delivery carries these headers: | Header | Content | Notes | |---|---|---| | `Content-Type` | `application/json` | | | `User-Agent` | `Cord-Webhooks/1.0` | | | `X-Cord-Event` | `quote.paid`, `ping`… | The event type, same as the body's `event` field. Handy for routing without parsing. | | `X-Cord-Timestamp` | unix seconds | The same `t` as in `X-Cord-Signature-V1`: the moment this attempt was signed. | | `X-Cord-Signature-V1` | `t=,v1=.")>` | **Recommended.** Includes a timestamp — real replay protection. May carry **two** `v1=` pairs during a secret rotation (see below); accept if either one matches. | | `X-Cord-Signature` | `sha256=` | Legacy, no timestamp. Still sent on every delivery for compatibility; use V1 if you can. | | `X-Cord-Event-Id` | `evt_…` | Same value as the body's `id` field. | | `X-Cord-Delivery-Id` | uuid | This **attempt's** id — changes on every retry/replay, unlike `X-Cord-Event-Id`. | | `X-Cord-Attempt` | number | 1-indexed. | | `Idempotency-Key` | `evt_…` | Repeats `X-Cord-Event-Id` — several server frameworks read it from there for free. | ## Verify the signature by hand If you don't use the SDK, this is the complete algorithm. It's what `constructEvent` does: 1. Read the **raw** body, exactly as it arrived. Parsed and re-serialized JSON won't match. 2. From the `X-Cord-Signature-V1` header take `t` and **every** `v1` value (two arrive during a rotation). 3. Reject the delivery if `t` is more than 300 seconds away from your clock: it's a replay. 4. Compute `HMAC-SHA256(secret, ".")` in hex. 5. Accept if it matches **any** of the `v1` values, comparing in constant time. ```js import { createHmac, timingSafeEqual } from 'node:crypto'; export function verifyCordSignature(rawBody, header, secret, toleranceSec = 300) { if (!header) return false; let t = null; const signatures = []; for (const part of header.split(',')) { const i = part.indexOf('='); if (i < 0) continue; const k = part.slice(0, i).trim(); const v = part.slice(i + 1).trim(); if (k === 't' && /^\d+$/.test(v)) t = Number(v); else if (k === 'v1' && /^[0-9a-f]{64}$/i.test(v)) signatures.push(Buffer.from(v, 'hex')); } if (t === null || signatures.length === 0) return false; if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSec) return false; const expected = createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest(); return signatures.some((s) => s.length === expected.length && timingSafeEqual(s, expected)); } ``` With Express, ask for the raw body on that route only: ```js import express from 'express'; import { verifyCordSignature } from './verify-cord.js'; const app = express(); app.post('/webhooks/cord', express.raw({ type: 'application/json' }), (req, res) => { if (!verifyCordSignature(req.body, req.get('X-Cord-Signature-V1'), process.env.CORD_WEBHOOK_SECRET)) { return res.sendStatus(400); } const event = JSON.parse(req.body); // Deduplicate by event.id before applying side effects. res.sendStatus(200); }); app.listen(3000); ``` Never compare signatures with plain `===` in production — use a constant-time comparison (the SDK already does). A regular `!==` can leak information via a timing attack. ## The `ping` test event With `ping` selected (the default option), an endpoint's **Test** button in the Workbench sends a delivery with `event: "ping"` through the same path as a real event (signature, headers and log). It uses sample data shaped like a quote plus a `mensaje` field. Every test carries `"test": true` at the top level of the payload: ```json { "id": "evt_0b7e3d9a1c5f2e8b4a6d0c9f3e1b7a5d", "event": "ping", "created_at": "2026-10-07T17:12:09.441Z", "test": true, "data": { "id": "00000000-0000-0000-0000-000000000000", "folio": "COT-PRUEBA", "status": "sent", "moneda": "MXN", "total": 12500, "cliente": "Cliente de prueba S.A. de C.V.", "cliente_id": null, "link_publico": "https://cordhq.app/q/demo", "mensaje": "Esta es una entrega de prueba enviada desde el Workbench de Cord." } } ``` Instead of `ping` you can pick any event the endpoint is subscribed to: it arrives with its real type, sample data in the endpoint's API version and `"test": true` too. A test is attempted **only once**: if it fails, it doesn't enter the retry schedule. Tests don't land in the event history or trigger Workflows. Respond `2xx` and discard them. To test with any of the 41 real events and the data of a test object, use the [webhook simulator](/en/docs/desarrolladores/empezar/pruebas) or `cord trigger` from the [CLI](/en/docs/desarrolladores/herramientas/cli). ## Event identity & idempotency Every logical event has a stable `id` (`evt_…`), identical in the body and in `X-Cord-Event-Id`/`Idempotency-Key`. It's the **same** value: - Across every automatic retry of the same event (see the next section). - On a manual replay from the Workbench ("Retry" in the delivery log) — the payload is resent **byte-for-byte**, `id` included. Since retries and replays can make your endpoint receive the same event more than once, your handler needs to be **idempotent**: store the `id`s you've already processed (even a simple table with a `unique` constraint works) and silently skip duplicates before applying side effects (charging a card, sending an email, etc.). ## Retries and guaranteed delivery Cord enqueues every event **before** attempting delivery — if your endpoint is down, the event isn't lost: it follows an exponential-backoff retry schedule for up to **11 attempts over ~3.6 days**: | Attempt | Wait since the previous one | |---|---| | 1 | immediate | | 2 | ~10 s | | 3 | ~1 min | | 4 | ~5 min | | 5 | ~30 min | | 6 | ~2 h | | 7 | ~5 h | | 8 | ~10 h | | 9–11 | ~1 day | (With ±20% jitter so many endpoints that went down at the same time don't all get retried in the exact same second.) Any non-`2xx` response, a network error or not answering within **5 seconds** counts as a failure and schedules the next attempt. Respond fast and process later: store the event and answer `200` before doing heavy work. A `3xx` (redirect) is **never followed** — it's treated as a failure; if your endpoint moved, update the URL in the Workbench instead of leaving a redirect in place. The first attempt goes out at the moment of the event. Retries are run by a sweep of the delivery engine that runs **every 5 minutes**, so each retry goes out in the first sweep after the time the table shows. If your endpoint was down, don't wait for the next retry: recover what you missed with the [event history](#event-history-through-the-api). Delivery is **at-least-once**, not exactly-once — which is exactly why deduplicating by `id` matters (see above). ## Endpoint health Cord tracks each endpoint's failure streak (only events that **exhausted** their full retry schedule count, or a failed manual test/replay — never an attempt that still has retries ahead of it): - **3 failures in a row** → you get a warning email (at most one every 24h). - **5 failures in a row** → the endpoint is **automatically disabled** (stops receiving new events) and you get an email explaining why. Events still waiting to retry against that endpoint get canceled — they don't pile up indefinitely against a dead destination. Both emails go to the account owner, in your account's language (**Settings › General**). Once you've fixed your endpoint, from the Workbench's Webhooks tab you can: - **Reactivate** — start receiving new events again from now on. - **Reactivate & retry** — also requeues whatever failed in the **last 24 hours** (never the full backlog, so you don't get bombarded with old events all at once). ## Secret rotation You can rotate an endpoint's secret without missing a single delivery. In the Workbench, click **"Rotate secret"**, pick an overlap window (1h / 24h / 72h), and confirm — you'll see the new secret in clear text once. During the window, Cord signs every delivery with **both** secrets at once: ```text X-Cord-Signature-V1: t=1732650000,v1=,v1= ``` The order is fixed: the **new** secret's `v1=` comes first and the **old** secret's comes last. That lets you update your `CORD_WEBHOOK_SECRET` at any point within the window without a single delivery getting rejected, as long as your verification compares **every** `v1=` in the header. The SDK already accepts whichever one matches. If you verify by hand, don't keep a single value: reading only the first one requires that you already have the new secret, and a parser that keeps the last `v1=` (for example, one that builds a key-value map) only validates with the old secret during the window, so it fails as soon as you switch to the new one before the window closes. The legacy `X-Cord-Signature` signature holds a single value, so during the window it's computed with the **old** secret; once the window closes it's signed with the new one. When the window closes, Cord stops signing with the old secret in both headers. ## Event catalog | Event | Fires when… | |---|---| | `quote.sent` | The seller sends the quote to the client. | | `quote.viewed` | The client opens the public link for the first time. | | `quote.approved` | The client approves (fully or partially) the quote. | | `quote.rejected` | The client rejects it. | | `quote.updated` | The seller edits and resends it ("Modify and resend" from the detail view). | | `quote.expired` | Its expiration date passed without a client decision (it was `sent`/`viewed`). | | `quote.deleted` | A draft is deleted (only applies to quotes that were never sent). | | `quote.paid` | Full payment is received (a simple charge, or the last pending charge of a deposit/installment plan). | | `payment.partial` | A SINGLE partial charge is received (deposit, balance, or one installment) without the quote being fully paid yet. | | `payment.failed` | A recurring retainer/subscription charge fails. | | `invoice.stamped` | The CFDI is stamped (comes from a quote, see note below). | | `invoice.issued` | A commercial invoice is issued outside Mexico (comes from a quote). | | `invoice.finalized` | A **Cord Invoicing** invoice is finalized — the standalone invoice object, not tied to a quote. | | `invoice.sent` | The seller sends that invoice to the client. | | `invoice.paid` | The invoice is paid in full. | | `invoice.payment_failed` | A charge against that invoice fails (declined card, failed direct debit). | | `invoice.voided` | The invoice is voided. | | `invoice.marked_uncollectible` | The invoice is marked uncollectible. | | `invoice.overdue` | Its due date passed without being settled (fired by the reminders cron). | | `quote.created` | A quote is created, from the app, the API, MCP, or Cord Elements. | | `quote.approval_requested` | A new quote is waiting for internal approval (discount, amount, or margin outside the threshold). Includes `motivo`. | | `quote.approval_decided` | Management approves or rejects that request. Includes `decision` (`approved` \| `rejected`). | | `quote.comment_added` | The client or the seller writes in the quote conversation. Includes `autor` (`cliente` \| `vendedor`), `mensaje` and, for a line comment, `item_id`; a counteroffer includes `tipo: "contraoferta"` and `propuesta`. | | `client.created` / `client.updated` / `client.deleted` | A client is created, edited, or deleted in the directory. | | `product.created` / `product.updated` / `product.deleted` | A product is created, edited, or deleted in the catalog. | | `task.created` / `task.completed` | A task is created (from the app, the API, MCP, a workflow, or by Cord for a chargeback or SPEI refund) or marked as done. | | `promise.created` / `promise.kept` / `promise.broken` | A payment promise is recorded, or marked as kept or broken. | | `dispute.created` / `dispute.closed` | A client opens a dispute on a Cord Payments charge, or it closes with its outcome in `estado` (`won` \| `lost` \| `warning_closed`). Includes `monto`, `moneda`, `motivo`, and `fecha_limite` to respond. | | `refund.succeeded` / `refund.failed` | A refund succeeds or fails. Includes `monto`, `moneda`, `motivo`, and `motivo_falla` when it fails. | | `payout.paid` / `payout.failed` | A payout to your bank account is paid or fails. Includes `monto`, `moneda`, `llegada`, and `motivo_falla` when it fails. | | `account.updated` | What your payments account can do changes: `puede_cobrar`, `puede_depositar`, `pendientes` (items to verify), and `motivo_bloqueo`. Only sent when one of them changes. | | `ping` | Only shows up when using "Test" from the Workbench — never fired by a real event. | > Dispute, refund, and payout events include `referencia`, the transaction identifier at the payment processor, and are sent once per transaction and outcome. When the charge comes from a quote, they also include `cotizacion_id`, `folio`, and `cliente`. > **Note:** `payment.partial` carries extra fields on `data` that other **quote** events don't > have: `tipo` (`anticipo`\|`saldo`\|`cuota`), `monto`, `numero_cuota`, `saldo_pendiente`, and > `payment_method`, in addition to the normal quote summary (folio, client, total, link). **Two event families, two shapes of `data`.** The `quote.*` and `payment.*` events (including `invoice.stamped`/`invoice.issued`, which fire from the quote) share the `data` shape from the example above (`folio`, `status`, `total`, `cliente`, `link_publico`…). The seven events `invoice.finalized`/`sent`/`paid`/`payment_failed`/`voided`/`marked_uncollectible`/`overdue` belong to **Cord Invoicing** — the invoice as its own object, with its own lifecycle and its own public link, not something derived from a quote — and carry a DIFFERENT `data` shape: ```json { "id": "evt_7c3e9a1f5b2d8e4a0c6f3b9d1e7a5c2f", "event": "invoice.paid", "created_at": "2026-08-20T14:00:00.000Z", "data": { "id": "d4a1b3c5-7e9f-4a2b-8c4d-6e8f0a2b4c6d", "object": "invoice", "numero": "FAC-0032", "folio_fiscal": "3F2A9C1E-7B4D-4E6A-8C2F-1D5B9E3A7C40", "estado": "paid", "estado_fiscal": "issued", "pais": "MX", "tipo": "cfdi_40", "moneda": "MXN", "total": 12500.00, "pagado": 12500.00, "saldo": 0, "vence": "2026-08-30", "cliente": "Distribuidora El Zarco", "cotizacion_id": null, "link_publico": "https://cordhq.app/i/9c1f4e7a2b5d8c0f3a6e9b2d5f8a1c4e" } } ``` `estado` is the invoice lifecycle (`draft`, `open`, `paid`, `void`, or `uncollectible`). `estado_fiscal` is the registration with the tax provider: `pending`, `issued`, `cancelled`, or `error`. `tipo` is the document type: `cfdi_40`, `cfdi_egreso`, `proforma`, `commercial_invoice`, `commercial_credit_note`, `verifactu_invoice`, or `verifactu_credit_note`. Note the public link: `/i/{token}` for a Cord Invoicing invoice, versus `/q/{token}` for a quote. If you use `@flouviahq/node` in TypeScript, `constructEvent` returns `CordWebhookEvent`, a union discriminated by `event` that already types all 41 events in the catalog, including the seven Cord Invoicing `invoice.*` events with the shape above. ### Shape of `data` for clients, products, tasks, and promises Each object includes `object` so you can tell them apart. The product event **never** includes cost or margin. | `object` | Fields | |---|---| | `client` | `id`, `empresa`, `contacto`, `email`, `telefono`, `rfc`, `terminos`, `country_code`, `language` (their document language; `null` = the organization's) (on `client.deleted`: only `id` and `empresa`) | | `product` | `id`, `sku`, `nombre`, `unidad`, `precio_lista`, `activo` (on `product.deleted`: only `id` and `nombre`) | | `task` | `id`, `titulo`, `due_date`, `done`, `cotizacion_id` (no assignee, priority, or notes) | | `promise` | `id`, `cotizacion_id`, `fecha_promesa`, `monto`, `moneda`, `estado` | ## Managing endpoints through the API Platforms like Zapier or Make create and remove their own subscriptions. These routes exist for that: | Method and route | Scope | What it does | |---|---|---| | `GET /api/v1/webhooks` | `read` | Lists the endpoints created by **this same key**, without secrets. | | `POST /api/v1/webhooks` | `write` | Creates an endpoint. Body: `{ "url": "https://…", "eventos": ["quote.approved"] }`. Returns `id`, `url`, `eventos`, and `secret` (in clear text **once**). | | `DELETE /api/v1/webhooks/{id}` | `write` | Deletes an endpoint created by this same key. | The same URL rules as in the Workbench apply: only `https://` to public hosts. These subscriptions don't count against your team's endpoints: they have their own allowance of 100 per organization (`integration_limit_reached`). A key **cannot see or delete** endpoints created from the Workbench or by another key. When you revoke a key, its endpoints are **deactivated**: if you disconnect an integration, it stops receiving data. ## Event history through the API If your system was down longer than retries cover, or you prefer polling over receiving, `GET /api/v1/events` (scope `read`) returns your organization events from newest to oldest, **whether or not any endpoint is subscribed**: ```bash curl "https://cordhq.app/api/v1/events?type=quote.approved&limit=50" \ -H "Authorization: Bearer sk_live_tU..." ``` ```json { "data": [ { "id": "6b0e2f4a-8c1d-4e3b-9a5f-7d2c0e8b1a46", "type": "quote.approved", "object": "quote", "object_id": "b3f1c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "data": { "id": "b3f1c2d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "folio": "COT-0148", "status": "approved", "moneda": "MXN", "total": 45200 }, "actor": "client", "created_at": "2026-09-14T18:32:04.123Z" } ], "meta": { "next_cursor": "MjAyNi0wOS0xNFQxODozMjowNC4xMjMwMDBafDZiMGUyZjRhLThjMWQtNGUzYi05YTVmLTdkMmMwZThiMWE0Ng" } } ``` - Optional filters: `type` (an event from the catalog) and `object_id`. - `next_cursor` is an opaque token: repeat the request with `?cursor=`. It is `null` when there are no more pages. - `actor` tells you who caused the event: `user:`, `api:`, `mcp:`, `client` (the client on the public link), `workflow:`, `system` and others. See the [full list](/en/docs/desarrolladores/funciones/eventos#who-caused-the-event-actor). - The history's `id` is the record's UUID, different from the webhook's `evt_…`. - Unlike the webhook, `data` does **not** include `link_publico`: the link is a credential and is not stored in the history. ## Delivery log and retention In the Workbench's Webhooks tab, each endpoint has an expandable log with its last 50 deliveries (event, attempt, status, duration and date). Each one opens to show **what Cord sent** (the exact payload), **what your server answered** and the **Retry** button. The Workbench's **Events** tab shows the same thing from another angle: one logical event with its delivery to each endpoint, instead of a per-endpoint log, and the **Resend** button. The log is kept for **30 days**; events that ultimately failed for good are kept for **90 days** (so "Retry" keeps working longer in that case). Don't use Cord's log as long-term storage of what was sent — persist whatever you need to keep in your own system as you process each delivery. Viewing the delivery log, **Retry** on a delivery, **Resend** on an event and **Reactivate & retry** on an endpoint require the Professional plan or higher. Creating endpoints, receiving events, **Test**, **Rotate secret** and **Reactivate** are available on every plan. --- # Cord Workbench URL: https://docs.cordhq.app/en/docs/desarrolladores/herramientas/workbench Last updated: 2026-10-11 Cord's developer console inside the app: a log of every request, grouped errors, events, webhooks, a Shell to try the API, keys, your integration's health and an ID inspector. ## What is it? The Workbench is Cord's developer console. It lives at the bottom of the app as a **Developers** pill and, when you open it, expands into a panel with eight tabs: **Overview**, **Logs**, **Errors**, **Events**, **Webhooks**, **Shell**, **API keys** and **Health**. The panel's top bar holds the **Inspector**, which finds any ID. API keys, webhooks, logs and events live here. **MCP, Artificial intelligence and Embeddable quote builder are still in Settings**, under the Developers section of the index, because they're one-time configuration. ## Requirements - **Settings permission** on your role. Without it, the Workbench doesn't show up. - **Developer mode** turned on. It's a preference of your account, not of the organization. - It's on **every plan**. Webhook delivery history, **Retry** and **Resend** require the Professional plan or higher. ## Turning it on 1. Go to **Settings** and scroll to the bottom of the category index. 2. Turn on the **Developer mode** switch. 3. The **Developers** pill appears in the bottom-right corner, across the whole app. Click it, drag it upward or press `W`. Developer mode follows you on any computer where you sign in with your account. You can also change it in [Your preferences](/en/docs/cuenta/preferencias). A link with `?wb=` or `?wbi=` (see [Direct links](#direct-links)) also turns it on. ## The panel - **Size.** Drag the top handle to make the panel taller or shorter; drop it near the bottom to close it. - **Full screen.** The button next to **Close** expands the panel to the whole window. Exit with the same button, with `⇧W` or with `Esc`. - **Options (⋯).** **Show times in UTC** switches every date in the panel instantly without touching your account's time zone. The menu also lists the keyboard shortcuts and links to this guide and to the OpenAPI spec. - **Environment.** The Workbench shows the environment the app is in. In the [test environment](/en/docs/desarrolladores/empezar/pruebas) you see what your `sk_test_` keys and the Shell in **Test** did; in live mode, what your live keys did. Overview marks it with a **Test** or **Live** label. - The panel remembers, in this browser, whether it was open, the tab, the height, full screen and the UTC option. ### Keyboard shortcuts | Key | What it does | |---|---| | `W` | Opens or closes the Workbench. | | `⇧W` | Full screen. | | `/` | Puts the cursor in the Inspector. | | `1` to `8` | Goes to the tab with that number, in the order of the bar. | | `J` / `K` | Next or previous row in Logs and Events. | | `⌘↵` (`Ctrl+↵` on Windows) | Sends the Shell request. | | `Esc` | Closes whatever is open: menu, dialog, Inspector, full screen and, last, the panel. | Single-letter and number shortcuts don't fire while you're typing in a field. On screens narrower than 880 px there are no single-key shortcuts and the panel opens as an edge-to-edge sheet; on the narrowest ones, the Inspector is an icon in the top bar that expands when you tap it. ## The tabs ### Overview The landing view, with a period of **24 hours**, **7 days** or **30 days**: - **Indicators:** API requests, error rate, p95 latency (with p50 below) and the share of webhook deliveries that succeeded. - **Requests over time:** bars of succeeded and failed requests. - **Top errors:** the five most frequent codes. A click opens Logs filtered by that code. - **Where they come from:** requests by source. A click opens Logs filtered by that source. - **Recent activity:** the last six requests. - On the right: the health card (it takes you to **Health**), **API usage this month** against what your plan includes, **getting started** steps while there are no requests in the period, and developer resources. Only calls made with live keys count toward this month's usage: test and Workbench calls don't use your quota. Each request's source comes from the client that made it: | Source | When | |---|---| | **Node SDK**, **Python SDK**, **PHP SDK**, **CLI** | Cord's SDK or CLI identified itself in the request. | | **cURL** | The request came from `curl`. | | **MCP** | A call to the [MCP server](/en/docs/desarrolladores/herramientas/mcp). | | **Cord Elements** | A publishable key (`pk_`), like the one [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen) uses. | | **Connected app** | An app authorized through [OAuth](/en/docs/desarrolladores/herramientas/oauth), like Zapier or Make. | | **Workbench** | The [Shell](#shell). | | **HTTP** | Any other client. | ### Logs Every request that reached `/api/v1` and the MCP server, in a list with its detail on the right. MCP calls show the tool, for example `/mcp/tools/call:listar_productos`. - **Search** by route, by request id (`req_…`), by error code or by an exact `Idempotency-Key`. A request id is searched across the whole history, regardless of the period. - **Filter** by method (`GET`, `POST`, `PATCH`, `DELETE`), by status class (2xx, 4xx, 5xx), by key (or only the Workbench's), by source and by period (1 hour, 24 hours, 7 days or 30 days). - **Live** adds new requests at the top every few seconds while the tab is in view. **Load more** brings the next 50. A request's detail shows the status, the error code with its message and a **How to fix it** link to [Errors](/en/docs/desarrolladores/esenciales/errores), the request id, the date, the latency, the key, the source, the API version, the mode, the IP and the `Idempotency-Key`. If Cord returned the stored response of a repeated request, it's marked as **Replayed response**, and below it lists the other requests with the same `Idempotency-Key`. - **Copy as cURL** copies the request ready to paste into your terminal: the `Authorization` header reads your key from the `$CORD_SECRET_KEY` environment variable. The body isn't included because it isn't stored. - **Open in Shell** loads it in the [Shell](#shell) with its parameters. In live mode it only appears for `GET` requests. - **Inspect the resource** opens the ID in the route in the Inspector. Cord **doesn't store the body** of API requests or responses, only their metadata. Storing them would mean keeping your customers' data (tax IDs, emails, amounts) on every call. To see a full response, repeat the operation in the Shell or check your own server's log. Each request is kept for **30 days**. A daily job deletes anything older, so the longest period in Logs, Errors and Overview is 30 days. The deletion runs through a database function that only removes records older than 30 days; not even Cord can use it to delete anything more recent. ### Errors Failed requests grouped by **code, method and route**, with the IDs in the route replaced by `{id}`, so you see the cause and not every row. Period of 1 hour, 24 hours, 7 days or 30 days. A request without its own code shows up as `http_` plus its status. Each group shows how many times it happened and when it last did. Opening it shows the last error message, the path, the first and last time, how many keys caused it and three actions: **View requests** (Logs filtered by that code), **View an example** (the most recent request in the Inspector) and **How to fix it**. ### Events Your business's event history: the same one [`GET /api/v1/events`](/en/docs/desarrolladores/funciones/eventos) returns, even if you don't have any webhook. - **Filter** by event type, by delivery status (**Failed**, **Queued**, **Delivered**) and by the object's ID. **Live** and **Load more** work the same as in Logs. - Each row shows the status of its deliveries, the type, the object, who triggered it (API, MCP, Dashboard, Workflow, Workbench, Integration or System) and the date. - The **detail** shows the event ID, the date, the object (a click opens it in the Inspector), who triggered it with the name of the key or person, the **event data** and one delivery per subscribed endpoint: URL, status, attempts, next attempt, the `evt_…` that endpoint received and the last error. - **Resend** sends a delivery again with the same payload and the same `evt_…`, so your server can deduplicate it. With more than one failed delivery, **Resend failed ones** appears. Both require the Professional plan or higher. - The event's status comes from the **latest** delivery to each endpoint: a successful resend replaces the failure. A delivery Cord canceled because it disabled the endpoint shows as **Canceled**, not as delivered. Internal events, like `quote.expiring` or `invoice.due_soon`, carry the **Internal** label: workflows use them and they aren't sent through webhooks. Test deliveries (an endpoint's **Test** button or the simulator without `objeto_id`) aren't events of your business: they don't show up here, only in the endpoint's deliveries. ### Webhooks Your endpoints, with your plan's allowance. **Add endpoint** opens a full-screen wizard: 1. **Choose events.** The 41 catalog events, grouped by family, with search and a checkbox to select a whole family. **All events** also includes the ones Cord adds later; if you select none, you receive all of them. 2. **Configure the destination.** A public `https://` URL. 3. **Save the secret.** The signing secret (`whsec_…`) is shown only once. From there you can also **Send test event**. Each endpoint shows its masked secret, how many events it receives, its last delivery and the **last 7 days**: deliveries per day, success rate and p95 latency. Its actions: - **Test** sends `ping` or any of its subscribed events with sample data, in the API version the endpoint is pinned to. The payload carries `"test": true` at the top level so your server can tell a test apart from a real event. - **Edit**, **Rotate secret** (with a 1, 24 or 72 hour window in which both secrets stay valid), enable or pause, and **Delete**. - **Reactivate** or **Reactivate & retry** when Cord disabled the endpoint after a failure streak. The second one requeues what failed in the last 24 hours. - Expanding the row shows its last 50 deliveries. Each one opens **what Cord sent** (the exact payload) and **what your server answered** (up to 2,000 characters), with **Retry** and, if it came from an event, **View the event**. The full guide (payload, signatures, catalog and retries) is in [Webhooks](/en/docs/desarrolladores/herramientas/webhooks). ### Shell Runs any public API operation with your session, without creating a key. - **Test** runs on your test environment: you can create and change things without touching real data, and use the test simulators. - **Live · read only** reads your real data: it only lets you send `GET` operations. - Operations tied to a key (webhook endpoints through the API and `cord listen` sessions) and the ones that stream their response or upload files don't run in the Shell. Pick an operation from the list (with search), fill in its parameters and its JSON body, which comes with an example, and send it with **Send** or `⌘↵`. Under **Optional headers** you choose the API version (`Cord-Version`). The response shows the status, the latency and the request id, and has three views: **Response** (up to 200 KB), **Headers** and **Code**, with the same request in cURL, Node SDK, JavaScript (`fetch`) and Python, using your key as `$CORD_SECRET_KEY`. **Recent** keeps your last 15 calls for this organization in this browser. Every Shell call shows up in Logs with the **Workbench** source and doesn't use your plan's API quota. A click on the request id opens it in the Inspector. If you ran it in a different environment than the app's (for example, in **Test** with the app in live mode), the request id is only copied: switch the app's test mode to see it in Logs. ### API keys - **API usage this month** against what your plan includes, and the current **API version**. Every key and webhook is pinned to the version of the day it's created; the `Cord-Version` header overrides it per request. See [Versions](/en/docs/desarrolladores/esenciales/versiones). - **API keys:** generate, edit, roll and revoke secret (`sk_`), restricted (`rk_`) and publishable (`pk_`) keys, in test or live mode. Each key has a **Logs** button that opens its requests from the last 7 days. Apps authorized through OAuth show up as an **Authorized connection**. See [API Keys](/en/docs/desarrolladores/empezar/apikey). - **API reference:** every operation, grouped, with a `curl` example, a **Try it** button on the ones that can run in the Shell and the button that generates an integration prompt for ChatGPT or Cursor. ### Health A list of **active alerts**, each with a link to the tab where you fix it: - an endpoint that's disabled or has 3 or more failures in a row; - events that ran out of retries and overdue retries in the queue; - an error rate of 5% or more with at least 20 requests in 24 hours; - 5xx errors in the last 24 hours; - a key that expires, or a rolled key that stops working, in the next 7 days. Below, three cards: the status of each endpoint (active with its success rate and p95, paused, disabled or with failures in a row), the **event queue** (queued, overdue retries, exhausted and p95 delivery) and **API in the last 24 hours** (requests, error rate, 4xx, 5xx and p95 latency). ## Inspector Paste an ID into the search box in the panel's top bar, or press `/`: - a request id (`req_…`) opens that request; - an event id (`evt_…`) opens the event behind it, or tells you it was a test delivery; - the ID of a quote, invoice, client, product, key, webhook endpoint or event. For an object you see its type, its name or folio, the events that mention it and the requests from the last 30 days that touched it (or that the key made). **Open in Cord** takes you to its page when it has one, and on a quote, invoice or client, **See it as the API returns it** opens it in the Shell. **Back** or `Esc` return to the tab. ## Direct links - `/app?wb=registros` opens the Workbench on that tab. The names are `resumen` (Overview), `registros` (Logs), `errores` (Errors), `eventos` (Events), `webhooks`, `shell`, `api` (API keys) and `salud` (Health). - `/app?wbi=` opens the Inspector with that ID. Both turn on Developer mode if it was off. ## FAQ **Why don't I see a request I made with a test key?** The Workbench shows the environment the app is in. Switch to the test environment to see what your `sk_test_` keys did. **Does the Workbench count against my API quota?** No. Browsing the panel doesn't call your API, and Shell calls don't count either. Only requests made with live keys count. **Why does Events show events even though I have no webhooks?** Because it reads your business's event history, not the deliveries. Without endpoints, each event shows up as **No endpoints**. **Why can't I see an endpoint's deliveries?** Delivery history, **Retry** and **Resend** require the Professional plan or higher. Creating endpoints, receiving events, **Test**, **Rotate secret** and **Reactivate** are on every plan. **How long are logs kept?** 30 days from each request. If you need a longer history, store the request id (`Cord-Request-Id`) and the response in your own system. **Does my team see the same thing I do?** Yes. Any member with the Settings permission sees the organization's data. What's personal is Developer mode, which goes with your account, and, in each browser, the panel's size and the UTC option. The Shell's recent calls are kept in each browser per organization. --- # SSO and SAML URL: https://docs.cordhq.app/en/docs/desarrolladores/seguridad/sso Last updated: 2026-10-07 Secure access to the Cord ecosystem using your corporate identity provider. ## Enterprise Security As organizations grow, managing users and passwords individually becomes an unmanageable risk. Cord supports **SSO via SAML 2.0** with its own engine (not a cosmetic checkbox): XML-DSig signature validation, replay protection, automatic account provisioning, attribute-based role mapping, and an emergency mechanism if your identity provider fails. By enabling SSO in your Cord organization: - Your employees log in automatically if they are already authenticated in their corporate work portal. - Any **MFA** policy you already enforce at your identity provider (Okta, Azure AD, Google Workspace) carries over: Cord delegates authentication entirely, so it never sees or manages that second factor itself. - Turning on **"Require SSO"** blocks password, Google, Apple, and passkeys for every member **except the account owner**, who always keeps their password as a fallback — the one way in that doesn't depend on your IdP being up. - The requirement belongs to your organization, not to the account: someone who also belongs to another organization with its own SSO can't sign in through that one and then switch to yours. When they open your organization, Cord sends them to sign in with **your** identity provider. ## Prerequisites 1. Your organization must be on Cord's **Scale** plan or higher (Developer) — SSO isn't available on Free, Starter, or Pro. 2. You need the `equipo` (team) permission on your Cord role (Owner and Administrator have it by default; a custom role can also carry it). 3. You must have Administrator privileges in your Identity Provider (Okta, Azure AD / Microsoft Entra, Google Workspace, or any SAML 2.0 IdP). ## Where to configure it **Settings › Team & permissions › SSO** (it doesn't live under Security — SSO sits in the same group as Team & roles, because it governs who gets into the organization, and shares the `equipo` permission). ## SAML Configuration Steps The exchange is two-way, but the real order flips what most people expect: you hand Cord your IdP's data first, and Cord generates its own from that — not the other way around. 1. In your Identity Provider, create a new SAML application for Cord and download or copy its **metadata XML** (most IdPs expose this at a public URL or a "Download metadata" button). 2. In Cord, go to **Settings › Team & permissions › SSO › Connect a provider**, name the connection, and paste that XML. Cord parses it automatically: it extracts the IdP's Entity ID, its sign-in URL, its signing X.509 certificate(s), and, if present, its Single Logout URL — you don't need to type those fields by hand (though the connection's detail view leaves them editable afterward, in case your IdP rotates its certificate). 3. Once the connection is created, Cord shows you three values that belong to your organization: the **ACS URL** (Assertion Consumer Service — where your IdP should send the SAML response), Cord's **Entity ID**, and the **Metadata URL**. Go back to your Identity Provider and fill those into the application you created in step 1. 4. Test with a single user before requiring SSO for the whole team — an incorrect attribute mapping can lock out your entire staff. ## Provisioning and roles, not just login SSO in Cord isn't just "sign in a different way" — it automatically decides what account gets created and with what role: - **JIT (Just-in-Time) provisioning**: on by default. The first time someone logs in through this connection, Cord creates their account and adds them to the organization in that same login — no need to invite them manually from Team first. - **Attribute-based role mapping**: define rules like *"if the `groups` attribute my IdP sends contains `finance-admin`, assign the Administrator role."* Each rule compares one SAML attribute (`equals`, `contains`, or `regex`) against a value and a Cord role; rules are evaluated in order and **the first match wins**. If none apply, the account gets the connection's **default role** (e.g. Read-only). - **IdP-initiated login**: you can enable an employee to sign in directly from their IdP's app portal (Okta, Microsoft's MyApps), without going through `cordhq.app` first. Because that sign-in didn't start in their browser, Cord shows which email they are about to sign in with and asks them to confirm with **Continue** before opening the session. ## Verified domains (optional, recommended) You can tie an SSO connection to one or more email domains (`yourcompany.com`) via a **DNS TXT record** — the same verification pattern used for an outbound email domain. With at least one verified domain, only emails from that domain can sign in through that connection; with none verified, the connection doesn't restrict by domain. ## If your identity provider goes down (break-glass) With "Require SSO" on, a down identity provider locks out the whole organization — **except the account owner**. If the rest of the team needs to sign in with a password temporarily, the owner can use the emergency button on the same screen: re-authenticate with their password to disable the SSO requirement for **1 hour**. After the hour passes (or if you re-enable it sooner by hand), the requirement comes back on its own. **Important:** Test the integration with a single user before turning on "Require SSO" for the whole team — an attribute mapping error can lock out your entire staff, except the account owner. --- # Clients, terms, and statements URL: https://docs.cordhq.app/en/docs/gestion/clientes Last updated: 2026-10-15 How to create and import clients, configure discounts, credit, terms, tax data, and the language of their documents, and read commercial history and balances. A Cord client is more than a contact. Its record stores reusable commercial and tax identity plus terms that control suggested discounts, due dates, and credit exposure. ## Create a client Open **Clients > New client**. The **name or legal name** is the only field required to save (it works for a company or a person), but complete the remaining data before sending a quote that must be collected or invoiced. | Group | Fields | Effect | |---|---|---| | Identity | name or legal name, country, and tax ID | The country decides the tax ID's name (RFC, EIN, NIF, CNPJ…) and Cord checks its format in the markets it offers; if it doesn't look right you get a warning, but you can still save. | | Contact | person, email, phone with country code, and document language | The phone is saved in international format (`+1 512 555 0100`), which WhatsApp delivery needs. The language decides which one the client receives their documents in (see [Document language](#document-language)). | | Address | address lines, city, state or province, and postal code | Labels follow the country (ZIP code, CEP…); Mexico, the United States, Canada, Brazil, and Spain have a list of states or provinces. | | Tax details for CFDI | regime and CFDI use | Only when your business invoices in Mexico and the client is Mexican; options are filtered by RFC type (individual or legal entity). | | Terms | chips Due on receipt, Net 15, Net 30, and Net 60, or **Other term** (Net 7, Net 45, or Net 90) | Default due date for new client operations. | | Credit | limit at or above zero | Reference for exposure and over-limit alerts. | | Price level | Standard, Silver, Gold, or Distributor | Commercial classification and suggested discount. | Levels initially suggest 0%, 5%, 10%, and 15%. The percentage can be edited from 0% to 100%; the level is a label while the stored percentage is the effective default. The credit limit is an operating signal, not credit issued by Cord or a payment guarantee. The seller decides whether to keep selling above that exposure. ## Client country A new client starts with your business's country; change it if the receiver operates elsewhere. Cord accepts receiver countries beyond the 12 markets where the platform is sold (common ones are listed first). A client saved earlier without a country keeps inheriting your business's country until you edit it. Changing country adjusts the tax ID's name and expected format, the phone's country code, and the address fields, but doesn't turn a commercial invoice into an automatic filing with the receiver's authority. If your business is in Mexico and the client isn't, their CFDI is stamped to a foreign resident: see [Invoicing](/en/docs/pagos/facturacion). ## Document language In the **Contact** section, **Document language** decides the language in which this client receives what you send: the quote and invoice links, the payment page, their portal, the PDF, sending emails, reminders, your workflows' emails, and AI collections. You can choose Español, English, Português, Français, or Deutsch. The first option, **Organization default**, uses your account's language (**Settings › General**) and follows its changes. The client record shows the chosen language. - **Each document keeps the language it went out in.** A quote takes it when sent and an invoice when issued; if you change the record later, only the following documents change. A new version of a quote already sent keeps the original's language, and a credit note, a debit note, or an invoice that replaces another keeps its original invoice's language. An invoice created from a quote takes the language the client has when it is issued. - **Dates and numbers** follow that language's conventions. - **The language doesn't change the currency or the tax:** an English-speaking client of a business in Mexico still sees IVA and their document's currency. - **What you write isn't translated:** descriptions, notes, your own terms, and the email introduction and signature. - **The payment form** also appears in that language, and Cord asks the payment processor to use it in the notices it sends your client. - **France:** the invoice must be in French. If your business is in France and the client has another language, the invoice PDF comes out in French with the client's language alongside, and the client form warns you. The quote comes out only in the client's language. - **What doesn't follow the client:** the stamped CFDI PDF in Mexico (in Spanish), the NF-e DANFE in Brazil (in Portuguese), the data the authority returns in Argentina, Chile, Colombia, and Peru, the notices the law requires in its own language, the e-invoice XML files, and the WhatsApp Business template, which Meta approves in a single language. Each country's PDF language is in [Invoicing by country](/en/docs/pagos/paises/resumen). The language can also be set through the API with the `language` field: see [Clients API](/en/docs/desarrolladores/funciones/clientes). ## Import clients from CSV The **Clients > Import CSV** flow lets you upload a `.csv`, map columns, preview rows, and choose whether to update existing matches. One import accepts up to **2,000 rows**. Rows without a company are skipped. The terms column accepts codes (`contado`, `net7` to `net90`) or plain text such as "Net 45" or "45 days": Cord picks the offered term that does not exceed what was written. "Credit" without a number reads as `net30`, and any other text becomes due now. With **Update existing** enabled, Cord matches by exact tax ID first and case-insensitive company name second. Matches update contact, email, phone, ID, terms, and limit; other rows create clients. With it disabled, rows are inserted without merging duplicates. ## Search, filter, and sort Filter clients with or without quotes, with a non-standard level, with a credit limit, or with incomplete tax data. Sort by company, closed amount, quote count, recent activity, or credit limit. These controls only change the view. ## What a client record shows Cord calculates quote count, pipeline, closed and collected amounts, average ticket, win rate, average days to close, discounts conceded, 12-month activity, products sold, origin, creation date, and inactive days. When receivables exist, it also shows one statement across quotes and invoices: open balance, overdue amount, oldest item, and current, 1–30, 31–60, 61–90, and 90+ day aging bands. An invoiced operation appears as an invoice only, avoiding a duplicate balance. ## Client portal and automatic payments In the right-hand column of the profile, the **Client portal** block gathers the private link where your client sees all their invoices, their balance per currency, and pays several at once: - **Create portal link**, **Copy**, **Send by email** (if the client has an email), and **Open**. - **Generate new link** invalidates the previous one; **Disable link** leaves the client without access until you generate another. - **Automatic payments:** the method your client saved (for example, "Visa •••• 4242"), the next retry if a charge failed, or the reason it stopped. With the Clients permission you can **Turn off automatic payments**. See [Client portal: invoices and payments](/en/docs/pagos/portal-facturas) and [Automatic payments](/en/docs/pagos/cobro-automatico). ## Client source The profile shows under **Source** how the client arrived: - **Added manually:** created from Clients, the quote editor, the CSV import, or the clients API. - **Self-registered:** created automatically when a quote came in from your [embedded quote builder](/en/docs/desarrolladores/herramientas/elements/resumen) (or the quotes API) with a new client whose company or email didn't exist in your directory. The profile marks it with a label. A self-registered client is never updated automatically: if the same company quotes again from your site, Cord reuses the existing profile without changing its data. Review these clients and complete their information before invoicing them. ## Export clients to CSV 1. Go to **Settings › Advanced › Data & privacy**. 2. Under **Catalog and clients (CSV)**, click **Clients**. 3. A CSV downloads with the columns empresa, contacto, email, telefono, rfc, terminos, and limite: the same format as the import, to open in Excel or migrate. To open that screen you need the Settings permission, and to download the file, the Clients permission. On the same screen, **All organization data (ZIP)** exports, along with the clients, the rest of the organization's data: one JSON file per table and a manifest with each table's record count and what is left out and why. It does not include PDF/XML files or credentials. If a read fails, the download ends in an error instead of delivering an incomplete file: export again. ## Start a quote from the client Select **New quote** in the client record (requires the Clients permission). The editor opens with that client selected and uses its terms as defaults. Always review recipient, currency, tax, discounts, and due date for the current document. Later client edits don't silently rewrite issued fiscal documents; those keep the issuer, recipient, line, and amount data they were issued with. ## Permissions, limits, and deletion - Creating, editing, importing, and deleting requires the **Clients** permission. - Free supports up to 50 clients and Starter up to 500. Pro, Scale, and Developer have no hard client limit under the current contract. - Deletion is permanent and recorded in the audit trail. Review associated quotes and statement items first. ## Common problems **New client or Import CSV is missing.** The member lacks Clients permission. **Import updated a row that should have been separate.** Upsert matched its tax ID or company name. **Tax data is incomplete.** Review country, ID, address, and document-specific fields. **Balance exceeds the limit.** This is an alert; decide whether to change terms, request an upfront payment, or stop new sales. **I can't find how to export.** Export lives in **Settings › Advanced › Data & privacy**, not in the directory. **The client received a document in the previous language.** It was sent or issued before the change: each document keeps the language it went out in. The following ones already use the new one. ## Related - [Client data in a quote](/en/docs/cotizacion/cliente) - [Receivables and collections](/en/docs/pagos/cartera-cobranza) - [Credit terms](/en/docs/pagos/credito) - [Client portal: invoices and payments](/en/docs/pagos/portal-facturas) - [Clients API](/en/docs/desarrolladores/funciones/clientes) --- # Quote management URL: https://docs.cordhq.app/en/docs/gestion/cotizaciones Last updated: 2026-10-08 Find any quote, the actions available in each status and the permission they need, how to delete drafts, duplicate (and what isn't copied), and keep versions with Modify and resend. ## What it is **Quotes**, in the main menu, gathers all your organization's quotes, newest first. From there you open each one's detail, where its actions, activity, conversation, and versions live. ## Requirements - **View:** any member of the organization. - **Quotes permission:** create, continue editing, send, modify and resend, delete drafts, and reply in the conversation. - **Approvals permission:** mark approved or rejected, decide internal approvals, and record payment and issue the document from the detail. - **Plan:** all. The number of active quotes is capped on Free (5) and Starter (50). ## Find a quote **Filters** (pills above the list, each with its count): | Filter | Includes | |---|---| | **All** | Every quote. | | **Open** | Draft, Sent, and Viewed. | | **Needs approval** | Those waiting for an [internal approval](/en/docs/cotizacion/aprobaciones-internas). | | **Approved** | Approved. | | **Paid** | Paid and Invoiced. | | **Closed** | Rejected and Expired. | **Search:** the list has no search box of its own. On desktop, open the command palette (⌘K on Mac, Ctrl+K on Windows) and type at least two characters of the quote number or the client's name; it shows up to 6 quotes, plus matching clients and products. **From other screens:** the funnel and pipeline bars on Home open this list with the matching filter already applied. ## Actions by status | Status | Actions on the detail | Permission | |---|---|---| | **Draft** | **Send to client**, **Continue editing**, **Preview**, **Duplicate quote**, **Delete draft** | Quotes | | **Draft pending approval** | **Approve and send**, **Reject** (in addition to the above) | Approvals | | **Sent / Viewed** | **Mark approved**, **Mark rejected** | Approvals | | | **Modify and resend (V2)**, **Open link**, **Copy link**, **PDF**, **WhatsApp**, **Duplicate quote** | Quotes | | **Expired** | **Modify and resend**, sharing, **Duplicate quote** | Quotes | | **Approved** | **Record payment**, **Stamp CFDI 4.0** / **Issue invoice** / **Issue pro forma** | Approvals | | | Sharing, **Duplicate quote** | — | | **Paid** | **Stamp CFDI 4.0** / **Issue invoice** / **Issue pro forma** | Approvals | | **Invoiced** | Sharing, **Duplicate quote**; documents appear under **Tax documents** | — | | **Rejected** | Sharing, **Duplicate quote** | — | A quote with a monthly retainer doesn't show **Record payment**: its charge is the subscription, which you can cancel with **Cancel retainer**. ## Drafts - **Save draft** in the editor saves the client, terms, lines, prices, and conditions. A draft can be saved without a client; to send it you need one. - To pick it up again, open it and click **Continue editing**: the same editor opens (**Edit draft**). From there, every change saves itself a few seconds later and **Save and send** sends it. See [Preview and sending](/en/docs/cotizacion/envio). - **Delete draft** asks for confirmation ("This action cannot be undone. Delete this draft?") and removes it completely. Only drafts can be deleted: a quote that already went out isn't deleted, it's rejected or left to expire. ## Duplicate a quote 1. Open any quote, in any status. 2. Click **Duplicate quote**. 3. Cord creates a new draft with its own number and a 30-day validity, and takes you to it. The duplicate's activity notes which quote it was duplicated from. **What it copies:** client, payment terms, notes, and lines (description, quantity, list price, and price). **What the duplicate doesn't copy:** the sales currency (the duplicate is in MXN), the exchange rate, the deposit, the monthly retainer, **Prices include VAT**, each line's tax rate (it goes back to your catalog's default), each line's cost, the conversation, the signature, and the versions. Open the duplicate with **Continue editing** and check those fields before sending it. The duplicate counts as an active quote: if you've hit your plan's cap, it isn't created. ## Versions While a quote is *Sent*, *Viewed*, or *Expired*, **Modify and resend (V2)** opens the same quote editor as **New version of COT-0149** and, when you click **Send new version**, creates a new version on the same link (the old `/app/cotizaciones/[id]/editar` route only redirects to that editor): - you can change products, quantities, prices, each line's tax, and **Prices include VAT**; the client, currency, and terms (payment terms, validity length, deposit, retainer, and note) stay as they were sent; - if your organization uses [internal approvals](/en/docs/cotizacion/aprobaciones-internas), the version is checked against the caps before it's sent; - the quote goes back to *Sent*, its validity restarts from that day with the same length it was sent with (if it was 30 days, it expires in 30 days), and the client gets the email again if they have an email on file. That's how an *Expired* quote comes back; - the badge next to the client's name shows the current version (V1, V2, V3…); - **Version history** on the detail lists each version with its date and total. If the client has the link open, they see the changes live and must review them before approving (see [Negotiation and counteroffers](/en/docs/interaccion/negociacion)). ### When a version isn't enough To change something **Modify and resend** doesn't allow (client, currency, terms, or a different validity length), duplicate the quote, adjust it, and send the new link. Then, on the original (while it's still *Sent* or *Viewed*), use **Mark rejected** to take it out of the pipeline. Cord has no "Canceled" status: *Rejected* signals that link is no longer active. ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Active quotes (draft, sent, viewed, or approved) | 5 | 50 | No cap | No cap | No cap | | Sends per month | 5 | No cap | No cap | No cap | No cap | ## Common problems **I don't see Mark approved or Record payment.** Your role doesn't have the Approvals permission. **I can't delete a quote.** Only drafts can be deleted. **Cord says the quote can't move with this action.** The quote already changed status (for example, the client approved it while you had it open). Reload the detail. **The duplicate came out in MXN.** The duplicate doesn't copy the currency; change it with **Continue editing**. ## Related - [Home and views](/en/docs/gestion/dashboard) - [Negotiation and counteroffers](/en/docs/interaccion/negociacion) - [Internal approvals](/en/docs/cotizacion/aprobaciones-internas) - [Quotes API](/en/docs/desarrolladores/funciones/cotizaciones) --- # Home and quote views URL: https://docs.cordhq.app/en/docs/gestion/dashboard Last updated: 2026-10-08 What every Home widget shows and which time window it uses, how the KPIs and their change are calculated, how to customize the board with the widget library on desktop, keyboard, and mobile, and how to use the List and Board views in Quotes. ## What it is **Home** is the first screen when you sign in to Cord. At the top, pinned, is the **money indicator** with the date picker; below it, a board of widgets you can reorder, resize, hide, and extend from the **Widget library**. Your full pipeline lives in **Quotes**, with a **List** view and a **Board** view. ## Requirements | Requirement | Detail | |---|---| | Permission | Every member sees Home. The analytics widgets require **Reports**; **Receivables aging** and **Overdue invoices** require **Collections**. A widget your permission doesn't allow isn't drawn and doesn't appear in the library. | | Plan | The indicator, KPIs, funnel, trend, rankings, lists, and tasks are on every plan. **Expected cash flow**, **Pipeline health**, and **Needs follow-up** take their data from the finance panel, as do **Receivables aging** and **Expected pipeline**: all five exist from Pro; on Free and Starter they don't appear and the library doesn't offer them. | ## Everything in your business currency and time zone Every amount on Home is expressed in your **business currency** (the one in **Settings**), even if you sell in several. Each sale in another currency is converted with the exchange rate set on that quote or invoice and, when it has none, with today's published rate. If no exchange rate is available for a currency, those sales **are left out of the sum** instead of being added with a made-up rate. When you sell in more than one currency, this note appears under the indicator: > Amounts in \{currency}. Sales in \{currencies} are converted with the exchange rate set on each quote or invoice, or with today's published rate when there is none. and, if one was left out: "No exchange rate is available for \{currencies}, so those sales are not included for now." Days are counted in your **business time zone**: "today", "yesterday", and the cut-off of each day are yours, not the server's. ## The money indicator At the very top, pinned (it can't be moved or hidden), is the period amount with three metrics to choose from: | Metric | What it adds up | Date it uses | |---|---|---| | **Closed** | The total of won quotes (Approved, Paid, or Invoiced). | The approval date. | | **Collected** | Money that came in: quote and invoice payments, minus refunds. Same definition as the **Payments received** report. | The payment date. | | **Quoted** | The total of quotes that left draft. | The creation date. | Next to the amount you see the change **vs. previous period** and, below, the period's chart with the previous period as a reference. If the previous period adds up to zero, no change is shown: a "+100%" against nothing says nothing. ## Date picker The picker starts at **Last 30 days**. Options: **Today**, **Yesterday**, **Last 7 days**, **Last 30 days**, **Last 90 days**, **This month**, **Last month**, **This quarter**, **Year to date**, **Last 12 months**, and **Custom** (with **From**, **To**, **Cancel**, and **Apply**). Home keeps 12 months of history, so you can't pick an earlier date. - **The range is remembered in your browser**, not in the page address. When you come back to Home in the same browser you see the last range you picked; in another browser or device it starts at Last 30 days. An old link with `?rango=` is honored once and the address is cleaned up. - Changing the range updates the indicator, KPIs, funnel, trend, and rankings without reloading the page. Cards waiting for new data are marked busy instead of showing the previous range's numbers. As the note under the indicator says: "The range applies to revenue, trend, funnel and rankings. Receivables, pipeline and health always show today." ### Scope tag: Today, Range, or All time Every widget with data carries a tag that says which time window it measures. Hover over it to see the explanation: | Tag | Meaning (tooltip text) | |---|---| | **Today** | "A snapshot of right now; it does not follow the date picker." | | **Range** | "Follows the date range selected above." | | **All time** | "Your whole history, regardless of the range." | That way you don't compare a range number with a snapshot of today without noticing. ## KPIs with change **Close rate**, **Average ticket**, and the optional **Collected** follow the range, are compared against the previous period, and carry a mini chart. | KPI | How it is calculated | Subtitle | Change | Mini chart | |---|---|---|---|---| | **Close rate** | Of the quotes that **went out** in the range (by creation date), what percentage has been won. It is a cohort: it doesn't mix what was created in one period with what closed in another. | "\{g} of \{n} sent in the range" or "No quotes sent in this range" | In **points** (38% → 43% = 5 pts), not percent. | Progress bar with the rate. | | **Average ticket** | What closed in the range divided by the number of sales that make it up (by approval date). | "across \{n} closed quotes" or "No closed sales in this range" | In %. | Closed amount per day. | | **Collected** (optional) | Money that came in during the range, net of refunds. | "vs. \{amount} the previous period" or "No previous period to compare" | In %. | Collected amount per day. | Comparison rules: - **The previous period** has the same number of days and ends the day before your range starts. For "Last 30 days" it's the previous 30 days; for "This month" mid-month, the same number of days right before. - **No base, no change.** If the previous period is zero, or falls before the 12 months of history (for example with **Last 12 months**), the arrow isn't drawn and the subtitle says "No previous period to compare". - **The mini chart** goes by day up to about 45 days; for longer ranges it groups by week. - A KPI without data shows a dash (—), not a zero. ## The widgets In their default order: | Widget (name in the library) | What it shows | Scope | Requires | |---|---|---|---| | **In progress** | Sum of **Sent** and **Viewed** quotes, "\{n} active quotes", and a bar that splits how much is only sent and how much the client has already opened. | Today | — | | **Close rate** | See [KPIs with change](#kpis-with-change). | Range | Reports | | **Average ticket** | See [KPIs with change](#kpis-with-change). | Range | Reports | | **Needs follow-up** (KPI) | How many quotes are **Viewed** without a reply from the client. Opens Quotes. | Today | — | | **Conversion funnel** | Sent → Viewed → Approved → Paid for quotes created in the range. "Viewed" counts the client's first real open, even if they later rejected it. Each bar opens Quotes filtered: Sent and Viewed to open, Approved to approved, and Paid to paid. | Range | Reports | | **Pipeline** | Amount and count by status (Draft, Sent, Viewed, Approved, Paid); each segment opens Quotes with its filter. Link **View all →**. | Today | Reports | | **Monthly trend** | Quoted (bars) against closed (line). Groups by day for ranges up to 16 days, by week up to 70 days, and by month for longer ranges. | Range | Reports | | **Receivables aging** | Outstanding balances from quotes and invoices, by age. | Today | Collections · Pro or higher | | **Expected cash flow** | "Expected cash flow · 5 weeks": expected collections per week. Link **Treasury →** to the Cash flow · 90 days report. | Today | Reports · Pro or higher | | **Pipeline health** | Four indicators: **Avg. days to collect (DSO)** (Healthy up to 30 days, Watch up to 60, "High — speed up collection" after that), **Risk concentration** (Well diversified, Moderate from 40%, "Top client dominates the pipeline" from 70%), **Margin given up** (discount off list price), and **Expected revenue (weighted)** "of \{amount} in open pipeline". Link **View CFO →** to the Finance report. | Today | Reports · Pro or higher | | **Clients by approval rate** | The 5 clients with the best rate in the range. If at least three clients have two or more quotes, only those compete: a 1 out of 1 doesn't take first place. | Range | Reports | | **Products by revenue** | The 5 products with the highest amount in quotes that left draft in the range. | Range | Reports | | **Needs follow-up** (list) | Up to 5 open quotes with more than 7 days without activity, sorted by days of silence, with "\{n}d no reply", the amount, and the total number of cases. | Today | Reports · Pro or higher | | **Recent quotes** | The last 5 quotes with their status ("Recent"). Link **View all →**. | — | — | | **Activity** | The most recent events: sends, views, approvals, and payments. | — | — | | **Tasks** | "Tasks and reminders": the 8 most urgent pending tasks, with a quick-add field and a **Mine**/**All** filter when there is more than one person. See [Tasks](/en/docs/gestion/tareas). | — | — | ### Optional widgets (start hidden) These live in the library until you add them. A new widget never shows up by surprise on a board you already customized. | Widget | What it shows | Scope | Requires | |---|---|---|---| | **Sent to paid** | Percentage of sent quotes that ended up paid, with the Sent / Paid breakdown. "Conversion across your whole history". | All time | Reports | | **Expected pipeline** | Probability-weighted open pipeline today, with the unweighted open pipeline. | Today | Reports · Pro or higher | | **Collected** | KPI with change and mini chart: "Money that came in during the range and how it compares to the previous period". | Range | Reports | | **Days to close** | "Average days from creating a quote to winning it". | All time | Reports | | **Overdue invoices** | "\{n} overdue · \{amount}" and the overdue invoices that weigh the most, with "\{n} d overdue" and their balance. Link **View all →** to Invoices. | Today | Collections | | **Sales leaderboard** | "Who on the team closes the most value": the 5 members with the highest closed amount. Link **View all →** to Performance. | All time | Reports | Without the **permission**, the widget disappears: it isn't drawn, its data doesn't reach your browser, and the library doesn't offer it. Without the **plan**, the same happens with Expected cash flow, Pipeline health, Needs follow-up, Receivables aging, and Expected pipeline: they don't appear, instead of showing empty or zero as if your receivables were empty. ## Customize Home ### Entering and leaving edit mode 1. Click **Customize** (sliders icon) in the top bar. 2. Three round icon buttons replace it, each with its name in a tooltip on hover: - **Library** (grid with a +): opens the [Widget library](#the-widget-library). It shows a counter with how many widgets you have to add. - **Reset** (undo arrow): asks "Reset the dashboard's widget order and hidden widgets?" and, if you confirm, goes back to the default order, sizes, and widgets. Optional widgets go back to the library. - **Done** (check mark, navy fill): leaves edit mode. 3. While you edit, widget content doesn't respond to clicks (so you don't open a quote by accident while dragging) and each widget shows its control bar. ### Desktop - **Move:** drag the widget from anywhere on it; the others rearrange as you move it and the page scrolls by itself near the edge. **Move up** and **Move down** do the same with one click. - **Size:** **Compact** or **Expanded**. It only appears on widgets that have two sizes; an indicator without a chart or detail has a single honest size. In Expanded, lists use two columns and KPIs put the mini chart beside the number. - **Hide:** the X button. The widget moves to the library and the **Library** button pulses once and adds one to its counter. Hiding a widget doesn't delete data or change calculations. ### Keyboard All of edit mode works with a keyboard: - Tab goes through each widget's **Move up**, **Move down**, **Compact**, **Expanded**, and **Hide**; focus stays on the widget you moved. - Escape closes the library if it's open and returns focus to its button; otherwise it leaves edit mode and returns focus to **Customize**. During a drag, it cancels it and the widget goes back to its place. - Screen readers announce "\{widget} moved", "\{widget} added to the board", and "\{widget} hidden; find it in the library". ### Mobile Below 880 px widgets stack in one column and can't be dragged. In edit mode, each widget shows **Move up**, **Move down**, and **Hide** as 44 px buttons; the size selector isn't shown. The three top-bar buttons are also 44 px and have no tooltip. ## The widget library Click **Library** in edit mode. On desktop it opens as a **floating card** anchored to the button; on mobile, as a **bottom sheet** over a dimmed background. - **Header:** "Widget library" and the summary "\{n} to add · \{m} on screen". The X ("Close library") closes it. - **Search:** "Search widgets…" searches the name, the description, and the category. With no matches it says "No results". - **Categories**, each with its count: **All widgets**, **To add**, and one per group: **KPIs**, **Pipeline**, **Finance**, **Rankings**, and **Activity** (a widget without a group falls under **Other**). Group categories only appear when the board has more than one group. - **Cards:** each widget comes with a **thumbnail** drawn with the same data it has on your board today (your range, your numbers), its name, and its description. The ones you can add come first. - **Add:** the **+** button ("Add \{widget}") puts it on the board, scrolls it into view, and highlights it for a moment. The ones already visible show a check mark and **On screen**, disabled. - **It isn't modal:** with the library open on desktop you can keep rearranging the board and add several widgets in a row. Escape or a click outside closes it. On mobile, the sheet closes by itself after you add so you see where the widget landed, and the search box isn't focused automatically (the keyboard would cover the sheet). - **What you can't use doesn't appear.** A widget your permission or plan doesn't allow isn't in the library, and a layout saved before you lost access doesn't bring it back. ## Where your layout is saved Your layout (order, sizes, and hidden widgets) is **personal**: it's saved in your browser and in your user for that organization, so it follows you to other devices. If you change the layout on two devices, the most recent complete change wins, without mixing the two. It doesn't change what your teammates see, and each organization you belong to has its own layout. Every screen with widgets saves its own separately: Home, each report in [Reports](/en/docs/gestion/informes), [Payments](/en/docs/pagos/dashboard), [Collections](/en/docs/pagos/cartera-cobranza), [AI collections](/en/docs/pagos/cobranza-ia), and Performance use the same buttons and the same library. ## Quotes: List and Board In **Quotes**, above the list you see the value of your open quotes, the value already approved and, if there are internal approval requests, how many are **awaiting your approval**. ### List view The default view is a table with **Quote**, **Client**, **Terms**, **Valid until**, **Total**, and **Status**. The filter pills carry their counts; each filter is described in [Quote management](/en/docs/gestion/cotizaciones). Click a row to open the detail. ### Board view Click **Board**, next to **List**. Each column shows its number of quotes and the sum of their totals: | Column | Statuses it groups | |---|---| | **Draft** | Draft | | **Sent** | Sent | | **Viewed** | Viewed | | **Approved** | Approved | | **Paid** | Paid and Invoiced | Rejected and expired quotes don't appear on the board; you find them in the List with the **Closed** filter. ### Valid moves on the board Dragging a card **runs the real action**, it doesn't just change a label. There are only three valid destinations; the column turns green when the move is allowed: | You drag to | From | What it does | Permission | |---|---|---|---| | **Sent** | Draft | Sends the quote exactly like **Send to client**: activates the link, emails the client if they have an email, and on Free uses one of the month's sends. | Quotes | | **Approved** | Sent or Viewed | Marks it as approved on the client's behalf, like **Mark approved**: enables payment and, if you asked for a deposit, creates the payment plan. No client signature is recorded. | Approvals | | **Paid** | Approved or Invoiced | Records the payment manually, like **Record payment**, and cancels pending online charges. | Quotes | Any other move, including moving a card back, is rejected with "That move isn't valid in the pipeline." If the server rejects the action (for example, over permissions or the send cap), the card returns to its column and you see the reason. **There's no board on mobile.** Below 880 px, Quotes shows only the list, with each quote on two lines. To move a quote forward, open it and use the detail's buttons. ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Indicator, KPIs, funnel, trend, rankings, lists, tasks, and board | Yes | Yes | Yes | Yes | Yes | | Expected cash flow, Pipeline health, Needs follow-up | Not shown | Not shown | Yes | Yes | Yes | | Receivables aging, Expected pipeline | Not shown | Not shown | Yes | Yes | Yes | | Customize and library | Yes | Yes | Yes | Yes | Yes | ## Common problems **I don't see the funnel or the trend, and they aren't in the library either.** Your role doesn't have the Reports permission. Ask whoever manages the team. **I don't see Expected cash flow, Pipeline health, or Needs follow-up.** Your plan doesn't include the finance panel (Pro or higher) or your role lacks the Reports permission. **Pipeline health or Expected cash flow shows zeros.** You have no open quotes and no collections expected in the coming weeks. **I changed the range and a widget didn't change.** Check its tag: **Today** and **All time** don't follow the picker. **The change doesn't appear.** The previous period is zero or falls outside the 12 months of history. **An amount looks low and I sell in several currencies.** Read the note under the indicator: a currency without an available exchange rate is left out of the sum until one exists. **I see a different range on another device.** The range is remembered per browser; the board layout does follow you. **I can't drag a widget.** You're on a phone (use **Move up** and **Move down**) or you haven't clicked **Customize**. **I can't drag a card on the Quotes board.** You're on a phone, or the destination isn't valid for the current status. ## Related - [Reports and performance](/en/docs/gestion/informes) - [Custom reports and email delivery](/en/docs/gestion/informes-personalizados) - [Quote management](/en/docs/gestion/cotizaciones) - [Tasks and follow-up](/en/docs/gestion/tareas) - [Complete app map](/en/docs/operacion/mapa-de-la-app) - Support: [Customize Home and its widgets](https://cordhq.app/en/support/personalizar-inicio-widgets) - Support: [Read the KPIs and the date picker](https://cordhq.app/en/support/leer-kpis-y-rango) - Support: [Amounts in multiple currencies and time zone on Home and in reports](https://cordhq.app/en/support/importes-en-varias-divisas-informes) --- # Reports and sales performance URL: https://docs.cordhq.app/en/docs/gestion/informes Last updated: 2026-10-11 Cord's 15 reports one by one: what each answers, its KPIs, columns, and chart, what follows the range and what is a snapshot of today, how the previous-period comparison works, how CSV export works, how currency is converted, the custom report you can save and get by email, and how performance is attributed by team member. **Reports** is Cord's analytics surface: "One place to understand performance and decide what to move." It brings together **15 reports in 7 groups** behind one picker. Seven are **widget reports** (customizable boards), seven are **table reports** (compared KPIs, a chart, a table with totals, and CSV export), and one is the **Custom report**, where you choose how to group and what to measure. **Performance**, in the same menu group, compares the people on the team. ## Where it is and how to pick a report **Reports** is in the side menu, under the **Insights** group (shortcut G then A). At the top right is the **report picker**: click the current report's name to open it. - The panel groups reports by category: **Overview**, **Sales**, **Clients**, **Products**, **Finance**, **Team**, and **Custom**. Only categories with a report your permission allows appear. - Under each name it says **Date range** or **As of today**. - **Search reports** filters by name in Spanish and English. - With a keyboard: the search box gets focus when the panel opens, ↑ and ↓ move through the list, Enter opens the report, and Escape closes the panel. - Your organization's [saved reports](/en/docs/gestion/informes-personalizados) appear at the end, under **Custom**, labeled **Saved report**. Each report has its own address (`/app/informes?r=...`), so you can bookmark it or share it with a teammate who has the permission. ## The 15 reports | Group | Report | What it answers | Type | Scope | Permission | Plan | |---|---|---|---|---|---|---| | Overview | **Overview** | Close rate, closed and lost value, velocity, and maturity. | Widgets | Range | Reports | All | | Overview | **Commercial diagnosis** | Funnel, pipeline, stalled quotes, discount given, and time per stage. | Widgets | Range, with today widgets | Reports | All | | Sales | **Sales over time** | How much you quote, win, and collect, period by period. | Table | Range | Reports | All | | Sales | **Sales by client** | What each client bought, their ticket, their last purchase, and what they owe you today. | Table | Range | Reports | All | | Sales | **Sales by product** | Units, amount, margin, and close rate for each product. | Table | Range | Reports | All | | Clients | **Clients** | Value and conversion by client, cohorts, and inactive clients. | Widgets | Range, with today widgets | Reports | All | | Clients | **Repeat purchase by cohort** | Of the clients who first bought each month, how many came back. | Table | As of today (last 12 months) | Reports | All | | Products | **Products** | Amount, volume, discount elasticity, and close rate by product. | Widgets | Range | Reports | All | | Finance | **Payments received** | Every payment that came in, from quotes and invoices, with its method and refunds. | Table | Range | Reports and Collections | All | | Finance | **Invoiced taxes** | Taxes and withholdings from issued invoices, month by month. | Table | Range | Reports | All | | Finance | **Finance** | MRR, ARR, DSO, MRR at risk, weighted pipeline, and concentration. | Widgets | As of today | Reports | Pro or higher | | Finance | **Cash flow · 90 days** | Receivables, probable pipeline, retainers, and near-term concentration. | Widgets | As of today | Reports | Pro or higher | | Finance | **Collections and receivables** | Open, overdue, aging, promises, and payment behavior. | Widgets | As of today | Reports and Collections | Pro or higher | | Team | **Sales by team member** | What each person quoted and closed, with their close rate and time to close. | Table | Range | Reports | All | | Custom | **Custom report** | Group and measure however you want. | Explorer | Range | Reports | All | ### If you're missing the permission or the plan Each reason asks for a different action, and the screen tells them apart: - **Without the Reports permission** you see no report: "No access. Your current role doesn't have permission to view analytics. Contact your organization's admin." - **Without the Collections permission**, Payments received and Collections and receivables don't appear in the picker; if you open their link, you see "Restricted report" and a prompt to ask for the permission. - **Without the plan**, Finance, Cash flow, and Collections do appear in the picker, but when you open them you see what they offer and the button to go to **Settings › Plans & subscription**. For example, Cash flow says "How much cash is coming in over the next 90 days". The permission is called **Reports** in **Settings › Team & permissions**. See [Team and security](/en/docs/cuenta/equipo-seguridad). ## Dates, time zone, and currency ### The date picker **Date range** reports show the picker next to the report picker: **Today**, **Yesterday**, **Last 7 days**, **Last 30 days**, **Last 90 days**, **This month**, **Last month**, **This quarter**, **Year to date**, **Last 12 months**, and **Custom**. You can look back up to one year. - When you open a report, the range comes, in this order: from the link's address; if it has none, from the last range you used **in that report** in this browser (each report remembers its own); otherwise, **Last 30 days**. - The range is written into the page address, so a copied link opens the same period for whoever receives it. - In widget reports, changing the range repaints the numbers without reloading. In table reports, the page reloads because the table, totals, and CSV are built in full on the server. **As of today** reports have no picker (there would be nothing to ignore): they show the label "As of today · \{date}". Inside a range report, widgets tagged **Today** also ignore the range; hover over the tag to see the explanation. ### Time zone Days are cut in your **business time zone**: "today", the start and end of each day, and weeks and months are yours. A payment on the 31st at 11 p.m. in your city counts in that month even if it's already the 1st in another zone. ### Currency: everything in your business currency If you sell in several currencies, Cord doesn't add up amounts in different currencies as if they were one: it **restates everything in your business currency**, the one set in Settings. For each amount it uses the best real rate available: 1. if the sale is already in your business currency, as is; 2. if the quote's or invoice's accounting currency is your business currency, the **exchange rate set on that document** (the same one the invoice declares); 3. otherwise, **today's published** exchange rate. If no exchange rate is available for a currency, its amounts **are left out of the sum**; Cord never makes up a rate. Below the report you see the note: > Amounts in \{currency}. Sales in \{currencies} are converted with the exchange rate set on each quote or invoice, or with today's published rate when there is none. and, if a currency was left out: "No exchange rate is available for \{currencies}, so those sales are not included for now." If you sell in a single currency, the note doesn't appear. ### Which date each measure uses | Measure | What it counts | Date | |---|---|---| | **Quotes** / **Quoted** | Quotes that left draft (including ones later rejected or expired). | Creation | | **Sales** / **Sold** | Won quotes: Approved, Paid, or Invoiced. Sold is their total, including taxes and minus withholdings. | Approval | | **Close rate** | Of what went out in the range, what percentage was won (cohort). | Creation | | **Collected** | Money that came in. | Payment | | **Balance today**, receivables, pipeline | Snapshot of the moment. | Today | **"Collected" means the same thing across Cord** (Home, Reports, and Payments): quote payments (deposits, installments, retainers) plus payments applied to invoices, plus quotes marked paid by hand without any recorded payment, **minus refunds**. An invoice payment that already came from a quote charge isn't counted twice. A close rate is calculated on the **cohort**: the quotes created in the range. A recent cohort still has open quotes, so its rate can look low without the team selling worse. Compare against a cohort of the same age or check **Cohort maturity** in Overview. ## How to read table reports The seven table reports (Sales over time, Sales by client, Sales by product, Payments received, Invoiced taxes, Repeat purchase by cohort, and Sales by team member) and the Custom report share the same structure, top to bottom: 1. A one-line **description** of what the report answers. 2. **KPIs** compared against the previous period. 3. **Chart.** 4. The full **table**, sortable and with a **Total** row. 5. Notes specific to the report (margin, cohorts) and the currency note. ### KPIs and the previous-period comparison Each KPI shows its value, an arrow with the change and, below, "vs. \{value} the previous period". - **The previous period** has the same number of days as your range and ends the day before your range starts. September 1–30 is compared against the 30 days before (August 2–31), not against "August". - **Amounts and counts** change in **percent**. **Rates and percentages** (close rate, margin %, returning clients) change in **points**: from 38% to 43% is "5 pts", not "13%". - **No base, no arrow.** If the previous period is zero, the arrow doesn't appear. If there's no previous value, the line says "No previous period to compare". - With **Last 12 months** there's no comparison: the previous period would fall outside the queryable year. Repeat purchase by cohort doesn't compare either: it's a snapshot of today. ### The table - **Sort:** click a column header. The first click sorts from highest to lowest; the second, lowest to highest. Empty cells always go last. - **Total row:** at the bottom, pinned. It adds up what can be added; rates and averages in the total are those of the full period, not the sum of the rows. A column that isn't added stays blank. - **Links:** when the first column is a client, a catalog product, a quote, or an invoice, it links to its record or detail. - **Reading:** the header and first column stay pinned as you scroll. A dash (—) means "not applicable or no data", not zero. - **No data:** "No data in this range. Adjust the date range or come back once there is activity in this period." - **Mobile:** KPIs go in two columns, the table scrolls sideways with the first column pinned, and buttons are 44 px. ### The chart and drill-down - In **client** and **product** charts, each bar opens that client's or product's record. - In **Sales over time** and in the Custom report grouped by **Month** or **Week**, each bar opens that month or week. The period is trimmed to your range: if the range starts on the 15th, the month's bar opens the 15th through month end. - On desktop, a click (or Enter with focus on the bar) navigates directly. On mobile, the first tap shows the value and the tooltip includes **View detail →**. ### Export CSV **Export CSV**, at the top right, downloads exactly what you see: the same report, the same range and, in Sales over time, the same grouping. The button appears when the table has rows. | Aspect | Format | |---|---| | File name | `cord-{report}-{from}_{to}.csv`, for example `cord-ventas-cliente-2026-09-01_2026-09-30.csv`. Repeat purchase by cohort uses today's date: `cord-recompra-2026-10-08.csv`. | | Encoding | UTF-8 with BOM, so Excel opens accented characters correctly. Comma separator and Windows line breaks. | | Headers | The same as the table, in your account language. | | Amounts | As a **number**, with no symbol or thousands separator and a period as decimal point (`196469.20`). Whole numbers carry no decimals. | | Currency | If the report has any money column, a **Currency** column is added at the end with your business currency on every row. | | Percentages | As a whole number: `42` means 42%. | | Dates | `YYYY-MM-DD`. In period reports, the date is the first day of the period. | | Empty values | Empty cell (on screen they show as —). | | Total row | Not exported: the file carries only the rows, so you can sum and filter your own way. | | Protection | Text that starts with `=`, `+`, `-`, `@`, tab, or carriage return is exported with a leading apostrophe, so a spreadsheet doesn't run it as a formula. Amounts are left alone. | ## Table reports, one by one ### Sales over time "How much you quote, win and collect, period by period. Sales by close date; collected by payment date." - **KPIs:** Sold, Sales, Average ticket, and Collected. - **Chart:** Sold per period, as bars. - **Columns:** Period, Quotes, Quoted, Sales, Sold, Average ticket, Collected. **Every** period in the range appears, even at zero. - **Day / Week / Month grouping:** at the top right. If you don't choose, Cord decides by the range's length: **day** up to 31 days, **week** up to 124 days, and **month** after that. Weeks start on Monday. The first and last periods can be partial if your range doesn't start on a Monday or on the 1st. - Each column uses its own date: Quotes and Quoted by creation, Sales and Sold by approval, Collected by payment date. That's why a row can have sales without quotes: something quoted earlier was won in that period. ### Sales by client "Each client with what they bought in the range, their ticket, last purchase and what they owe you today." - **KPIs:** Clients who bought, Sold, Average ticket, and **Returning clients**: the percentage of clients who bought in the range that had bought from you before (changes in points). - **Chart:** the 8 clients with the most sold, as horizontal bars; each bar opens their record. - **Columns:** Client, Quotes (sent in the range), Sales, Sold, Average ticket, **Last sale** and **Client since** (from your whole history, not the range), and **Balance today**: what they owe you right now across quotes and invoices, with partial payments deducted. - Every client that received a quote or bought from you in the range appears, sorted by sold, up to 500 rows. Quotes without an assigned client aren't included. ### Sales by product "Which products sell, how many units, at what margin and how often they win when quoted." - **KPIs:** Units, Sold, Gross margin, and Margin %. - **Chart:** the 8 products with the most sold; each bar opens the product's record. - **Columns:** Product, SKU, Units, Sales (won quotes that include it), Sold, Gross margin, Margin %, Close rate (of the quotes created in the range that included it, how many were won). Totals for Units, Sold, Gross margin, and Margin %. - **Sold here is per line:** negotiated (or list) price times quantity, **before taxes** and the document-level discount. That's why it doesn't match Sold in Sales over time, which uses the quote total. - A free-text line, without a catalog product, appears with its description and no link. Lines the client didn't approve in a partial approval don't count. - **Margin:** "Margin only counts lines with a cost captured when quoting; without a cost, the line counts toward sales but not margin." The cost is what the product had when it was quoted; a zero cost is treated as "I don't know", not "it was free". With no line carrying a cost, margin shows as —. ### Payments received "Every payment that came in, from quotes and invoices, with its method and refunds." It also requires the **Collections** permission. - **KPIs:** Net collected, Gross collected, Refunded, and Payments. - **Chart:** net collected by method. - **Columns:** Date, Number, Client, Method, Amount, Refunded, Net. One row per payment, newest first, up to 1,000 rows. The number opens the quote or invoice. - **Methods:** Card, SPEI, Bank transfer, Cash, Mercado Pago, Online payment, and **Recorded manually** (a quote marked paid without any recorded payment). A method Cord doesn't name yet appears as is. A [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) collected in EUR, GBP, or USD appears as **Bank transfer**, like a transfer recorded by hand. - A refund is subtracted from the payment it belongs to, on that payment's date. This is the "Collected" definition used by Home and Sales over time. ### Invoiced taxes "Taxes and withholdings from issued invoices, month by month: what you report." - **KPIs:** Taxes, Withholdings, Subtotal, and Invoices. - **Chart:** taxes by month. - **Columns:** Month, Invoices, Subtotal, Taxes, Withholdings, Total. Always by month. - It comes from **issued invoices** by issue date, not from quotes. It doesn't count drafts, voided invoices, or credit notes (those aren't subtracted here). - It's a supporting read for your bookkeeping, not a filing: confirm it with your adviser. ### Repeat purchase by cohort "Of the clients who first bought each month, how many came back to buy again." It's an **As of today** snapshot: no picker and no comparison. - **KPIs:** New clients (12 months) and Repeat purchase next month (of the cohorts that have already reached one month). - **Heat map:** one row per month of first purchase over the last 12 months, with Cohort, Clients, and **Month 1** through **Month 6**. Each cell is the percentage of that cohort that bought again that many months later; darker means more repeat purchases. - "A dash is a month that cohort has not reached yet": the August cohort has no Month 3 in October. It isn't 0%. ### Sales by team member "What each team member quoted and closed in the range, with their close rate and time to close." - **KPIs:** Sold, Sales, Average ticket, and Members with sales. - **Chart:** the 8 members with the most sold. - **Columns:** Team member, Sent (created in the range and out of draft), Sales, Sold, Close rate (of their quotes sent in the range, how many they won), Average ticket, and Days to close (average days from creation to approval, with one decimal). - Each quote is attributed to the person who **created or duplicated** it. The table lists **active members**, even without sales. What people who have left the team created is grouped in a **Former team members** row, so the Total row matches the KPIs. Quotes without a creator (before attribution or created via the API) appear in neither the table nor the KPIs. ## Widget reports, one by one These are boards you can [customize](#customizing-a-reports-widgets). Widgets marked **optional** start hidden and are added from the library. ### Overview Cohort of quotes created in the range. | Widget | What it shows | |---|---| | **Close rate** | Won over sent: "\{g} / \{n} sent quotes". | | **Closed value** | Total won from the cohort created in the range. | | **Pipeline velocity** | Closed value per day of the range. | | **Lost value** | Rejected plus expired, with their count. | | **Commercial movement** | Closed value by quote creation date. | | **Cohort maturity** | What happened to quotes created in the range: Won, Lost, and Still open. With no sends in the range, it stays empty. | | **Decided quotes** (optional) | Won, rejected, or expired in the cohort. | ### Commercial diagnosis | Widget | What it shows | Scope | |---|---|---| | **Where conversion breaks** | Funnel sent → viewed → approved → paid. The base includes every quote that went out, even if rejected or expired; "viewed" is the client's first real open. | Range | | **Pipeline** | Amount and count by open or won status. | Today | | **Stalled** | "Quotes that need a next move": up to 5 sent or viewed quotes with no activity in 7 days or more, by amount. | Today | | **Negotiation cost** | Products with the most discount given up against list price. Requires Starter or higher. | Range | | **Median time by stage** | Created → sent, Sent → viewed, Viewed → approved, Approved → paid, in days. The median keeps a few outliers from distorting the cycle. | Range | | **Stalled follow-ups** (optional) | How many quotes have been inactive for seven days or more; it counts all of them, even though the Stalled list shows only the 5 with the highest amount. | Today | ### Finance Snapshot of today. Pro plan or higher. | Widget | What it shows | |---|---| | **MRR** | Contracted MRR: monthly amount of active retainers. | | **ARR** | Annualized MRR; not money already received. | | **DSO** | Estimated time to collection, based on your history. | | **MRR at risk** | Retainers with a late payment or set to cancel at period end. | | **Weighted pipeline** | Pipeline by client weighted by probability and timing, based on your history. Not guaranteed cash. | | **Concentration** | How much of the pipeline depends on the largest client. | | **Profitability by tier** | By client tier: average discount, close rate, number of sends, and closed value. | | **Active retainers** (optional) | Contracts contributing recurring revenue, with MRR and ARR. | ### Cash flow · 90 days Snapshot and forecast as of today. Pro plan or higher. The forecast separates three sources: **certain receivables** (approved or invoiced balances, with an estimated collection date), **pipeline** (open opportunities weighted by probability), and **retainers** (recurring installments within the horizon). The total is an expected scenario, not a bank balance. | Widget | What it shows | |---|---| | **Expected inflow** | Next 90 days: receivables + pipeline + retainers. | | **Beyond horizon** | What's expected from day 91, so it doesn't disappear from view. | | **MRR** | Active retainers and their count. | | **Certain receivables** | Outstanding balances not weighted by close rate. | | **30-day concentration** | Which clients concentrate what you expect to collect in 30 days. | | **Weekly flow** | Weekly flow · 90 days. | | **Cumulative cash** | Cumulative cash curve. | | **Expected daily inflow** (optional) | Daily forecast without accumulation. | ### Collections and receivables Snapshot of today. Pro plan or higher and the Collections permission. It uses the same receivables as the [Collections](/en/docs/pagos/cartera-cobranza) module: approved unpaid quotes and open invoices, with partial payments deducted. | Widget | What it shows | |---|---| | **Receivables** | Outstanding amount and number of documents. | | **Overdue** | Total overdue and number of accounts. | | **Expected collections** | What you expect to collect in 30 days: certain receivables, estimated timing. | | **Average delay** | Average days late against agreed terms. | | **Aging** | Not yet due, 1–30 days, 31–60 days, and 60+ days. | | **Client exposure** | Open balance against the configured credit limit. | | **Promise compliance** | Kept, broken, and overdue pending promises. A promise records the commitment; it doesn't move money. | | **Actual vs. agreed DSO** | How many payments arrive On time, 1–7 days late, 8–30 days late, and 30+ days late. | | **Outstanding documents** (optional) | Documents awaiting collection today and their amount. | ### Clients | Widget | What it shows | Scope | |---|---|---| | **Clients by closed value** | Who converts value, not just quote volume. | Range | | **Client conversion** | Approved over quotes and rate, with closed value; each row opens the record. | Range | | **New vs. returning** | New (their first quote falls in the range) against returning. | Range | | **Clients at risk** | Clients with history and no quotes in 90 days, by closed value. | Today | | **Tier and behavior** | Tier × payment behavior matrix (on time, slightly late, late). | Today | | **Relationships to reactivate** (optional) | How many clients with history have been inactive for 90 days; it counts all of them, even though the Clients at risk list shows only the 10 with the most closed value. | Today | ### Products | Widget | What it shows | |---|---| | **Products by quoted amount** | Demand inside the selected range. | | **Product volume** | Quoted units and proposal presence. | | **Discount elasticity** | Close rate by discount band, with the sample size. It uses your whole history and requires Starter or higher. | | **Close rate by product** | Which products win, not only which are quoted. | | **Units by product** (optional) | Quoted units in the selected range. | ## Customizing a report's widgets The seven widget reports have the **Customize** button, with the same controls as Home: **Library**, **Reset**, and **Done** as icon buttons; drag, **Move up**, **Move down**, **Compact**/**Expanded**, and hide; full keyboard support and, on mobile, 44 px buttons. **Reset** asks "Reset this report?". The full explanation is in [Home and views](/en/docs/gestion/dashboard#customize-home). - **Each report saves its own layout**, and the layout is yours: it doesn't change what your teammates see. - Hiding a widget doesn't delete data or change calculations. - Table reports and the Custom report aren't customized with widgets: their configuration is the table itself. ## Custom report and saved reports When no report answers your question, the **Custom report** lets you choose how to group (client, product, team member, status, month, week, day, country, client tier, or currency) and up to six metrics, save it with a name for the whole team, and receive it every Monday or every 1st by email with the CSV attached. - **Save changes** or **Delete** on a saved report: whoever saved it or an admin. Deleting it doesn't delete any data. - **Delivery** goes only to you, with the complete period that just ended. Only whoever saved the report can schedule it, and it stops arriving if that person leaves the team or loses the Reports permission. - **Cap:** 50 saved reports per organization. The full detail is in [Custom reports and email delivery](/en/docs/gestion/informes-personalizados). ## Performance by team member There are two places to look at the team, for different questions: | | **Sales by team member** (report) | **Performance** (page) | |---|---|---| | Where | Reports › Sales by team member (Team group) | Side menu, **Insights** group (shortcut G then E) | | Period | The range you choose, with comparison | Whole history | | Columns | Sent, Sales, Sold, Close rate, Average ticket, Days to close | Quotes, Close, Closed, Collected, Ticket, Days | | Exports CSV | Yes | No | **Performance** requires the Reports permission and is a customizable widget board: **Closed by the team** (approved, paid, and invoiced, with collected and unassigned in the detail), **Average close rate** ("of what each rep sent"), **Leading seller**, **Active reps**, **Contribution to closed sales**, **Sales activity**, **Ranking by rep** (by amount closed, with your row marked **You**), and the optional **Team average deal**. Amounts are in your business currency. Both attribute each quote to the person who created or duplicated it. Documents without a creator appear in Performance as **Unassigned** ("from before this report or via API"). Cord doesn't redistribute that history or credit a sale to the last editor. The team rate in Performance is the average of each rep's rate; it isn't a commission or a payroll calculation. ## Common problems **A report doesn't appear in the picker.** Check the Reports permission; Payments received and Collections and receivables also require Collections. Finance, Cash flow, and Collections do appear without the plan, but ask for Pro or higher when opened. **Changing dates doesn't modify a widget.** It's a snapshot of today: it carries the **Today** tag. **A recent cohort's closed value looks low.** Part of it is still open; check maturity and compare again once your normal sales cycle has passed. **A total doesn't match between two reports.** Check which date each measure uses: Sold goes by approval date, Quoted by creation, and Collected by payment date. In Sales by product, Sold is per line and before taxes. **Sales in another currency are missing.** Read the currency note: if a currency has no exchange rate available, its sales are left out of the sum for now. **I don't see the change arrow.** The previous period is zero, you picked Last 12 months, or the report is a snapshot of today. **I don't see the Export CSV button.** The table has no rows in that range, or you're in a widget report: those don't export. **The CSV opens with odd characters.** Open it with Excel or Google Sheets directly; the file carries the UTF-8 mark they need. If you import it by hand, choose UTF-8 and comma as the separator. **I can't schedule delivery for a saved report.** Only whoever saved it can schedule it. Click **Save** to create your own copy and schedule that one. **A close doesn't appear in Sales by team member.** The quote doesn't keep the person who created it (it predates attribution or was created via the API). If whoever created it is no longer active on the team, the sale appears in the **Former team members** row. ## Related - [Custom reports and email delivery](/en/docs/gestion/informes-personalizados) - [Home and views](/en/docs/gestion/dashboard) - [Receivables and collections](/en/docs/pagos/cartera-cobranza) - [Treasury and FX Lock](/en/docs/pagos/tesoreria-fx) - [Team and security](/en/docs/cuenta/equipo-seguridad) - Support: [Cord's reports: which one answers which question](https://cordhq.app/en/support/informes-de-cord) - Support: [Export a report to CSV (Excel and Google Sheets)](https://cordhq.app/en/support/exportar-informes-csv) - Support: [Amounts in multiple currencies and time zone on Home and in reports](https://cordhq.app/en/support/importes-en-varias-divisas-informes) --- # Custom reports and email delivery URL: https://docs.cordhq.app/en/docs/gestion/informes-personalizados Last updated: 2026-10-08 How to build your own report in Cord: every grouping and every metric with its exact definition, which metrics don't apply to which grouping, how to share it with a link, save it for the whole team, and receive it every Monday or every 1st by email with the CSV attached. ## What it is The **Custom report** is the explorer in [Reports](/en/docs/gestion/informes): "Choose how to group and what to measure. Counts the quotes created in the range and what happened to them." You decide the row (**Group by**) and the columns (**Metrics**), and Cord builds the same kind of table report as the others: KPIs compared against the previous period, a chart, a sortable table with totals, and **Export CSV**. When a configuration works for you, you **save** it with a name: it stays in the report picker for the whole team and, if you want, it reaches you **by email** every Monday or every 1st with the CSV attached. ## Requirements | Requirement | Detail | |---|---| | Plan | Every plan, including Free. | | Permission | **Reports**, to view, build, save, and receive custom reports. | | Edit or delete a saved report | Whoever saved it, or a **Super admin** or **Admin** of the organization. | | Schedule email delivery | Only whoever saved the report. A Super admin or Admin can turn it off, not on. | ## Opening it 1. Go to **Reports** (side menu › **Insights**). 2. Open the report picker and choose **Custom report**, in the **Custom** group. 3. The first time, it starts grouped by **Client** with **Quotes**, **Sales**, **Sold**, and **Close rate**, over **Last 30 days**. Above the table is the explorer bar: **Group by**, the **Metrics** chips and, on the right, **Save**. ## The cohort: which quotes are included The explorer measures **a single cohort**: the quotes **created in the range** that left draft (Sent, Viewed, Approved, Paid, Invoiced, Rejected, or Expired). Each row answers: "of what was quoted in this period, what happened?". - **Drafts don't count.** - **A sale counts in the cohort where the quote was created**, even if it was won after the range ended. That's why the explorer's Sold may not match **Sales over time**, which counts sales by approval date. - **Dates in your time zone** and **all amounts in your business currency**, with the same conversion as the rest of Reports: the rate set on the quote first, today's published rate after that; a currency without a rate is left out of the sum and the currency note says so. See [Dates, time zone, and currency](/en/docs/gestion/informes#dates-time-zone-and-currency). ## Group by Each option decides what a row is. There are ten: | Group by | A row is | Details | |---|---|---| | **Client** | One client. | Quotes without a client are gathered under **No client**. The row and the bar open the client's record. | | **Product** | A catalog product or, for free-text lines, its description. | Measures **per line**, not per quote (see below). A catalog product opens its record; a free-text line has no link. Lines the client didn't approve in a partial approval don't count. | | **Team member** | The person who created or duplicated the quote. | Without a creator (before attribution or created via the API): **No team member**. | | **Status** | The quote's **current** status: Sent, Viewed, Approved, Paid, Invoiced, Rejected, or Expired. | Useful to see where the cohort ended up. | | **Month** | A creation month. | In chronological order. Each bar opens that month grouped by **Week**. | | **Week** | A creation week, Monday to Sunday. | Each bar opens that week grouped by **Day**. | | **Day** | A creation day. | In chronological order. | | **Country** | The client's country, named in your account language. | Clients without a country: **No data**. | | **Client tier** | The tier assigned to the client. | Clients without a tier: **No data**. | | **Currency** | The quote's sale currency (MXN, USD, EUR…). | Each row's amounts are still expressed in your business currency: the row tells you how much you sold **in** that currency, converted. | By **Client**, **Product**, **Team member**, **Status**, **Country**, **Client tier**, and **Currency**, rows are sorted by the first metric, highest to lowest, with empty ones last. By **Month**, **Week**, and **Day**, in chronological order; only periods with at least one quote appear. The table shows up to 500 rows. ## Metrics Check the chips for the metrics you want to see. The exact definitions: | Metric | Grouping by quote | Grouping by Product | |---|---|---| | **Quotes** | Number of quotes in the cohort. | Number of quotes that include the product. | | **Quoted** | Sum of those quotes' **total** (including taxes and minus withholdings). | Sum of the product's **lines**: negotiated (or list) price times quantity, before taxes. | | **Sales** | How many were won: Approved, Paid, or Invoiced. | How many won quotes include the product. | | **Sold** | Total of the won quotes. | Sum of the product's lines in won quotes. | | **Close rate** | Sales over Quotes, as a whole percentage. | Same, counting quotes that include the product. | | **Average ticket** | Sold over Sales. | The product's Sold over the won quotes that include it. | | **Lost** | How many ended up Rejected or Expired. | How many quotes with the product ended up Rejected or Expired. | | **Days to close** | Average days from creation to approval for won quotes, with one decimal. | Not available. | | **Units** | Not available. | Units of the product in won quotes. | | **Gross margin** | Not available. | Sold minus cost, only on lines with a cost captured when quoting. | ### Which metrics don't apply to which grouping, and why - **Units** and **Gross margin** exist **per line**: a quote with five products has no single "units" or cost. They can only be checked when grouping by **Product**; in any other grouping they appear disabled with the hint "Only when grouping by product". - **Days to close** exists **per quote**: the time between creating and winning it isn't split across its lines. When grouping by **Product** it appears disabled with the hint "Not available by product". - If you change the grouping and a checked metric stops applying, it's removed automatically. If none is left, the starting set (Quotes, Sales, Sold, and Close rate) comes back without the ones that don't apply. - **Gross margin** only adds lines with a cost: a zero cost is treated as "I don't know", not "it was free". If no line in the row has a cost, the cell shows —. ### Up to six metrics You can check **up to six metrics at a time**. Once you reach six, the other chips are disabled and "Up to six metrics at a time." appears; uncheck one to pick another. At least one always stays checked: unchecking the last one does nothing. ### How your chosen metrics are used - **KPIs:** the first **four** checked metrics, in chip order, with their comparison against the previous period (in percent; close rate in points). - **Chart:** the first money metric you checked (if there's none, the first metric). By Month, Week, or Day, vertical bars with every period; in other groupings, the first 10 rows as horizontal bars. - **Total row:** the values for the **whole range**, not the sum of the rows: a rate or a ticket can't be added. That's why the Quotes total when grouping by Product can be lower than the sum of the rows (a quote with two products counts once). ## Applying changes and sharing with a link Every change in **Group by** or in the metrics applies on its own and reloads the table. (If your browser doesn't run JavaScript, the **Apply** button appears.) **The configuration lives in the page address**: the report, the range, the grouping, and the metrics. Copy the link and whoever opens it, with the Reports permission, sees exactly the same report under their own permissions. **Export CSV** downloads exactly what you see, named `cord-explorar-{from}_{to}.csv`; the file format is described in [Export CSV](/en/docs/gestion/informes#export-csv). ## Drill-down: from month to week to day Grouped by **Month**, each bar in the chart opens that month grouped by **Week**; grouped by **Week**, each bar opens that week grouped by **Day**. You keep the same metrics. The period is trimmed to your range. Grouped by **Client** or **Product**, the bar opens the record. On desktop, a click (or Enter) navigates directly. On mobile, the first tap shows the value and the tooltip includes **View detail →**. ## Saving a report 1. Set up the grouping and metrics. 2. Click **Save**. **Save report** opens. 3. Type a **Name** of 1 to 80 characters (for example, "Sales by country this quarter"). Repeated spaces are collapsed into one. 4. Choose **Email delivery**: **No delivery**, **Every Monday**, or **On the 1st of every month**. Below it says: "It goes to you, covering the period that just ended, with the CSV attached." 5. Click **Save**. The page reloads with the saved report open. What is saved and what isn't: - **Saved:** the name, the grouping, the metrics, and the delivery frequency. - **The date range isn't saved.** When you open a saved report, the range is the link's, or the last one you used in the Custom report in that browser, or Last 30 days. That way the same report works for this month and the next. ### Where it appears Saved reports appear in the report picker, under **Custom**, in alphabetical order, labeled **Saved report**. When you open one, its name becomes the page and picker title. They're **shared with the whole organization**: anyone with the Reports permission sees and opens them. If someone else saved it, "Saved by another team member" appears under the bar. ### Cap Each organization can have up to **50 saved reports**. At the cap, Cord says "You reached the maximum of 50 saved reports. Delete one to save another." It isn't a plan limit: it's the same on every plan. ## Editing, duplicating, and deleting With a saved report open, what you can do depends on who you are: | Action | Whoever saved it | Super admin or Admin | Any other member with Reports | |---|---|---|---| | View it, change the range, export CSV | Yes | Yes | Yes | | **Save changes** (name, grouping, metrics) | Yes | Yes | No | | **Save as new** (a copy with another name) | Yes | Yes | — | | **Save** (creates a new report of your own) | — | — | Yes | | **Delete** | Yes | Yes | No | | Schedule or change **Email delivery** | Yes | Only turn it off | No (yes on their own copy) | - **Save changes:** change the grouping or metrics, click **Save changes**, and confirm in the dialog. The dialog includes **Save as new** to create a copy without touching the original. The copy is yours and takes the **Email delivery** chosen in the dialog; if it has delivery, it goes to you. - **Delete:** the trash icon button, next to **Save changes**. It asks "Delete this saved report? This does not delete any data." Deleting it also turns off its email delivery. - **If you can't edit it**, you see the **Save** button (without the trash icon). When you click it, **Save report** opens with an empty name and creates a **new report of your own** with the grouping and metrics on screen; the original isn't touched. That copy is yours: you can edit it, delete it, and schedule its email delivery. ## Receiving it by email ### Scheduling it When you save (or with **Save changes** on a report you saved), choose under **Email delivery**: | Option | When it arrives | Which period it covers | |---|---|---| | **Every Monday** | On Monday, in your business time zone. | The full previous week, Monday to Sunday. | | **On the 1st of every month** | On the 1st, in your business time zone. | The full previous month. | | **No delivery** | It doesn't arrive. | — | - **It only goes to you**, at the email address of your Cord user. You can't add recipients: if someone else on the team wants it, they save their own copy and schedule it. - **The first email arrives in the next period.** If you schedule weekly delivery on a Wednesday, the first one arrives the following Monday with the week that just ended; a monthly one scheduled on October 8 arrives on November 1 with all of October. Switching from weekly to monthly (or back) restarts that clock. - **Nobody schedules it for you.** An email that would reach you is only turned on by you. What someone else sees when they open your saved report: - A **Super admin** or **Admin**, if the report **has** delivery: under **Email delivery**, only **No delivery** and the current frequency, with the note "As an admin you can turn this delivery off; only the person who saved the report can schedule it." - An admin, if the report has **no** delivery: "Email delivery is scheduled by whoever saved the report." - Any other member: the **Save** button creates their own copy, and that one they can schedule. ### What the email contains - **Subject:** "\{name} · \{period}", for example "Sales by country · Sep 1, 2026 – Sep 30, 2026". - **Header:** your business name, the report name, and the period dates. - **KPIs:** the report's first four metrics with their value for the period and, below, "vs. \{value} the previous period". In the email, the previous period is the **full previous calendar period**: the previous Monday-to-Sunday week, or the whole previous month (September against all of August, even though August has 31 days). On the Reports screen, by contrast, the comparison is still against the same number of days right before. - "The full detail is in the attached CSV, ready to open in Excel or Google Sheets." - **Open in Cord:** opens that saved report with exactly that period. It asks you to sign in and requires the Reports permission. - **Attachment:** `cord-informe-{from}_{to}.csv`, in the same format as **Export CSV**. - **Footer:** "You receive this email because you scheduled this report. Change or turn it off from Reports in Cord." The email uses your account language and amounts in your business currency, without decimals. ### Changing or turning it off Open the saved report, click **Save changes**, and choose another frequency or **No delivery**. It also stops arriving if the report is deleted. A Super admin or Admin can turn off delivery on someone else's report (choosing **No delivery** and **Save changes**) or delete it. ### When it stops arriving without you turning it off - **You leave the team** or your user is deactivated in that organization. - **You lose the Reports permission.** In both cases the report isn't sent and its clock doesn't advance: if you get access back, the next delivery covers the latest closed period. In the meantime nobody else receives your numbers. ### If delivery fails If the email couldn't be sent, the period **isn't marked as sent** and is retried on the next run, the following day. A run that doesn't happen doesn't skip the week either: the next one sends it. Two emails for the same period never arrive. ## Common problems **A metric is disabled.** It doesn't apply to that grouping: Units and Gross margin only by Product; Days to close not by Product. Or you already checked six. **Sold doesn't match Sales over time.** The explorer counts the cohort of quotes **created** in the range; Sales over time counts sales by **approval** date. **The Quotes total is lower than the sum of the rows.** Grouped by Product, a quote with several products appears in several rows but counts once in the total. **I opened a saved report and the range isn't the one it had.** Saved reports don't save the range: they use the link's or the last one you used in that browser. **Monday's email didn't arrive.** Check that you saved the report, that its delivery says **Every Monday**, that you're still active with the Reports permission, and that you didn't schedule it this same week (the first one arrives in the next period). Also check your spam folder. **I can't schedule delivery.** Only whoever saved the report can schedule it. Open the report, click **Save** to create your own copy, and schedule that one. **"You reached the maximum of 50 saved reports."** Delete one that's no longer used; the organization shares the cap. ## Related - [Reports and performance](/en/docs/gestion/informes) - [Home and views](/en/docs/gestion/dashboard) - Support: [Create, save, and share custom reports](https://cordhq.app/en/support/informes-personalizados) - Support: [Get a report by email every week or every month](https://cordhq.app/en/support/recibir-informes-por-correo) - Support: [Export a report to CSV (Excel and Google Sheets)](https://cordhq.app/en/support/exportar-informes-csv) - [Google Sheets](/en/docs/automatizacion/integraciones/google-sheets) - [Excel](/en/docs/automatizacion/integraciones/excel) - [Team and security](/en/docs/cuenta/equipo-seguridad) --- # Notifications URL: https://docs.cordhq.app/en/docs/gestion/notificaciones Last updated: 2026-10-13 Which events alert you, when each one fires (including what counts as a view), which channel they arrive on, and what doesn't trigger an alert. ## What it is In **Settings › Notifications › Notifications** there's a matrix of 8 events by 3 channels (Email, Slack, and Teams). Slack, Teams, and the task reminder apply to the whole organization. Email for the other events says **Personal**: each person chooses it in [Your preferences](/en/docs/cuenta/preferencias). ## Requirements - **Permission:** Settings, to change the matrix. - **Plan:** all. - **Channels:** email goes to each person according to what they chose in **Your account › Preferences**; the task reminder goes to each assignee. Slack and Teams must be connected (see below). ## The events | Event | When it fires | Triggered by | |---|---|---| | **Your client viewed the quote** | The first time the client opens the link (see below what counts as a view). | The client | | **Quote approved** | The client signs the proposal, in full or in part, from the link. | The client | | **Quote rejected** | The client confirms the rejection from the link. | The client | | **Payment received** | Cord confirms an online payment that settles the quote. | Online payment | | **Quote about to expire** | Exactly 3 days before the validity date, if it's still sent or viewed. | The daily process | | **Overdue payment** | The day after the payment of an approved or invoiced quote comes due without being paid. | The daily process | | **Someone joined the team** | An invitee accepts your invitation. | Your team | | **Task reminder** | Every morning, from 8:00 in your business's time zone, if someone has tasks due today or overdue. Email only, sent to each assignee (not to the owner), at most once a day per person. | The hourly check | ### What counts as a "view" The view alert is there so you know **your client** opened the proposal, so Cord discards anything that isn't the client: - **Your team doesn't count.** If you open the link signed in to the organization, you see the preview notice and nothing fires. - **Link preview generators don't count.** Pasting the link into WhatsApp, Slack, or an email doesn't mark it as viewed. - **It's measured with the page open and visible.** The view is recorded from the link itself when the tab is visible, not when the link loads in the background. - **Only once.** The alert goes out when the quote moves from *Sent* to *Viewed*. Reloading or reopening doesn't repeat it. More in [What your client sees](/en/docs/interaccion/vista-del-cliente). ### What doesn't trigger an alert - **Messages, per-line comments, and counteroffers.** They stay in the conversation and in the bell on the top bar, but don't trigger email, Slack, or Teams. To receive them, create a [workflow](/en/docs/automatizacion/workflows/primer-workflow) with **A message is posted on a quote**. - **What your team does:** **Mark approved**, **Mark rejected**, and **Record payment** change the status but don't send these alerts. - **Internal approval requests:** they reach Slack with buttons to decide and Teams with a link to Cord, separately from this matrix (see [Internal approvals](/en/docs/cotizacion/aprobaciones-internas)). ## Before you save for the first time Until people choose their notices, the owner gets **by email** quote approved, rejected, and payment received, and the rest of the team gets those for their own quotes. The **Task reminder** is on. If the company had saved this matrix before email became personal, the owner gets what was checked for email for each notice they haven't changed in their preferences. ## Channels Each person chooses which emails they get in [Your preferences](/en/docs/cuenta/preferencias): all, only those for quotes they created, or none. The email carries the quote number, client, total with its currency, and a button to open the quote, in the interface language that person chose. In the **Slack channel** section of the same screen, paste the URL of a **Slack incoming webhook** and check the Slack column for the events you want. The message includes the quote number, client, total, and a link to the quote. See [Slack](/en/docs/automatizacion/integraciones/slack). Connect Teams with **Connect with Microsoft** in **Settings › Integrations** (you pick the channel, nothing to copy), or paste the URL of a Teams Power Automate flow in **Settings › Notifications**. Check the Teams column for the events you want. It's a separate channel from Slack: you can have both and choose where each alert goes. See [Microsoft Teams](/en/docs/automatizacion/integraciones/teams). **The task reminder doesn't go to the owner; it goes to each assignee.** Each person gets only their own tasks, in a single email a day (see [Tasks](/en/docs/gestion/tareas#email-reminder)). Turning it off here turns it off for the whole organization, which is why the email footer only invites people with the Settings permission to turn it off. Email only. **"Someone joined the team" only arrives by email.** It isn't tied to a quote (no number or amount to show in the channel), so Slack and Teams show "Not available for this event". ## What Cord sends your client Separately from this matrix, Cord emails your client payment reminders, in the language of each document (see [Document language](/en/docs/gestion/clientes#document-language)) and as long as the client has an email on file: the ladder for each open invoice, on the schedule you choose in **Settings › Invoicing › Reminders**, and two notices for each approved quote with a balance, three days before the due date and on the day it's due. You turn them off on that same screen, and pause a client from their profile. Test organizations don't send reminders. See [Automatic payment reminders](/en/docs/pagos/recordatorios). ## Limits by plan Alerts are on every plan. Customizing the sender and signature of emails to the client is available from Starter (**Settings › Notifications › Email**). ## Common problems **I didn't get the view alert.** You opened the link yourself while signed in, the quote was already *Viewed*, or the event isn't checked in your matrix (it's off by default). **My partner doesn't get the emails.** Each person chooses their notices in **Your account › Preferences**. Until they do, they only get their own approved, rejected, and paid quotes. **Nothing arrives in Slack.** Check that the webhook URL is saved and the Slack column is checked for that event. ## Related - [Chat and comments](/en/docs/interaccion/chat) - [Negotiation and counteroffers](/en/docs/interaccion/negociacion) - [Workflow triggers](/en/docs/automatizacion/workflows/disparadores) - [Webhooks](/en/docs/desarrolladores/herramientas/webhooks) --- # Tasks and follow-up URL: https://docs.cordhq.app/en/docs/gestion/tareas Last updated: 2026-10-11 To-dos with an assignee, due date, and priority; a daily email reminder; how to create them from the app, the API, MCP, or a workflow, and which events they emit. ## What it is Tasks are your team's to-dos: the next call, the pending delivery, the follow-up on a quote. Each one has an assignee, a due date, and a priority, and Cord emails you when it's due. They show in two places: - The **Tasks and reminders** widget on [Home](/en/docs/gestion/dashboard), with the most urgent ones. - The **Tasks** page in the sidebar (shortcut G T), with every task and the completed ones. ## Requirements - **Permission:** Quotes, Collections, or Clients (any of the three) to create, edit, complete, or delete. Without any of them you see tasks but can't change them. - **Plan:** all. - **Who sees them:** every member of the organization. ## Create a task 1. Go to the composer in the **Tasks and reminders** widget on Home or on the **Tasks** page. 2. Type the task, for example "Call Luis to ask whether he reviewed the quote". Up to 200 characters. 3. Optional: pick the date with the **Today**, **Tomorrow**, or **Monday** (next Monday) shortcuts, or with the calendar. 4. Optional: turn on **High priority** and, if there's more than one person on the account, choose the **assignee**. 5. Click **Add** (or press Enter). The task shows up in the list without reloading the page. **From any screen:** click **Create** in the top bar and choose **Task** (or press T); the option shows if you have the Quotes, Collections, or Clients permission, even if you can't create anything else. **New task** opens, with the title and the due date; click **Add task**. The task is assigned to you with normal priority; priority, notes, and assignee are changed later with **Edit**. **Assignee:** with a single person on the account, every task you add is yours. With a team, the selector starts on you ("Your name (me)"); you can pick another active member or **Unassigned**. Only an active team member can be the assignee. **Notes** aren't entered when you create a task: you add them with **Edit** (up to 2,000 characters). ## Organize your day - **Groups by urgency:** Overdue, Today, Tomorrow, This week, Later, and No date. "Today" is the day in your business's time zone, not the server's (change it in Settings › General). - **Filters:** on the page, **Open** and **Completed**, and by assignee **Mine**, **All**, and **Unassigned**; the Home widget only has **Mine** and **All**. With a team, both views open on **Mine**. With a single person on the account, the assignee filter doesn't show. - **Complete:** click the circle. For a few seconds you can click **Undo**. Under **Completed** you see who completed it and when, and you can **Reopen** it. - **Task menu (···):** **Edit** (title, notes, date, priority, and assignee), **Snooze until** tomorrow, Monday, or in a week, **Assign to me**, and **Delete**. Delete asks for confirmation because it can't be undone. - **Linked to a quote or invoice:** if the task is linked to a quote (for example, a workflow, the API, a chargeback, or a transfer refund created it), the quote number and the client show as a link to the quote. If it's linked to an invoice (a workflow on an invoice event, the API, or MCP created it), the link goes to the invoice. - **Long lists:** the page shows 200 tasks per view and says below how many there are in total ("Showing 200 of 260"); the **Show more** button opens the next ones, 200 at a time (in the example, **Show 60 more**), up to 1,000. Beyond that, filter by assignee or complete the ones you already did. - **Notes:** on the page they show below the title; in the widget, an icon tells you the task has notes. - In the sidebar, **Tasks** shows how many of yours or unassigned ones are due today or overdue; the number is red when some are overdue. ## Email reminder Every morning, from 8:00 in your business's time zone, each assignee gets an email with their tasks due today and overdue, with dates in your account's language and your country's format. An unassigned task goes to whoever created it. If no one on the team created it (a workflow, the API, MCP, or a chargeback added it) or that person is no longer on the team, it goes to the account owner. - Each person gets at most one email a day per organization. If you add a task for today, or move or assign one to today, after that person got their morning email, no second email goes out: it shows up in tomorrow's, as overdue. If that person hadn't gotten an email that day yet (nothing was due in the morning), it arrives at the next check. - If you snooze a task, it reminds again on its new date. - An overdue task that isn't completed shows up in each day's email until you complete or snooze it. - Tasks without a due date don't trigger a reminder. - The **Open my tasks** button in the email opens the **Tasks** page with the **Mine** filter. - **Test mode** doesn't send reminders. - It's turned off for the whole organization, not per person: someone with the Settings permission unchecks **Task reminder** in [Settings › Notifications](/en/docs/gestion/notificaciones). The email footer says so to whoever can turn it off; everyone else is asked to talk to whoever manages the account. ## Tasks Cord creates for you When a payment operation needs your attention, Cord adds the task with **high priority**: - **Respond to the [amount] chargeback:** when a client disputes a card charge, with the day (in your business's time zone) the evidence deadline falls on as the due date. It's linked to the payment's quote and created unassigned (see [Disputes](/en/docs/pagos/disputas)). - **Send the [amount] SPEI refund:** when you request a refund of a quote's SPEI payment, which is transferred outside Cord, linked to the quote and assigned to whoever requested it (see [Refunds](/en/docs/pagos/reembolsos)). Completing the task doesn't record the refund as paid: it only closes your to-do. An invoice's SPEI payment doesn't create this task: it's returned to the account your client provides. The title is written in your account's language, and these tasks emit **A task is created** like any other. ## Other ways to create tasks The **Create a task** action in [Workflows](/en/docs/automatizacion/workflows/acciones) adds a task with a title (it can use event data, such as the quote number or client) and, optionally, **Due in (days)**, up to 365. If the event is about a quote, the task is linked to it; if it's about an invoice (for example **An invoice is paid** or **An invoice becomes overdue**), it's linked to that invoice and, if the invoice came from a quote, to the quote too. Example: "when the client rejects a quote, create a task to call them tomorrow". `POST /api/v1/tareas` creates a task with `titulo`, an optional `due_date` (YYYY-MM-DD), an optional `cotizacion_id`, and an optional `factura_id`. It requires a key with write permission. The API creates unassigned tasks; assigning, completing, and deleting them is done in the app. See [Tasks API](/en/docs/desarrolladores/funciones/tareas). The **crear_tarea** tool in the [MCP server](/en/docs/desarrolladores/herramientas/mcp) lets an AI assistant create a follow-up task, optionally linked to a quote or an invoice and with a date. ## Task events Each task emits events you can use in [workflows](/en/docs/automatizacion/workflows/disparadores) and [webhooks](/en/docs/desarrolladores/herramientas/webhooks): | Event | When | |---|---| | **A task is created** | When it's created from the app, a workflow, the API, or MCP, and when Cord creates it for you (chargeback or transfer refund). | | **A task is completed** | When it's marked complete. | Editing, snoozing, reopening, or deleting a task emits no event. ## Limits by plan Tasks have no cap by plan. ## Common problems **I don't see the tasks widget.** You hid it when customizing Home: bring it back from the **Library**. The **Tasks** page in the sidebar is always available. **I can't add a task.** Your role doesn't have the Quotes, Collections, or Clients permission. Without them you don't see **Task** in the **Create** menu either. **A task is missing from the list.** Check the filter: **Mine** only shows yours. The Home widget shows the 8 most urgent; the rest are on the **Tasks** page, which shows 200 per view and opens more with **Show more**. **I didn't get the reminder.** It only arrives if you have tasks with a due date of today or overdue, from 8:00 in your business's time zone, and once a day: what becomes due today after your email goes out shows up in tomorrow's. Someone else's task goes to them, not to you. Check that **Task reminder** is still on in Settings › Notifications, and your spam folder. ## Related - [Home and views](/en/docs/gestion/dashboard) - [Workflow actions](/en/docs/automatizacion/workflows/acciones) - [Tasks API](/en/docs/desarrolladores/funciones/tareas) --- # Chat and comments URL: https://docs.cordhq.app/en/docs/interaccion/chat Last updated: 2026-10-07 The general conversation and per-line threads inside the quote link: who writes, how you reply from Cord, when it shows live, and how to find out about a message. ## What it is Each quote has two conversation spaces: - **General conversation:** the **CONVERSATION** section at the end of the link, for questions about the whole proposal ("Can we move delivery to 15 days?"). - **Per-line comments:** a thread on each line, for questions about one product ("Can you switch this to the 16 GB model?"). Everything stays on the quote, visible to your team, without depending on personal email. For counteroffers, partial approval, and versions, see [Negotiation and counteroffers](/en/docs/interaccion/negociacion). ## Requirements - **Portal option:** **Comments and counteroffers** on in **Settings › Brand appearance › Client portal**. It's on by default; if you turn it off, the link shows neither the conversation nor the comment buttons. - **Permission to reply:** Quotes. - **Status:** the client can write while the quote isn't approved or rejected. - **Plan:** all. Seeing new messages live from Cord requires Pro or higher. ## On the client's side 1. **General conversation:** they type in "Write a message or proposal…" and send. 2. **Comment on a line:** they click the comment button next to the product name (it shows that line's message count), type in "Comment on this line...", and click **Send**. Each bubble carries its author next to the time: **You** for the client's messages and your business name for your replies. Your replies reach the client's link live, without reloading, in the general conversation and on each line. ## On your team's side On the quote detail: - **Conversation** shows the general thread. Reply in "Reply to the client (shows on their link)…". - Each line has its comment button; opening it shows **Comments on this line** and you reply in "Reply about this line…". - Bubbles say **You** for your team and the client's name for theirs. Your replies appear on the client's link; they aren't emailed to them. ## How you find out about a message Cord doesn't send email, Slack, or Teams for every client message or comment. - **Pro, Scale, and Developer:** with the detail open, messages arrive live and **New** appears in Conversation. - **Free and Starter:** reload the detail to see new messages. - **The bell on the top bar** lists your organization's 15 most recent activities, including "New message from your client" and "Counteroffer from your client", with the quote number and client. - **Any plan:** create a [workflow](/en/docs/automatizacion/workflows/primer-workflow) with the **A message is posted on a quote** trigger to get the alert wherever you want (team email, Slack, Teams). The same event reaches your [webhooks](/en/docs/desarrolladores/herramientas/webhooks). ## Behavior and edge cases - **Messages up to 800 characters.** - **On approval or rejection,** the link stops showing the message field and the comment buttons; the history is kept on the quote. - **The conversation doesn't change the quote.** A message doesn't change prices or status. To change the proposal use **Modify and resend**. - **The side menu doesn't count messages.** The number next to **Quotes** counts sent or viewed quotes still waiting for a decision, not messages. ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Conversation and per-line comments | Yes | Yes | Yes | Yes | Yes | | Live messages on the detail | No | No | Yes | Yes | Yes | ## Common problems **The client doesn't see where to write.** **Comments and counteroffers** is off, or the quote was already approved or rejected. **I missed a message.** Messages don't trigger alerts. Create a workflow with **A message is posted on a quote**. **I can't reply.** Your role doesn't have the Quotes permission. ## Related - [Negotiation and counteroffers](/en/docs/interaccion/negociacion) - [What your client sees](/en/docs/interaccion/vista-del-cliente) - [Notifications](/en/docs/gestion/notificaciones) - [Workflow triggers](/en/docs/automatizacion/workflows/disparadores) --- # Approval and technical evidence URL: https://docs.cordhq.app/en/docs/interaccion/firma Last updated: 2026-10-07 How your client signs a quote in Cord and what Cord records: declared name, IP address, browser, date and time, and the SHA-256 fingerprint of the accepted lines. ## The "OK" via email problem Traditionally, a sales rep sends a PDF and the client replies "Authorized, proceed." It can later be difficult to show which version, line items, or amount each person was reviewing. Cord adds an **electronic approval and technical evidence** layer at that moment. ## Requirements - **Status:** the quote must be *Sent* or *Viewed*. An expired, rejected, or already approved quote doesn't accept the signature. - **For the client:** just the link; no account needed. - **Plan and country:** every plan and all 12 markets. ## The approval process When your client clicks **Approve quote** inside the link, the same quote card moves to the **Digital signature** step (it's not a separate window), with a summary of the folio and the total being approved. To proceed, the client must: 1. **Type their full name** in *Signer's full name* (at least two characters). 2. **Check the box** *"I have reviewed this quote and accept the stated terms and conditions"*. The *Email (optional)* field can be left blank. The **Confirm and sign** button is enabled as soon as there's a name and the box is checked. If you changed the proposal while the client was reviewing it, Cord doesn't accept a signature on the previous version: it asks them to review the changes before approving. ### Partial approval Before approving, the client can uncheck the line items they don't want to include (each line has its own *Include this line in your approval* checkbox). The signature covers only the included lines: Cord recalculates subtotal, taxes, and total with those lines, and the rest are marked as **Not included**. ### Rejection with a reason If the client disagrees, they can use **Reject**, write a *Reason (optional)*, and **Confirm rejection**. The reason shows up in the quote's activity, and the rejection triggers the matching notification (see [Notifications](/en/docs/gestion/notificaciones)). ### Audit trail data At confirmation, Cord stores a **technical audit trail**: - **Signer's name** and, if they entered it, their email. - **IP address** from which the approval was made and the browser used. - **Date and time** of the signature, recorded by Cord's database at the moment it's saved. - **Cryptographic fingerprint (SHA-256)** computed over the quote, the type of approval (full or partial), the signer's name, the IP, and the approved lines (description, quantity, prices, and tax rate), used to detect later changes to the data covered by the approval. ## The Audit Stamp Once approved, the quote's link shows an **audit stamp** in the web view, with this content: > **Document verified** — **Signer:** [Signer's name] (IP: [IP address]) — **Date:** [date and time] — **Seal:** [SHA-256 fingerprint] The signer's email doesn't appear on the stamp. The quote PDF you download from Cord doesn't include the stamp; in the quote's details, the activity records who signed, from which IP, and, for a partial approval, how many lines and what amount they accepted. ### What it is useful for - **Preparing a dispute:** if the client disputes a card charge, the record can form part of the evidence you submit. The issuing bank decides the outcome, and Cord does not guarantee that a dispute will be won. - **Partial approval, also signed:** the fingerprint covers exactly the lines the client accepted, not the original total. - **Collections context:** the team can review who accepted, when, and for what amount instead of relying only on a verbal "yes" or a stray email. - **Connecting the commercial workflow:** the approved version can be used to begin collection and prepare the invoice available for the account's market. Cord stores technical evidence of approval; it does not provide notarial services or legal advice. Validity and evidentiary weight depend on the document, workflow, and jurisdiction. Consult a professional for high-risk cases. ## Common problems **The Confirm and sign button doesn't enable.** The name (at least two characters) or the acceptance checkbox is missing. **Cord says the quote can no longer be modified.** The quote expired, was rejected, or was already approved. **The client went back to review when signing.** You changed the proposal while they were reading it; they need to review the changes with **See changes** and sign again (see [Negotiation and counteroffers](/en/docs/interaccion/negociacion)). ## Related - [What your client sees](/en/docs/interaccion/vista-del-cliente) - [Negotiation and counteroffers](/en/docs/interaccion/negociacion) - [Approval and invoicing](/en/docs/cotizacion/timbrado) - [Disputes](/en/docs/pagos/disputas) --- # Negotiation and counteroffers URL: https://docs.cordhq.app/en/docs/interaccion/negociacion Last updated: 2026-10-08 How your client negotiates from the link (counteroffer, partial approval, rejection with a reason), how you reply with Modify and resend, what happens if you change the proposal while they read it, and what Cord notifies you about. ## What it is In Cord, negotiation happens on the document, not in an email thread. While the quote is *Sent* or *Viewed*, the client has four ways to respond: write a message, send a **counteroffer**, **approve only some lines**, or **reject** with a reason. Your answer is another version of the same quote, which arrives at the same link. ## Requirements - **Status:** *Sent* or *Viewed*. An approved, rejected, or expired quote no longer accepts counteroffers or a signature. - **Portal option:** counteroffers and messages require **Comments and counteroffers** to be on in **Settings › Brand appearance › Client portal**. Partial approval and rejection are always available. - **Permission:** Quotes to reply to messages and to **Modify and resend**; Approvals to **Mark approved** or **Mark rejected**. - **Plan:** all. ## Counteroffer 1. In the link's **CONVERSATION** section, the client enters an amount in the proposal field (in the quote's currency) and, optionally, a message. 2. They click **Counteroffer**. 3. The proposal appears in the conversation with a distinct style, showing the proposed amount followed by the message. A counteroffer **doesn't change the quote's status** or amounts: it's a message with an amount. To accept it, adjust the prices and resend (see below). If you don't accept it, reply in the conversation. ## Partial approval Before signing, the client can uncheck the lines they don't want with **Include this line in your approval**. The link shows how many lines they'll approve and the new total, calculated with the same engine Cord uses when saving. When a partial approval is signed: - The quote moves to *Approved* with the **total recalculated** from the included lines only: subtotal, per-line taxes, and withholding. - The other lines are marked **Not included** on the link and on the detail, which shows "Partial approval — the client only signed the included lines". - The activity logs who signed, how many lines they approved out of the total, and the approved amount against the original. - If you asked for a deposit, it's calculated on the approved total. - The invoice includes only the approved lines. At least one line must stay included: with every line unchecked, the approve button is disabled. ## Rejection with a reason 1. From review, the client clicks **Reject**. 2. They write a **Reason (optional — helps the seller improve)**. 3. They click **Confirm rejection**. The quote moves to *Rejected*. The activity logs the client's reason (or that they rejected it from the link without a reason), and the client sees "We notified [your business]". A rejection can't be undone: to propose again, duplicate the quote. ## How you reply: Modify and resend While the quote is *Sent*, *Viewed*, or *Expired*, the detail shows **Modify and resend (V2)**; the number is the version you're about to create. 1. Click **Modify and resend (V2)**. The quote editor opens as **New version of COT-0149**, with the current lines and the **Version 2** tag in the summary. 2. Change products, quantities, prices, each line's tax, or **Prices include VAT**. The client, currency, and terms can't be changed here: "A new version changes lines and prices. Client, currency and terms stay as they were sent." 3. Click **Send new version** (or **⌘ Enter**). If your organization uses [internal approvals](/en/docs/cotizacion/aprobaciones-internas), the version is checked against the caps before it goes out. When you resend, Cord: - saves the new version and adds it to the detail's **Version history**, with its date and total; - keeps the **same link**; - emails the client again if they have an email on file; - moves the quote back to *Sent* and restarts its validity from today; - emits the quote-modified event with the previous total, so your automations can tell an unchanged resend from one with a discount. Every new version restarts the validity from the day you send it, with the same length the quote was sent with (if it was 30 days, it expires in 30 days). That's how an *Expired* quote comes back: it returns to *Sent* with a new date. For a different length, client, currency, or terms, use **Duplicate quote**. ## If you change the proposal while the client reads it The link is connected in real time. If the client has it open when you resend: 1. Changed lines update without reloading, with a highlight and the previous amount for a few seconds ("was …"). 2. **The proposal was updated** appears with the **See changes** button. 3. The approve button is **locked** until the client clicks **See changes**, which takes them to the lines. On top of that, every signature carries the document revision the client had on screen. If it doesn't match the current one, Cord **rejects the signature**, takes the client back to review with the notice on, and never saves an approval on a version that no longer exists. Cord detects changes through the document revision, which advances with any write to the quote (lines, charges, messages, and events). That's why the notice can also appear after someone writes in the conversation. Clicking **See changes** is enough to approve again. ## What Cord notifies you about and what it doesn't | Client action | Changes the status | Email, Slack, or Teams alert | Webhook and workflow | |---|---|---|---| | Message in the conversation | No | No | Yes: "A message is posted on a quote" | | Comment on a line | No | No | Yes: "A message is posted on a quote" | | Counteroffer | No | No | Yes: "A message is posted on a quote", flagged as a counteroffer | | Full or partial approval | Yes, to *Approved* | Yes: **Quote approved** (by email, on by default) | Yes: "A quote is approved" | | Rejection | Yes, to *Rejected* | Yes: **Quote rejected** (by email, on by default) | Yes: "A quote is rejected" | Messages and counteroffers do appear in the bell on the top bar, which lists the most recent activity. To get an alert outside Cord, create a [workflow](/en/docs/automatizacion/workflows/primer-workflow) with the **A message is posted on a quote** trigger, for example to notify your Slack channel. Email, Slack, and Teams alerts are configured in [Notifications](/en/docs/gestion/notificaciones). **Mark approved** and **Mark rejected** from the app change the status and fire the webhook, but don't trigger the Notifications alerts, which are for the client's decisions. ## Limits by plan Negotiation is on every plan. On Pro or higher, the quote detail receives the client's messages live; on Free and Starter, reload the detail to see them. ## Common problems **The client doesn't see the counteroffer field.** **Comments and counteroffers** is off, or the quote is no longer *Sent* or *Viewed*. **Cord rejects the counteroffer.** The quote was already approved, rejected, or expired. **The client can't approve after I resent.** They need to click **See changes** first; if the button is still disabled, check that at least one line is included. **I don't see Modify and resend.** The quote is a draft (use **Continue editing**), it's already approved or paid, or your role doesn't have the Quotes permission. ## Related - [What your client sees](/en/docs/interaccion/vista-del-cliente) - [Chat and comments](/en/docs/interaccion/chat) - [Approval and evidence](/en/docs/interaccion/firma) - [Quote management](/en/docs/gestion/cotizaciones) --- # What your client sees URL: https://docs.cordhq.app/en/docs/interaccion/vista-del-cliente Last updated: 2026-10-13 A walkthrough of a quote's public link: review, sign, and pay, list versus negotiated price, language and currency, PDF, chat, seller presence, and which activity signals your team receives. ## What it is Every quote has a unique public link. It's a page with your logo and colors where the client sees the full proposal and acts on it. The link is the credential: whoever has it can see the quote, so share it only with your client. To see it the way they will, use **Preview** or **Open link** from the quote detail while signed in (see [Preview and sending](/en/docs/cotizacion/envio)). ## Requirements - **For the client:** just the link and a browser. No account needed. - **For your team:** the quote must be sent. Live presence and per-section attention require the Pro plan or higher. - **Country:** the same in all 12 markets; the language, currency, tax name, and payment rails change. ## What they see, top to bottom 1. **Header** with your logo, the quote number and, if you set them up, the **top announcement** and the **welcome message** (in **Settings › Brand appearance › Client portal**). 2. **FOR**, **VALID UNTIL**, and **TERMS**. Next to the validity date there's a notice: "Due in N days", "Due today", or "Expired". 3. **TOTAL DUE**, with the currency. If you asked for a deposit, below it says how much they pay on approval and what balance remains; if it's a retainer, how much is charged each month. 4. **Lines**: item, quantity, unit price, and amount. When the negotiated price is lower than the list price, the list price appears **struck through** next to the one they pay. The table doesn't show your cost or your margin. 5. **Subtotal, taxes, and total**: one row per rate with your country's tax name (IVA, VAT, GST, Sales tax) and, if applicable, withholding subtracted. 6. **Notes for the client**, if you wrote any. 7. **Actions**: approve, download PDF, or reject. 8. **Conversation**, if you have it turned on. 9. **Contact**: "Questions about this quote? Contact [your business]" with WhatsApp, email, or phone, depending on your business contact details. At the bottom is Cord's branding ("Legally binding signature · Verified by Cord"). From Starter you can remove it in **Client portal › Show Cord branding**. ## The steps: review, sign, pay 1. **Review.** The client reads the proposal. Each line has the checkbox **Include this line in your approval**: if they uncheck any, they see how many lines they'll approve and the recalculated total to approve. 2. **Sign.** With **Approve quote** the same card moves to **Digital signature**: a summary of the quote number and total, **Signer's full name**, **Email (optional)**, the acceptance checkbox, and **Confirm and sign**. See [Approval and evidence](/en/docs/interaccion/firma). 3. **Pay.** After confirming, **Quote approved** appears with the audit stamp. If your account collects online and an amount is due today, **PAY NOW** and **Pay securely** appear. On credit, they see the date their payment is due; with a deposit, the **Payment plan** with deposit and balance. On mobile, a bar with the total and the **Approve** button sticks to the bottom as they scroll. From review they can also choose **Reject**, write an optional reason, and **Confirm rejection** (see [Negotiation and counteroffers](/en/docs/interaccion/negociacion)). ## Language, format, and currency - **Language:** the quote's, which the quote takes when sent: the one your client has in their record or, if they have none, your organization's (**Settings › General**). It doesn't depend on the client's browser, and changing the record later doesn't change a quote already sent. The payment page and its form appear in the same language. See [Document language](/en/docs/gestion/clientes#document-language). - **Date and number format:** that of the quote's language, with your country's variant when there is one. - **Currency:** that quote's sales currency. A business in Madrid quoting in EUR shows euros; if you quote in USD, the client sees and pays dollars (see [Advanced options](/en/docs/cotizacion/opciones)). ## PDF and printing **Download PDF** opens the browser's print dialog with a clean version of the quote (no buttons, chat, or contact block), which the client can save as a PDF. After approval, the same button is called **Download receipt**. ## Conversation and presence If you left **Comments and counteroffers** on (in **Client portal**), the client sees the **CONVERSATION** section to write messages or send a counteroffer, and a comment button on each line. Each bubble says who wrote it: **You** for the client and your business name for your replies. See [Chat and comments](/en/docs/interaccion/chat). While the proposal is open, a strip shows the connection status: - **Connected in real time** when nobody from your team is looking at it. - **[Name] is online** when someone on your team has that quote's detail open (Pro plan or higher). Cord uses the member's profile name, or their email if they have no name. - **[Name] is typing…** when that person is writing a reply. If you change the proposal with **Modify and resend** while the client has it open, the amounts update without reloading and **The proposal was updated** appears with **See changes** (see [Negotiation and counteroffers](/en/docs/interaccion/negociacion)). ## What your team sees of the visit | Signal | Where you see it | Plan | |---|---|---| | **Viewed** (first open) | The quote moves to *Viewed*, the activity logs that the client opened it from the link and, if you turned it on, the [Quote viewed](/en/docs/gestion/notificaciones) alert arrives. | All | | **Viewing now** | Badge next to the client's name on the detail, for example "Viewing now — Line items". | Pro or higher | | **Client attention** | Detail block with distinct people, opens, first and last visit, time per section (Summary, Line items, Notes and terms, Approval and payment, Conversation), and total time. | Pro or higher | | **New message** | **New** appears in Conversation when the client writes while you have the detail open. | Pro or higher | ### What counts and what doesn't Cord only counts what the client does, and it measures it from the open page itself: - **Your team doesn't count.** Anyone who opens the link with an active session in your organization sees "Preview — this is what your client sees. Your visit is not counted as a view." and generates no view, client presence, or attention. - **Link preview generators don't count.** When you paste the link into WhatsApp, Slack, or an email, the service that builds the link card isn't recorded as the client. - **It's measured with the page visible.** The view is recorded when the link is open in a visible tab and the page has finished loading; a background tab adds no time. - **The view is counted once.** Reloading or reopening doesn't trigger new view alerts. In Client attention, each new tab adds one open. If you open the link from another browser without a session, Cord can't tell you apart from the client and will count your visit. ## Transparency notice Below the card, the client reads: "Whoever sent you this proposal can see when you open it and which sections you review." This notice isn't shown in your preview. IP addresses for these signals are stored as a hash, not in clear text; the full IP is kept only as signature evidence. Below it is the **Platform Privacy Notice** link, which opens Cord's privacy notice in the quote's language, even if you've hidden the Cord brand mark. The invoice link and the portal carry it too. ## Behavior and edge cases - **Expired quote:** the link still opens with "Expired", but Cord no longer accepts the signature and tells the client the quote can no longer be modified. - **Rejected:** the link shows **Quote rejected** and "We notified [your business]. If you change your mind, contact them directly." - **Paid, rejected, or expired while open:** the page reloads by itself to show the final status. - **Test quote:** the ribbon "Test quote — no commercial or fiscal validity" appears. - **Quote builder embedded on your site:** if the quote is shown on a site that isn't authorized, it appears read-only with **Respond from the secure link** and the **Open proposal** button (see [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen)). ## Limits by plan | | Free | Starter | Pro | Scale | Developer | |---|---|---|---|---|---| | Public link, signature, and PDF | Yes | Yes | Yes | Yes | Yes | | Remove Cord branding | No | Yes | Yes | Yes | Yes | | Live presence and client attention | No | No | Yes | Yes | Yes | ## Common problems **The quote was marked as viewed and the client says they didn't open it.** Someone else with the link may have opened it, or you opened it without a session. Check **Client attention** to see how many distinct people opened it. **The client doesn't see the pay button.** They haven't approved yet, the payment is on credit and not yet due, or your account has no active payment rail. **The client doesn't see the conversation.** It's turned off in **Client portal › Comments and counteroffers**, or the quote was already approved or rejected. ## Related - [Chat and comments](/en/docs/interaccion/chat) - [Negotiation and counteroffers](/en/docs/interaccion/negociacion) - [Approval and evidence](/en/docs/interaccion/firma) - [Customize your branding](/en/docs/cuenta/marca) --- # Complete app map URL: https://docs.cordhq.app/en/docs/operacion/mapa-de-la-app Last updated: 2026-10-11 What each section of Cord does, how quotes, clients, invoices, payments, collections, reports and settings connect, what is in the sidebar and top bar, and how the test environment and Cord Workbench work. Cord organizes work around a single sales cycle: **register the client, prepare the offer, negotiate, approve, collect, invoice and follow up**. The sections are not isolated databases; they show different stages of the same clients, documents and transactions. ## The main flow 1. Create or import the client in **Clients**. 2. Create reusable products, services or kits in **Products**. 3. Prepare a quote by hand, from a kit or with an AI draft. 4. Send the link. Cord records your client's first view and keeps the document's activity. 5. The client discusses, approves or rejects and, when applicable, pays online. 6. Cord records the online payment or the payment you mark manually. 7. The deal moves to **Invoices** and **Collections** based on the document issued, the balance and the due date. Your client can pay several invoices from their [invoice portal](/en/docs/pagos/portal-facturas) or leave [automatic payments](/en/docs/pagos/cobro-automatico) on. 8. **Reports** and **Performance** aggregate the results without creating a second copy of the transaction. ## Sidebar At the top of the sidebar is the **organization switcher**. From it you switch workspaces, create a new one (**Create workspace**), open **Team settings**, turn the **Test environment** on or off, and sign out. | Group | Item | Route | What it's for | |---|---|---|---| | — | **Home** | `/app` | KPIs, pipeline, recent activity and pending follow-ups. Guide: [Home and views](/en/docs/gestion/dashboard). | | — | **Quotes** | `/app/cotizaciones` | Create, search, filter, edit, duplicate, send and print. The counter shows quotes that need follow-up. Guide: [Quote management](/en/docs/gestion/cotizaciones). | | — | **Clients** | `/app/clientes` | Directory, CSV import, commercial terms, tax details, credit and statement. Guide: [Clients and statements](/en/docs/gestion/clientes). | | — | **Products** | `/app/productos` | Catalog, volume pricing, CSV import and the **Kits** tab. Guide: [Import your catalog](/en/docs/cuenta/catalogo). | | — | **Tasks** | `/app/tareas` | Team to-dos by assignee and due date, with filters, editing and completed tasks. The counter shows your tasks (or unassigned ones) due today or overdue; it turns red when some are overdue. Guide: [Tasks and follow-up](/en/docs/gestion/tareas). | | Revenue | **Invoices** | `/app/facturas` | Issue, review, export and follow up on invoices, and refund their online payments from the detail page; includes recurring ones (Professional or higher). Guide: [Invoices](/en/docs/pagos/facturas-emitidas). | | Revenue | **Payments** | `/app/cobros` | Charges, payouts, balances, refunds and disputes. Guide: [Payments dashboard](/en/docs/pagos/dashboard). | | Revenue | **Collections** | `/app/cobranza` | Receivables, aging and exposure by client (Professional or higher). The red counter shows overdue documents. Guide: [Receivables and follow-up](/en/docs/pagos/cartera-cobranza). | | Revenue | **AI agent** (under Collections) | `/app/cobranza/agente` | Configure and supervise AI collections (Pro, Scale, or Developer). Guide: [Autonomous collections (AI)](/en/docs/pagos/cobranza-ia). | | Insights | **Reports** | `/app/informes` | 15 reports in seven groups: Overview (Overview and Commercial diagnosis), Sales (over time, by client, and by product), Clients (Clients and Repeat purchase by cohort), Products, Finance (Payments received, Invoiced taxes, Finance, Cash flow, and Collections and receivables), Team (Sales by team member), and Custom. Seven are widget boards, seven are tables with comparison and CSV export, and the Custom report builds your own, saves it for the team, and emails it. Guides: [Reports and performance](/en/docs/gestion/informes) and [Custom reports](/en/docs/gestion/informes-personalizados). | | Insights | **Performance** | `/app/desempeno` | Team performance across your whole history: results attributed to whoever created or duplicated each quote. For a range with comparison, use the **Sales by team member** report. | | Automation | **Workflows** | `/app/workflows` | "When this happens, do this" automations, ready-made ideas and run history. Guide: [Cord Workflows](/en/docs/automatizacion/workflows). | Also: - **Pinned.** The pin button next to any page title (or the `X` key) adds it to the **Pinned** group at the top of the sidebar. - **Collapsible groups.** **Revenue**, **Insights** and **Automation** collapse with a click on their title. - **Collapse the sidebar.** The button at the bottom of the sidebar shrinks it to icons. - **Settings** (`/app/ajustes`) opens with the gear in the top bar. See the [Settings map](/en/docs/cuenta/mapa-de-ajustes). - **Set up with AI** (`/app/setup`) opens from **Settings › General**. - Each client's **invoice portal** isn't in the sidebar: you create, send, or disable it from the client's profile, and your client opens it on their own link (`cordhq.app/portal/...`). See [Invoice portal](/en/docs/pagos/portal-facturas). ## Top bar | Item | What it does | |---|---| | **Search…** (`⌘K` or `Ctrl+K`) | Opens the palette to search quotes, clients, products and Settings tabs, or run a command. | | **Setup guide** | While your account is incomplete, shows your completion percentage and opens the **Set up Cord** widget. See [Create your account](/en/docs/cuenta/crear-cuenta). | | **Create** | Menu to create a **Quote**, **Invoice**, **Client**, **Product** or **Task**. It only shows what your permissions allow. | | **Apps** | For people with the Settings permission: which apps are connected and which you can connect, without leaving the screen. | | **Notifications** | Recent activity panel with **Mark as read** and **View all activity**. A dot means there is something new. Guide: [Notifications](/en/docs/gestion/notificaciones). | | **Help** | **Help center** with search, keyboard shortcuts, user guide, contact support, frequently asked questions and the Cord AI assistant. | | **Theme** | Switches between light and dark mode. | | **Settings** | Opens the Settings index. | ### Keyboard shortcuts On desktop you can use these shortcuts when you are not typing in a field. On screens narrower than 880 px they are disabled and everything is done with visible buttons. | Shortcut | Action | |---|---| | `⌘K` / `Ctrl+K` or `/` | Open search | | `C` | New quote | | `F` | New invoice | | `T` | New task | | `G` then `D`, `C`, `L`, `P`, `T`, `F`, `O`, `B`, `A`, `E` or `W` | Go to Home, Quotes, Clients, Products, Tasks, Invoices, Payments, Collections, Reports, Performance or Workflows | | `X` | Pin or unpin the current page in the sidebar | | `?` | Show or hide the shortcuts help | The quote and invoice editor (`/app/cotizaciones/nueva` and `/app/facturas/nueva`, also for drafts with `?draft=` and new versions with `?version=`) has its own shortcuts: there `/` jumps to the catalog search, `⌘ Enter` sends or issues, and `⌘ S` saves the draft; `⌘K` still opens search. See [Preview and sending](/en/docs/cotizacion/envio). On a phone, the sidebar opens as a panel and includes shortcuts to **Help** and **Settings**. The options you see depend on your **permissions**, your **effective plan**, your **country of operation** and the account's setup state. A page existing does not mean any member can change it. ## Test environment The **Test environment** is an isolated copy of your organization for rehearsing without touching your real data: quotes, charges with test data, webhooks and integrations. 1. Open the organization switcher at the top of the sidebar. 2. Turn on **Test environment**. 3. The app shows a **Test mode** strip with the notice "Everything you do here is a test — your real data is untouched". 4. To go back, select **Exit test mode** on the strip or turn the switch off. From the strip you can also **Clear test data** to start over. Keep in mind: - Test data does not mix with production: when you leave, you won't see what you created inside. - Some real actions are not available in test mode: subscribing or changing plans, connecting a custom domain, and applying a **Set up with AI** proposal. - Test documents do not consume your plan's allowance. Guide for integrations: [Test environments](/en/docs/desarrolladores/empezar/pruebas). ## Cord Workbench **Cord Workbench** is the developer panel. It appears as a pill in the bottom-right corner across the app when you turn on **Developer mode** in **Your account › Preferences**, and requires the Settings permission. Its tabs are **Overview**, **Logs**, **Errors**, **Events**, **Webhooks**, **Shell**, **API keys** and **Health**: the log of every request, grouped errors, events with their deliveries, webhook endpoints, a Shell to try the API, keys and the status of your integration. Its **Inspector** finds any ID. Guide: [Cord Workbench](/en/docs/desarrolladores/herramientas/workbench). ## Quote statuses | Status | Operational meaning | |---|---| | `draft` | Editable draft not yet sent to the client. | | `sent` | Sent; the link is ready to be viewed. | | `viewed` | The client opened the quote for the first time. Your own visit doesn't count. | | `approved` | The client recorded their approval. A balance may remain. | | `rejected` | The client rejected the proposal. | | `expired` | Its validity ended without closing. | | `paid` | The non-recurring flow was paid according to its recorded payments. | | `invoiced` | The deal already has an associated invoice. | A recurring quote does not become `paid` forever: each installment creates its own charge and the subscription keeps a separate status. ## Active organization Cord is multi-company. Every client, product, quote, invoice, member and setting belongs to the **active organization**. If you have access to more than one, check the organization switcher before importing, issuing or changing configuration. ## Permissions that change the experience The owner always has full access. Other members get presets or per-section permissions: - **Quotes:** create, edit, send and duplicate. - **Approvals:** approve discounts, amounts or controlled changes. - **Collections:** review and manage receivables. - **Clients** and **Products:** change their directories; with **Clients**, also create, send, rotate, or disable a client's invoice portal. - **Reports:** open Reports and Performance, see Home's analytics widgets, and save custom reports. - **Settings:** change the business configuration. - **Payment settings:** change Cord Payments and the payout account. - **Refunds:** start refunds of already reconciled online payments: quote payments, in **Payments**, and invoice payments, on the invoice's detail page. - **Team:** invite people and change permissions. If an action doesn't appear, check the member's permission first; then the plan and the configuration that feature requires. ## What changes by country - Sign-up is available in 12 markets: Mexico, the United States, Canada, Brazil, Spain, the United Kingdom, Germany, France, Colombia, Argentina, Chile and Peru. - Cord Payments is available in Mexico, the United States, Canada, Spain, the United Kingdom, Germany and France. In Brazil, Colombia, Argentina, Chile and Peru, online payments work with [Mercado Pago](/en/docs/pagos/mercado-pago), which is also offered in Mexico as an alternative. - SPEI is exclusive to Mexico. Bank transfer with a reference is for Spain, Germany, and France (in EUR), the United Kingdom (in GBP), and the United States (in USD). SEPA debit is for Spain, Germany, and France (in EUR); ACH bank debit, for the United States (in USD); Bacs Direct Debit, for the United Kingdom (in GBP); and pre-authorized debit, for Canada (in CAD). See [Payment methods](/en/docs/pagos/metodos). - Mexico issues CFDI 4.0 with a valid CSD. - Outside Mexico, Cord issues commercial invoices. In Argentina, Brazil, Chile, Colombia, and Peru, the invoice authorized by the tax authority when issuing is active on your account. In Spain, the invoice is registered with the AEAT through Verifactu (beta) if you uploaded your electronic certificate. ## Before looking for an error When something isn't available, check in this order: 1. active organization and test environment; 2. the member's permission; 3. the plan's limit or capability; 4. country of operation and compatible method; 5. required fields of the client, issuer or document; 6. the previous status of the quote, invoice or payment. Then read the section's guide. The [support center](https://cordhq.app/en/support) is for specific incidents; these guides explain the full model. ## Related pages - [Settings map](/en/docs/cuenta/mapa-de-ajustes) - [Create your account](/en/docs/cuenta/crear-cuenta) - [All products](/en/docs/productos) --- # Accepting a payment URL: https://docs.cordhq.app/en/docs/pagos/aceptar Last updated: 2026-10-11 What your customer sees when paying from the link: when the pay button appears, how they choose a method, how they pay by card, SPEI, bank transfer with a reference, bank debit, or Mercado Pago, what happens with deposits, installments, credit, and partial payments, and how payment is confirmed. ## What it is The public link of a quote or invoice includes the **payment checkout**: a screen with your logo and colors where your customer pays with the methods you have active. There's no second payment link to send: the same link is used to review, approve, pay, and check what's left. ## Requirements | Requirement | Detail | |---|---| | Plan | All plans. | | Payment rail | [Cord Payments](/en/docs/pagos/onboarding) active (MX, US, CA, ES, GB, DE, FR) or [Mercado Pago](/en/docs/pagos/mercado-pago) connected (MX, BR, CO, AR, CL, PE). | | Methods | At least one turned on in **Settings › Payments › Payment methods**. See [Payment methods](/en/docs/pagos/metodos). | | Document | An approved quote (and signed, if you required it) or an issued invoice with a balance. A test document can't be paid online. | | Currency | The document's sale currency. SPEI only in MXN; bank transfer with a reference only in EUR, GBP, or USD depending on your country; SEPA debit only in EUR, ACH only in USD, Bacs only in GBP, and pre-authorized debit only in CAD. | Without an online payment rail, the link shows your manual transfer details (if you set them up) and you record the payment once you verify it. ## When the pay button appears | Situation | What your customer sees | |---|---| | Approved **upfront** quote | The pay button, from approval onward. | | Quote with a **credit term** (any Net term, from Net 7 to Net 90) | On approval, **Order confirmed with Net 30 credit** and "The payment of [total] is due on [date]". Online payment opens on that date. See [Credit terms](/en/docs/pagos/credito). | | Quote with a **deposit** | From approval, the deposit amount. The balance opens according to the term. See [Upfront and balance](/en/docs/pagos/anticipos). | | Quote with an **installment plan** | The next installment that's already due. See [Installment payment plans](/en/docs/pagos/cuotas). | | **Recurring** quote | The card authorization for the monthly retainer. See [Monthly retainers](/en/docs/pagos/igualas). | | Issued **invoice** | The full balance, with the **Pay another amount** option to pay part of it. An invoice can be paid as soon as it's issued, even before it's due. | | **Several invoices** from the same customer | In their [invoice portal](/en/docs/pagos/portal-facturas), the ones they pick, in a single charge. | | Invoice with a **bank debit in progress** | A notice that a bank debit is processing and they don't need to pay again. The pay button doesn't appear until the bank confirms or rejects it. | | Paid document | The **Paid** status and the payment history. | ## How your customer pays 1. Opens the link and, if it's a quote, approves it. 2. Clicks the pay button. If you have both card and a bank transfer (SPEI or with a reference) active, they first **choose how to pay**; with only one, they see the form directly. 3. Pays by card inside the document, follows the bank transfer instructions, authorizes the bank debit, or clicks **Pay with Mercado Pago**. 4. Once confirmed, the link shows the payment and the document changes status. ### By card - The form lives inside the document, with no redirects to another site. - It accepts the credit and debit cards your payments account supports. Your customer's bank may ask for additional verification. - If the payment fails, your customer sees a clear message with a reference they can share with you; they never see technical errors. - Once confirmed, the document moves to **Paid** (or that part's charge does, if it's a deposit, an installment, or a partial payment). ### By SPEI On **MXN** quotes and invoices from businesses in Mexico. - Cord generates instructions with a **CLABE tied to that charge** (on the invoice, the CLABE belongs to that invoice), bank, beneficiary, reference, and amount, with copy buttons. - Your customer can **Print or save PDF**. On the quote they can also click **Email these to me** to receive them at the email registered on it. - They transfer from their online banking. When the money arrives, Cord reconciles it on its own and changes the status: no receipts to cross-check. An incomplete transfer isn't recorded until the rest arrives. SPEI on the invoice link is a new feature; see [SPEI on the invoice link](/en/docs/pagos/metodos#spei-on-the-invoice-link). SPEI confirmation depends on the bank's notice and isn't always instant. See [SPEI](/en/docs/pagos/metodos#automatic-spei). ### By bank transfer with a reference On quotes and invoices in EUR (businesses in Spain, Germany, and France), GBP (United Kingdom), or USD (United States) that have a linked client. It's a new feature. - Your customer picks **Bank transfer** and sees the instructions: the **reference** highlighted, the amount, and the details of their account (IBAN, sort code, or routing and account number), with copy buttons. - The account is the same for all their payments; the reference is unique to each payment. In euros, the account holder is typed exactly as shown. - When the money arrives, Cord reconciles it on its own. An incomplete transfer isn't recorded until the rest arrives. See [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). ### By bank debit (SEPA, ACH, Bacs, or pre-authorized debit) Only on **invoice** links and in the portal, in EUR (SEPA, businesses in Spain, Germany, and France), USD (ACH, United States), GBP (Bacs, United Kingdom), or CAD (pre-authorized debit, Canada), once the payment processor has activated the method in **Settings › Payments › Payment methods**. - Your customer picks bank debit in the same payment form and authorizes the charge with their account details. - The bank takes days to confirm it. Meanwhile, the link tells them the debit is processing and they don't need to pay again (in the portal, the invoice shows **Payment processing**); if the bank rejects it, it goes back to unpaid. - With Canadian pre-authorized debit, your customer first states whether they're paying as a business or an individual, and an account verified with micro-deposits shows the **Verify my account** button. See [Bank debit](/en/docs/pagos/domiciliacion). ### With Mercado Pago Your customer goes to Mercado Pago's checkout, pays with the methods available in their country, and returns to your link. The payment is marked once Cord reads the approved payment in your Mercado Pago account. ## After payment - **Your customer** sees the payment reflected on the link. If they return from a payment still being confirmed, the link waits a few seconds for the notice and lets them refresh. - **You** see the payment in [Revenue › Payments](/en/docs/pagos/dashboard), on the document timeline, and, if you set up alerts, in your [notifications](/en/docs/gestion/notificaciones). - **Your integrations** receive the payment event. A partial payment (deposit, installment, or partial invoice payment) doesn't trigger the quote-paid event: that one only goes out when no balance is left. - **The money** lands in your payments account balance and reaches your bank at your [payout frequency](/en/docs/pagos/depositos). Fees depend on the method and the currency. On MXN payments, each collected part (deposit, balance, installment, or partial payment) carries its own fee. See [Cord Payments fees](/en/docs/pagos/condiciones). ## Edge cases - **The quote amount changed after the link was opened.** If there are no payments yet, your customer sees a notice asking you to review the breakdown before paying. - **Your customer switched methods mid-payment.** Cord checks the previous attempt before opening another and doesn't replace it if it already received money. See [Switch between bank transfer and card](/en/docs/pagos/metodos#switch-between-bank-transfer-and-card). - **The same charge was paid through Cord Payments and Mercado Pago.** Cord notes it in the history so you can decide whether to refund one. - **The invoice balance changed while your customer was paying.** Cord asks them to refresh the invoice before continuing. ## Common problems **My customer doesn't see the pay button.** Check that your account is active, that a method is turned on, and that payment is already open according to the credit term. **My customer paid, but the document is still pending.** If it was a bank transfer (SPEI or with a reference) or a bank debit, wait for the bank's confirmation. If it was a card, check **Recent payments** on the dashboard before recording anything by hand. **The link says the document is a test.** That document has no valid fiscal issue and can't be paid online. See [Invoicing by country](/en/docs/pagos/facturacion). ## Related - [Payment methods](/en/docs/pagos/metodos) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [Upfront and balance](/en/docs/pagos/anticipos) - [Credit terms](/en/docs/pagos/credito) - [Invoice portal](/en/docs/pagos/portal-facturas) - [Installment payment plans](/en/docs/pagos/cuotas) - [Automatic payment reminders](/en/docs/pagos/recordatorios) --- # Upfront and balance URL: https://docs.cordhq.app/en/docs/pagos/anticipos Last updated: 2026-10-10 Learn how to split the payment of a quote to receive a percentage upfront and collect the rest later. ## The split payment model In service-based projects (agencies, consultancies, software development), it is very common not to charge 100% upfront, but rather to require an initial deposit (e.g., 50%) to kick off the work and settle the balance upon delivery. In traditional invoicing platforms, this forces you to generate **two different payment links** or duplicate the invoice. In Cord, the quote is **smart** and handles split payments without you having to do double the work. ### How to configure an upfront payment 1. Open the quote editor. 2. In step 1, **Who are you quoting?**, choose the payment term. With **Due on receipt**, the balance can be paid as soon as the deposit is covered; with a credit term (from **Net 7** to **Net 90**, for example **Net 30**), the balance is due that many days after approval and is enabled for payment on that date. 3. In step 3, **Terms**, enter the percentage in **Deposit (%)**, between 1 and 99 (e.g., `50`). 4. Below the field, the editor instantly shows how much your client pays on approval and how much balance remains, for example "Upon approval, your client pays MXN 5,000.00 as a deposit and the rest (MXN 5,000.00) per the terms." **Productivity tip:** In *Settings > Quotes > Numbering & tax* you can set **Default deposit (%)**. If you set it to 50, all your new quotes will be pre-configured with that model. ## What does the client see? When the client opens the public link of the quote, below the total amount they will see a clear breakdown: - **Project total:** $10,000.00 MXN - **Pay upfront today (50%):** $5,000.00 MXN - **Balance:** $5,000.00 MXN (due according to the payment term) ### Automatic payment button mutation Each part of the quote — the upfront payment and the balance — is an independent payment within the same link: 1. **First charge:** The client clicks "Approve and Pay". The button charges them **only the $5,000.00 MXN** of the upfront payment. Once processed, the quote switches to "Approved" and is ready for you to start working. 2. **Second charge:** Once the balance is enabled, the client can **re-enter the exact same link** from the original quote. The system will detect that the upfront payment has already been made, and the payment button will have automatically mutated to charge the **remaining Balance**. You didn't have to send a second email, nor generate a "payment link for the balance". Everything lives in the same ecosystem. Each payment (the upfront payment and the balance) is an independent transaction for fee purposes: on payments in Mexican pesos (MXN), Cord Payments charges its fee on each one separately, using the same fee schedule as a normal payment. In other currencies, Cord applies no platform fee today. See [Fees and advantages](/en/docs/pagos/condiciones). --- # Receivables and operating collections URL: https://docs.cordhq.app/en/docs/pagos/cartera-cobranza Last updated: 2026-10-10 How Collections works: what goes into the list, what each widget measures, how to record payment promises, remind via WhatsApp, and record a manual payment, and how it relates to the unified accounts receivable view. ## What it is **Collections** (sidebar › **Revenue**) is an operating list **as of today**. It has no date selector because it answers a single question: what needs action now? Historical analysis (full aging, days to collect, payment behavior) lives in **Reports › Collections and receivables**. See [Reports and performance](/en/docs/gestion/informes). ## Requirements | Requirement | Detail | |---|---| | Plan | Pro, Scale, or Developer. On Free and Starter, the page shows an invitation to change plans. | | Permission | **Collections**. | | AI collections | Pro, Scale, or Developer. See [AI collections](/en/docs/pagos/cobranza-ia). | ## What goes into the list The Collections list comes from the [unified accounts receivable view](#the-unified-accounts-receivable-view), so it brings both rails together: - **approved or invoiced quotes that aren't paid yet**, due on the approval date plus the payment term's days; - **open invoices** with a balance, with their own due date, including those issued without a quote; - except [recurring retainers](/en/docs/pagos/igualas), which charge themselves every month and are never treated as overdue receivables. Each account shows its **balance**: for a quote, the total minus payments already received (deposits, installments); for an invoice, the total minus partial payments and credit notes. Amounts are expressed in your business currency; if you sell in several currencies, the note below the page says how they were converted and which one was left out for lack of an available exchange rate. An invoice is collected from its own detail, because that's where the payment is recorded in its history. That's why invoice rows show **View invoice** instead of **Paid**, and payment promises are recorded only on quote rows. Remind via WhatsApp works on both. ### The unified accounts receivable view Cord keeps a single view that joins quotes and invoices with a common shape: origin, number, currency, total, paid, **balance**, and days overdue. Rules of that view: - A quote with an **open invoice** appears only as the invoice, because the invoice carries the real balance; counting it twice would double your receivables. - An invoice's balance already deducts partial payments and credit notes. - Recurring retainers don't enter. It's used by the [AI collections agent](/en/docs/pagos/cobranza-ia), each customer's **account statement**, and [Workflows](/en/docs/automatizacion/workflows/consultas) receivables queries. ## Today's summary | Widget | What it shows | |---|---| | **Overdue** | Total overdue and number of accounts. Tap it to filter the table. | | **Due this week** | Accounts falling due in the next 7 days. | | **Promises coming due** | Promises committed for today or earlier, with the historical compliance percentage. | | **Overdue, untouched** | Overdue accounts with no payment promise. Tap it to filter the table. | | **Handle first** | Priority by amount and days overdue: what weighs most, on top. | | **Payment promises** | Pending promises, with date and amount. | | **Promise compliance** | Kept versus broken. | | **Credit exceeded** | Customers with an open balance above their configured credit limit. | | **Receivables age** | Not yet due, 1–30 days, 31–60 days, and more than 60 days. | | **Accounts receivable** | The actionable table. | With **Customize** you can hide, reorder, or resize the widgets, with the same icon buttons (**Library**, **Reset**, and **Done**), the same floating library, and the same keyboard support as [Home](/en/docs/gestion/dashboard#customize-home). From the library you can also add **Credit limits exceeded**: how many clients are above their configured credit limit today. That preference is personal and doesn't change any calculation. ## The table and its actions The table filters by **All**, **Overdue**, **With promise**, or **Untouched**. Each row shows customer, number, terms, due date, status, and balance, with these actions: ### Record a payment promise 1. In the row, open the payment promise. 2. Enter the **date** the customer committed to pay, the **amount** (optional), and a **note** of up to 400 characters. 3. Save. The promise appears in the widgets and the account no longer counts as "untouched". 4. When the date arrives, mark it **fulfilled** or let it lapse as broken. If you entered it by mistake, delete it. A promise helps organize follow-up and measure compliance. It does **not** lower the balance, extend the due date, run a charge, or remove the account from overdue. If you edit an active promise, the new one replaces the previous one. ### Remind via WhatsApp **Remind via WhatsApp** opens WhatsApp with a pre-written message: customer, number, total, due date, and document link. If the customer record has a phone number, it opens the conversation with that number; otherwise you choose the contact. Review the text before sending it: delivery happens in WhatsApp, not in Cord. ### Record a manual payment The **Paid** button marks the quote as paid, after a confirmation ("Record the payment of [number] for [amount]?"). On invoices, **View invoice** opens its detail so you record the payment there. Recording a payment is a manual record: it doesn't create a charge or confirm a deposit. Use it only after verifying the transfer in your bank, and never to simulate revenue. ## Automatic reminders Besides what you do from this page, Cord sends [automatic payment reminders](/en/docs/pagos/recordatorios) on its own: a ladder before and after each invoice's due date, on the schedule you choose in **Settings › Invoicing › Reminders**, and a notice in the days before each quote's due date. You turn them off on that same screen, and a client on **Never email** doesn't get them either. ## Late interest Automatic late interest is **suspended** while the legal review by country concludes: new rates can't be configured today and the monthly process generates no charges. Interest recorded earlier still appears separately to keep the balance traceable. ## Manual and AI collections | Plan | What it includes | |---|---| | Pro, Scale, and Developer | Receivables, priorities, promises, WhatsApp, payment recording, and the [AI collections agent](/en/docs/pagos/cobranza-ia), with [installment plans](/en/docs/pagos/cuotas). | ## Limits - A promise doesn't change the balance, and it's only recorded on quotes. - **Paid** marks the whole quote as paid: record partial payments on the document. Invoices are collected from their detail. - A sale in a currency without an available exchange rate isn't added to the totals until one exists. ## Common problems **Collections doesn't appear.** Check that your plan is Pro or higher and that you have the **Collections** permission. **A customer paid the deposit and the account is still on the list.** That's expected: the row shows the remaining balance, already without the deposit, until everything is paid. **I don't see an overdue invoice.** The list includes open invoices with a due date and a balance. A draft, voided, already paid, or undated invoice doesn't appear; look for it in **Invoices**. **An amount doesn't match the document.** The list expresses everything in your business currency. Check the note below the page: a currency without an available exchange rate isn't added. **A promise didn't lower the balance.** That's intentional: only a recorded payment lowers it. ## Related - [Automatic payment reminders](/en/docs/pagos/recordatorios) - [AI collections](/en/docs/pagos/cobranza-ia) - [Installment payment plans](/en/docs/pagos/cuotas) - [Clients and statements](/en/docs/gestion/clientes) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) --- # AI collections URL: https://docs.cordhq.app/en/docs/pagos/cobranza-ia Last updated: 2026-10-15 How the AI collections agent works: which accounts it picks, how often it writes, approval or automatic mode, the drafts inbox, plans of 2 to 6 installments, exclusions, promises, and AI quota per plan. ## What it is The **collections agent** (sidebar › **Revenue › Collections › AI agent**) reviews your overdue receivables every day, drafts an email for each account with the real balance, days overdue, and payment link, and, from the days overdue you set, can propose an [installment payment plan](/en/docs/pagos/cuotas) that only the customer can accept. It starts **off**: it doesn't email anyone until you turn it on. ## Requirements | Requirement | Detail | |---|---| | Plan | Pro, Scale, or Developer. Free and Starter don't include collections. | | Permission | **Collections** to see the page and approve, edit, or discard drafts. **Settings** to turn on and configure the agent. | | AI quota | Each email drafted or regenerated uses one AI unit from your plan: 50 included per month on Pro and 500 on Scale (overage is billed as usage) and unlimited on Developer. | | Customers | With an email on file. Without one, the agent can't send. | | Account | Doesn't run on test accounts or the demo account. | ## Turn it on 1. Open **AI agent** (under Collections). The first time you'll see what the agent does, a sample email, and how many accounts it would email today. 2. Click **Turn on with approval**. The agent starts in **Needs approval** mode: nothing goes out without your sign-off. 3. Click **Configure** to adjust grace, cadence, installments, tone, and signature. 4. Check **Up next** to see whom it will email on the next run and whom it won't. ## Settings | Option | What it controls | Default | Range | |---|---|---|---| | **Operating mode** | With approval, the agent drafts and waits. On automatic, it sends on its own. | Needs approval | — | | **Grace days** | How long it waits after the due date before writing. | 3 days | 0 to 90 | | **Days between emails** | Minimum before emailing the same account again. | 7 days | 1 to 90 | | **Propose a plan after** | Days overdue from which it may propose an installment plan. | 15 days | 1 to 365 | | **Maximum instalments** | Cap on a plan's monthly installments. | 3 | 2 to 6 | | **Minimum amount** | It won't write for smaller balances. | No minimum | — | | **Maximum per run** | Cap on emails per run. | 25 | 1 to 200 | | **Tone** | Warm, Professional, or Firm. | Professional | — | | **Signature** | How the email signs off (up to 400 characters). | No signature | — | On top of these settings, Cord applies a fixed cap you can't raise: a customer gets at most **2 collection messages every 7 days**, counting the agent's emails and the ones you write yourself from the thread. See [One-click opt-out and message cap](#one-click-opt-out-and-message-cap). ## How it decides whom to email Every day, the agent takes receivables from the [unified accounts receivable view](/en/docs/pagos/cartera-cobranza#the-unified-accounts-receivable-view), quotes and invoices, that are **more days overdue than your grace days**, from most to least overdue. From that list it **skips**: | Reason in "Up next" | Why | |---|---| | **Already settled** | The balance is already zero. | | **Excluded** | The customer, quote, or invoice is on **Never email**. | | **Below minimum amount** | The balance is below your minimum. | | **Emailed recently** | There's an unresolved draft, or the last email sent was fewer days ago than your cadence. | | **Plan on track** | The account has an installment plan and no overdue unpaid installment. | | **Over the run cap** | The per-run maximum was reached; it goes into the next run. | | **Weekly cap** | The customer already got 2 collection messages in the last 7 days. | Recurring retainers never enter: they charge themselves every month. ## The email - The agent writes it with the **real balance**, days overdue, and chosen tone, in the language of the document it collects (English, Spanish, Portuguese, French, or German): the one the invoice or quote took when issued or sent or, if it has none, the client record's or your account's. There's no language to choose in the settings: under **Tone**, the note "Each email goes out in the client's document language." says so. See [Document language](/en/docs/gestion/clientes#document-language). - It always includes the **payment link**: the invoice's or the quote's. If you collect online, the button says "Pay [amount] online" with the amount due today (the overdue installment, if there's a plan); otherwise "View quote and payment options". - It goes out in your business's name, with its legal name, and replies go to your contact email. - The footer includes your legal name, your tax ID, the notice "This message about an outstanding balance is sent to you by [your business].", and the link **Don't contact me through this channel again**. It closes with the line "Sent with Cord". - Below the text, a visible line says the message was drafted with artificial intelligence on your behalf and that the customer can reply to the email to talk to a person at your business. If you have no contact email, it asks them instead to use the contact details you already gave them, because their reply wouldn't reach you. The email also carries a technical marker that identifies it as AI-drafted. What you write yourself from the thread doesn't carry that line. - The AI model doesn't receive your customer's name or email address. - **It never offers discounts on the principal.** ## Approval mode and automatic mode | | Needs approval | Automatic | |---|---|---| | Email | Stays as a draft in the **Approval inbox**. | Sent during the run. | | Plan proposal | The email that proposes it waits for your approval. | The email that proposes it goes out during the run. | | Notice for you | A single email per run: "N collection emails awaiting approval". | Failed ones show in the inbox. | In both modes, an installment plan only activates when your customer accepts it from the link in the email: neither approving the draft nor automatic mode activates it. In the inbox you can: - **Approve and send.** If the draft proposes installments, the email goes out with the proposal; the quote's pending charges don't change until your customer accepts the plan. - **Edit** the text and **Save changes**. - **Regenerate**, optionally with an instruction ("shorter and less formal"). - **Discard**: the email doesn't go out and its proposed plan is canceled. The agent may write again on the next run. - **Don't email them**: adds the account to **Never email**. If you approve several emails without changing a word, Cord suggests switching to automatic. Your call. ## Installment payment plans When an overdue quote reaches the **Propose a plan after** days, the agent can propose **2 up to your maximum monthly installments** (up to 6) that add up to exactly the balance, with no discounts. Cord validates the numbers and calculates the amounts; the agent can't invent them. Plans are only proposed on quote balances, not on invoices. The proposal arrives in the email with a link. There your customer sees each installment, its amount, and its date, and clicks **Accept plan** if it works for them. Only then is the plan created, and its installments replace the quote's pending charges: neither you nor the agent can accept it for them. When they accept, Cord notifies you with a high-priority task and records it on the quote's timeline. If they don't accept within 14 days, the proposal expires. Full details in [Installment payment plans](/en/docs/pagos/cuotas). ## Conversations, exclusions, and promises - **Conversations:** one thread per account, with each message labeled **Agent**, **Customer**, or **You**. You can take over and write yourself from the thread. - **Never email:** customers, quotes, or invoices the agent ignores entirely. They don't get [automatic reminders](/en/docs/pagos/recordatorios) either: it's the same list as the per-customer pause. Click **Remove from list** to bring them back. - **Payment promises:** recorded from [receivables](/en/docs/pagos/cartera-cobranza#record-a-payment-promise). A promise doesn't stop the agent; to pause an account while you wait for an agreed payment, add it to **Never email**. ## One-click opt-out and message cap - **Don't contact me through this channel again:** every email sent from AI collections, by the agent or by you from the thread, carries this link. If your customer clicks it, they're excluded from email collections right away: the agent stops writing to them and they don't get [automatic reminders](/en/docs/pagos/recordatorios) either. Cord notifies you with a high-priority task. The opt-out goes on **Never email** and, since your customer asked for it, it can't be removed from the list. [Automatic reminders](/en/docs/pagos/recordatorios) carry this link too. - **Fixed cap:** a customer gets at most **2 collection messages every 7 days**, counting the agent's emails (in the run, when you approve them, or when it replies) and the ones you write yourself from the thread. It's a Cord limit and can't be raised from the settings. [Automatic reminders](/en/docs/pagos/recordatorios) don't count toward this cap. ## Run now **Run now** runs the agent at that moment with the same logic as the daily run. Use it to test your settings; it still respects cadence, exclusions, and the message cap. ## Indicators | Indicator | What it measures | |---|---| | **Recovered by the agent** | What was collected in the last 30 days on accounts the agent emailed. | | **Awaiting your approval** | Pending drafts (on automatic, it says emails go out on their own). | | **Active payment plans** | Amount committed in installments. | | **Emails sent** | In the last 30 days, with the share that replied and those that couldn't be delivered. | The indicators and the page's sections (**Approval inbox**, **Conversations**, **Payment plans**, **Up next**, and **Never email**) are widgets: with **Customize** you reorder, resize, or hide them with the same icon buttons (**Library**, **Reset**, and **Done**), the same floating library, and the same keyboard support as [Home](/en/docs/gestion/dashboard#customize-home). From the library you can add **Email delivery failures**: collection emails that couldn't be delivered in the last 30 days, next to those sent. The layout is personal and doesn't change what the agent does. ## Limits - Pro, Scale, and Developer only. - One daily run plus the ones you trigger with **Run now**. - Plans on quotes only, 2 to 6 monthly installments, and only if the customer accepts them. A proposal expires after 14 days. - At most 2 collection messages per customer every 7 days; the cap can't be raised. - Each email uses AI quota from the plan. - The agent doesn't send via WhatsApp or SMS. ## Common problems **The agent doesn't email an overdue account.** Check its reason in **Up next**: grace, cadence, exclusion, minimum amount, plan on track, or run cap. It also doesn't write if your customer clicked **Don't contact me through this channel again** or already got 2 collection messages in the last 7 days. **A customer's plan doesn't show as active.** A plan only activates when your customer clicks **Accept plan** from the link in the email. If they don't within 14 days, the proposal expires. **I don't see Configure.** You need the **Settings** permission. **An email shows as "not sent".** The customer has no email or the send failed. Fix the record and try again from the inbox. **Emails fail because of AI quota.** The period's AI usage cap was reached and the agent couldn't draft. Check your usage in [Subscription](/en/docs/cuenta/suscripcion). ## Related - [Installment payment plans](/en/docs/pagos/cuotas) - [Receivables and operating collections](/en/docs/pagos/cartera-cobranza) - [Automatic payment reminders](/en/docs/pagos/recordatorios) - [Credit terms](/en/docs/pagos/credito) --- # Automatic payments URL: https://docs.cordhq.app/en/docs/pagos/cobro-automatico Last updated: 2026-10-14 Your client saves a card or a bank account in their portal and each invoice is charged on its due date. Consent, what's charged and when, retries based on the decline reason, notices, and how you stay in control. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. ## What it is With automatic payments, **your client** saves a card or a bank account in their [portal](/en/docs/pagos/portal-facturas) and authorizes your business to charge there each invoice you issue them from that day on, on its due date. Cord makes the charge, applies the payment to each invoice and, if the bank declines it, decides whether to retry, when, or whether to ask the client for another method. It's **always turned on by the client**: it's their authorization. You decide whether your business offers it and you can turn it off, but you can't turn it on for them. ## Requirements | | Details | |---|---| | **Plan** | All plans. | | **Account** | [Cord Payments](/en/docs/pagos/onboarding) active. Available in Mexico, the United States, Canada, Spain, the United Kingdom, Germany, and France. | | **Offering it** | **Allow automatic payments** turned on in **Settings › Payments › Payment methods** (on by default), with the **Payment settings** permission. | | **Turning it off for a client** | **Clients** permission, from the client's profile. | | **Methods** | Card in any currency. SEPA Direct Debit for invoices in EUR (businesses in Spain, Germany, and France), ACH for invoices in USD (United States), Bacs for invoices in GBP (United Kingdom), and pre-authorized debit for invoices in CAD (Canada), if you turned on [bank debit](/en/docs/pagos/domiciliacion). In MXN, card only. Bank transfer (SPEI or with a reference) isn't used for automatic payments. | ## How your client turns it on 1. You share their [portal](/en/docs/pagos/portal-facturas) from their profile. 2. On the **Automatic payments** card, your client clicks **Turn on automatic payments**. 3. They read and check the authorization: "I authorize [your business] to charge this method, on its due date, each invoice it issues to me from today on. I can turn this off at any time from this portal." They can't continue without checking it. 4. They click **Continue**, enter their card or bank account, and click **Save method**. 5. Back on the portal they see "Done: automatic payments are on." If they saved a bank account that needs to be verified, they see "We're verifying your bank account…": automatic payments turn on as soon as it's confirmed. They can also turn it on **while paying**: when they pay several invoices from the portal, they check **Save this method for automatic payments** along with the same authorization. A **Bacs** account can only be saved this way, while paying: **Turn on automatic payments** doesn't offer it. With Canadian **pre-authorized debit**, your client first states whether the account is a business or a personal one, and the authorization says it's debited on each invoice's due date and on retries. **Consent is evidence, not a click.** Cord stores each authorization on its server with the exact text your client accepted, in their language and with your business name, and a fingerprint of that text, along with the date, IP address, browser, and saved method. It stores it as **pending** and only turns automatic payments on when the processor confirms that the method was saved for that client. If your client changes methods, the previous one is removed and its authorization stays in the history as replaced: there are never two live authorizations, and none is deleted when it changes. Each authorization is kept while it's active and for 540 days after it ends, the period in which a bank can still dispute a charge. ## What's charged and when Once a day, Cord reviews the clients with automatic payments on and charges the invoices that meet **all** of this at the same time: | Condition | Why | |---|---| | It's issued, open, with a balance, with no cancellation in progress, and isn't a test document. | Only what's owed is charged. | | It's due **today or earlier** (or, if it has no due date, it was issued today or earlier). | The charge arrives on the agreed date, not before. | | It was issued at least **one day before** the charge. | Your client receives the invoice before being charged for it. | | It's due **on or after the day of the authorization**. | What they already owed before authorizing isn't charged as a surprise: they pay it from the portal. | | The saved method **covers its currency** and your business still accepts that method. | A SEPA account doesn't pay dollars. | | It has no payment in progress and the retry cycle isn't stopped or waiting for its date. | Nothing is charged twice. | - **One charge per client and per currency.** All invoices due that day in the same currency are charged together, up to 50: a single entry on your client's statement and, where Cord charges a fee, a single fee. - **Recurring invoices included.** A [recurring invoice](/en/docs/pagos/facturas-recurrentes) issued to a client with automatic payments is charged like any other invoice. - **Mexico.** A replaced CFDI, one being replaced, and the global invoice aren't charged automatically. - **Bank debits.** They take days to confirm. Meanwhile, those invoices show **Payment processing** and can't be charged again or voided. ## Notices | Who | When | What they get | |---|---|---| | **Your client** | When their automatic payments turn on. | An email with your branding confirming the authorization: the method (for example, "Visa •••• 4242"), the date they authorized it, that each invoice will be charged on its due date, and the **Open my portal** button to turn it off. It's sent once per authorization, in the language they accepted it in. | | **Your client** | With each invoice you send them while automatic payments are on. | The invoice email adds: "You have automatic payments on: this invoice will be charged to your [method] on [date]. If you prefer to pay it earlier, use the button." | | **Your client** | Before each SEPA debit, when authorizing an ACH debit, and, for Bacs and pre-authorized debit, with the mandate and each debit. | The notice the payment processor sends to the account holder. | | **Your client** | When an automatic charge doesn't go through. | An email with your branding: what happened, the date of the next attempt or what they need to do, and the **Open my portal** button. | | **Your team** | When automatic payments **stop**. | A high-priority task due today, for example "Automatic payments stopped: [client]'s method no longer works ([amount])". A scheduled retry doesn't create a task. | ## Smart retries When a charge fails, Cord doesn't retry blindly. It reads the decline reason and classifies it: | Decline reason | What Cord does | Automatic payments | |---|---|---| | **Stolen, lost, blocked, or fraud-flagged card** | Never retries. | Turned off and the method removed. Your client must add another one. | | **Debit authorization withdrawn** (mandate revoked, unauthorized debit) | Doesn't retry. | Turned off and the method removed. | | **Method no longer works** (expired card, wrong details, closed or invalid account) | Doesn't retry: asks for another method. | Off until your client adds another one. | | **The bank asks for authentication** | Doesn't retry: a charge without the cardholder present can't pass that check. Asks your client to pay from their portal. | Stays on. | | **Insufficient funds** (card) | Retries on the next **1st or 16th of the month**, if it falls between 2 and 7 days later; otherwise after 3 days. | Stays on. | | **Technical failure at the issuing bank** | Retries the next day. | Stays on. | | **Other declines** (card) | Retries after **2, 4, and 7 days**. | Stays on. | - **Card:** up to **4 attempts** (the first one and three retries). After that, charging in that currency stops as "unsuccessful after several attempts" and your client pays from their portal. - **Bank debit (SEPA, ACH, Bacs, or pre-authorized debit):** only retried for **insufficient funds**, up to **3 attempts** (**2** with Canadian pre-authorized debit) and within **30 days** (SEPA, Bacs, and pre-authorized debit) or **40 days** (ACH) of the first one, the same limits the banking scheme applies. With Bacs, an account that changed owner turns the method off like a revoked mandate. The retry falls on the next 1st or 16th of the month if it's between 3 and 7 days later; otherwise after 4 days. Any other debit decline is for your client to sort out with their bank. - **A decline counts once**, even if the bank reports it through two channels. - **The cycle starts over** when a charge in that currency goes through (automatic or from the portal) or when your client saves a new method. ## What you see in Cord On the client's profile, the **Client portal** block shows: - **Automatic payments:** the method it's on with (for example, "Visa •••• 4242" or "SEPA account •••• 3000"), or **Off** with the note "Your client turns it on from their portal, with their authorization." - **Retry scheduled:** "Attempt 1 declined in MXN. Next attempt: October 16, 2026." - **Stopped:** "Stopped in MXN: the bank asks the client to confirm the payment." - **Turned off by the system:** "Turned off automatically: the bank blocked the card." Each invoice also records in its history the charge that didn't go through ("Automatic payment did not go through") and, when it does, the payment like any other. ## Turn off automatic payments | Who | Where | What happens | |---|---|---| | **Your client** | In their portal, **Turn off**. | Charging stops and their saved method is removed. Their invoices stay in the portal to pay whenever they want. | | **You, for one client** | On their profile, **Turn off automatic payments** (Clients permission). | The same. Your client can turn it back on from their portal. | | **You, for everyone** | **Settings › Payments › Payment methods**, **Allow automatic payments** switch (Payment settings permission). It saves right away. | Charging stops for everyone and it's no longer offered in the portal. Saved methods aren't deleted: if you turn it back on, it resumes with them. | Disabling the portal link does **not** turn off automatic payments. ## Limits - Only with Cord Payments: it doesn't work with Mercado Pago or in Colombia, Argentina, Chile, and Peru. - One saved method per client. - Up to 50 invoices per charge, all in the same currency. - What the client already owed when authorizing isn't charged automatically. - Charges go out once a day; a bank debit takes days to confirm. ## Troubleshooting **My client doesn't see the automatic payments option.** Check that **Allow automatic payments** is on in **Settings › Payments › Payment methods** and that your Cord Payments account is active. **Automatic payments are on but an invoice wasn't charged.** Check that it's already due, that it was issued at least one day before, that it's due after the authorization date, and that the method covers its currency (for example, a SEPA account doesn't cover an invoice in USD). **It turned itself off.** The bank declined the method for good (blocked card, withdrawn authorization, or expired method). Your client must add another method from their portal. **My client says their bank asks them to confirm.** It's an authentication decline: your client pays that invoice from their portal and automatic payments stay on for the next ones. ## Related - [Client portal: invoices and payments](/en/docs/pagos/portal-facturas) - [Payment methods](/en/docs/pagos/metodos) - [Automatic reminders](/en/docs/pagos/recordatorios) - [Recurring invoices](/en/docs/pagos/facturas-recurrentes) - [Tasks and follow-up](/en/docs/gestion/tareas) - [Refunds](/en/docs/pagos/reembolsos) --- # Cord Payments fees URL: https://docs.cordhq.app/en/docs/pagos/condiciones Last updated: 2026-10-11 How much Cord charges to process a payment, which currencies carry a platform fee, how VAT is calculated, the SPEI cap, how the fee is activated, and what happens to the fee on refunds and disputes. ## What it is The Cord Payments fee is the per-transaction fee Cord deducts from each online payment processed through your payments account. **It already includes the processing cost**: there's no second third-party fee added later. It's separate from your [Cord subscription](/en/docs/cuenta/suscripcion): it applies the same on every plan. ## Fee by currency The fee depends on the **currency the payment is collected in**, not on the country or the plan. | Payment currency | Cord platform fee today | |---|---| | **MXN** (Mexican pesos) | Yes: the per-method table below. | | **USD** (US dollars) | Doesn't apply. | | **EUR** (euros) | Doesn't apply. | | **GBP** (pounds sterling) | Doesn't apply. | | **CAD** (Canadian dollars) | Doesn't apply. | | **BRL** (Brazilian reais) | Doesn't apply. | In currencies without a platform fee you only pay your payments account's processing cost and your Cord subscription. The **Fee by method** table in **Settings › Payments › Fees** tells you so, with your account's currency. If a fee is ever activated in another currency, it will be published here and you'll have to accept it before it applies. Payments through [Mercado Pago](/en/docs/pagos/mercado-pago) carry no Cord fee: you pay your Mercado Pago account's fee, under your terms with them. Manual transfer carries no fee from anyone. ## Fee table in MXN | Method | Total fee | Example on a $10,000.00 MXN payment | |---|---|---| | **Card** (credit/debit) | 4% + $3.00 MXN + VAT | $467.48 MXN | | **SPEI** (automatic transfer) | 1% + $7.00 MXN + VAT, with a **maximum of $588.12 MXN** per payment | $124.12 MXN | | **Retainers** (monthly recurring card charge) | 4% + $3.00 MXN + VAT on each monthly charge | $467.48 MXN per charge | | **Manual transfer** | $0.00 MXN: doesn't go through Cord Payments | $0.00 MXN | VAT (16%, Mexico's IVA) is calculated on the fee (the percentage component plus the fixed one), never on the full payment amount. By card: (4% of $10,000.00 MXN + $3.00 MXN) × 1.16 = $467.48 MXN. By SPEI: (1% of $10,000.00 MXN + $7.00 MXN) × 1.16 = $124.12 MXN. ### Why SPEI has a cap and card doesn't Processing a SPEI costs practically the same regardless of the amount. That's why the percentage part of the SPEI fee (the 1%) is capped at **$500.00 MXN** before VAT, reached on a **$50,000.00 MXN** payment. From there, a SPEI's total fee stays at **$588.12 MXN**: ($500.00 MXN + $7.00 MXN) × 1.16. | Payment amount | Total card fee | Total SPEI fee | |---|---|---| | $50,000.00 MXN | $2,323.48 MXN (4.65%) | **$588.12 MXN** (1.18% effective) | | $100,000.00 MXN | $4,643.48 MXN (4.64%) | **$588.12 MXN** (0.59% effective) | | $500,000.00 MXN | $23,203.48 MXN (4.64%) | **$588.12 MXN** (0.12% effective) | For large payments in pesos, SPEI is by far the cheapest online method. ### Split payments Each part of a quote is a separate transaction: the [deposit and the balance](/en/docs/pagos/anticipos), each [installment](/en/docs/pagos/cuotas), and each partial payment of an invoice carries its own fee, calculated with the same table. ### Retainers A [retainer](/en/docs/pagos/igualas) is always charged by card, because it's the only way for the charge to go out on its own every month. The fee is the same as a regular card payment, applied to each monthly charge. ## How your fee schedule is activated Cord's fee doesn't apply until you **explicitly accept the current version** of the schedule: 1. Connect your payments account. See [Connect your account](/en/docs/pagos/onboarding). 2. Open **Settings › Payments › Fees** with the **Payment settings** permission. If there's a version you haven't accepted, the **Cord Payments fee** section shows the notice "The current version isn't accepted yet. Until you accept it, Cord won't add its fee". **Settings › Payments › Account** also lets you know, with the **Review fee** link. 3. Review the fees that apply to you in the **Fee by method** table, which is always visible, also after you accept. If your account collects in a currency without a platform fee, each method says **No Cord fee** and a notice confirms it, instead of showing the Mexican table. 4. Check the box accepting the Cord Payments fee terms. 5. Click **Activate current fee** and confirm your identity when Cord asks. The acceptance is recorded in the audit log with the terms version, date, and IP address. Once the current version is accepted, the section says **You accepted the [date] version on [date]**, with the **See terms** link. If we change the schedule, the change is **not retroactive**: the checkbox and the button appear again and the new version doesn't apply until you accept it. A connected account that hasn't accepted the current version keeps collecting with its active methods, and Cord doesn't add its fee to those payments. This protects accounts that were collecting before this schedule existed: nobody changes your fee without your confirmation. Accepting the fee also turns on the quote payment screen where your customer first chooses how to pay, by card or by bank transfer: SPEI in Mexico or [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) in EUR, GBP, or USD, which on quotes only appears on that screen. The full legal text is in the [Terms and conditions, Cord Payments section](https://cordhq.app/en/terminos#cord-pagos). ## What happens to the fee if you refund If you return money to a customer from Cord (a quote's payment in **Revenue › Payments** or an invoice's online payment from its detail page; see [Refunds](/en/docs/pagos/reembolsos)), the refunded amount is deducted from your net revenue, but **the original payment's fee isn't returned**: it's a cost incurred when the payment was processed. ## What happens to the fee in a dispute If a customer disputes the charge with their bank (chargeback), the amount is held while it's resolved. If you lose the dispute, that money leaves your balance along with a processor dispute fee, and Cord's original fee isn't returned either. See [Disputes and chargebacks](/en/docs/pagos/disputas). ## Advantages of collecting with Cord Payments 1. **Automatic reconciliation.** Each payment is tied to its quote or invoice and the status changes to paid as soon as it's confirmed. 2. **The money is yours, straight to your account.** Cord doesn't hold your funds or act as a middleman for the money: you're the merchant of record of every payment. 3. **Checkout with your branding.** Your customer pays inside the document, with your name and colors. 4. **Split payments without double work.** Deposit and balance, installments, partial payments, and retainers all come from the same link. ## Before you activate 1. **Payout timing.** Money doesn't reach your bank instantly: it first lands in your payments account balance and is paid out at the [frequency you choose](/en/docs/pagos/depositos). 2. **Identity verification.** To activate Cord Payments you go through a regulatory verification of the business and the people who control it. See [Connect your account](/en/docs/pagos/onboarding). 3. **Chargebacks.** If a customer disputes a card charge, the business that collected is responsible. Cord gives you the tools to defend yourself with evidence. **Tip:** on very large quotes in pesos, manual transfer is still the no-cost option, at the price of losing automatic reconciliation and verifying each deposit by hand. ## Limits - The platform fee only applies to MXN payments today. - The fee isn't returned on refunds or disputes. - The fee can't be negotiated per account from the app. ## Common problems **I don't see the checkbox to accept the fee.** You already accepted the current version (the **Cord Payments fee** section says when), your payments account isn't connected yet (the section says you can accept it once you connect it), or you don't have the **Payment settings** permission. **My USD payment shows no Cord fee.** That's expected: there's no platform fee outside MXN today. **Net deposited doesn't match what I collected.** Check the **Where every peso goes** widget on the [payments dashboard](/en/docs/pagos/dashboard): it separates fees, refunds, and disputes. ## Related - [Payment methods](/en/docs/pagos/metodos) - [Payouts to your bank](/en/docs/pagos/depositos) - [Invoicing by country](/en/docs/pagos/facturacion) (tax receipt for the fee in Mexico) - [Subscription](/en/docs/cuenta/suscripcion) --- # Credit terms URL: https://docs.cordhq.app/en/docs/pagos/credito Last updated: 2026-10-10 How credit terms work in Cord: Due on receipt and Net 7, 15, 30, 45, 60, or 90; where they're set, how the due date is calculated, what your client sees on approval, when online payment opens, and how collections start once it passes. ## What they are A **credit term** is the time you give your client to pay after approving. In Cord it's expressed as **Net N**: N calendar days counted from approval. With **Due on receipt**, payment is available as soon as the client approves. When a quote carries a credit term, the public link **doesn't offer to pay upfront**: the client approves, sees the date their payment is due, and the pay button only appears when that date arrives. ## Available terms | Term | Days | Where it appears when quoting (editor step 1) | |---|---:|---| | **Due on receipt** | 0 | Visible chip | | **Net 15** | 15 | Visible chip | | **Net 30** | 30 | Visible chip | | **Net 60** | 60 | Visible chip | | **Net 7** | 7 | Under the **Other term** chip | | **Net 45** | 45 | Under the **Other term** chip | | **Net 90** | 90 | Under the **Other term** chip | They're the same seven terms in the app, the [API](/en/docs/desarrolladores/funciones/cotizaciones) (`contado`, `net7`, `net15`, `net30`, `net45`, `net60`, `net90`), the MCP server, and the integrations. In a Spanish-language account, Due on receipt is called **Contado**. ## Where the term is set Cord picks the term for a new quote in this order: 1. **The one you choose when quoting**, in **Who are you quoting?**. It always wins. 2. **The one on the client's profile** (the **Terms** field), which Cord preselects when you pick them. See [Clients](/en/docs/gestion/clientes). 3. **Your account's**, in **Settings › Quotes › Numbering & tax**, field **Default payment terms**. If the client has no term of their own and you change nothing, the quote starts with your account's default term. ## How the due date is calculated The due date is the **approval date plus the term's days**. If the quote isn't approved yet, Cord counts from its creation date. The same calculation is used by the public link, [receivables and collections](/en/docs/pagos/cartera-cobranza), the [reminders](/en/docs/pagos/recordatorios), so they all see the same day. Example: your client approves with **Net 30** on October 12, 2026; payment is due on November 11, 2026. ## What your client sees 1. You send the quote with, for example, **Net 30**. 2. Your client opens the link and sees the **Approve quote** button, the same as with Due on receipt. 3. On approval, the link shows **Quote approved** and, instead of the payment form, the notice **Order confirmed with Net 30 credit** with the line "The payment of [total] is due on [date]". 4. Below it, Cord tells them how they'll pay: - if you collect online, "Once the date arrives you'll be able to pay online from this same link"; - if not, "Coordinate payment directly with the seller". The quote becomes **Approved** and you can deliver the product or service. ### When the due date arrives On the due date, the same link stops showing the credit notice and shows the pay button with the methods you have active (see [Payment methods](/en/docs/pagos/metodos)). Before that date, the quote's payment page sends the client back to the link, which explains when it's due. ### With a deposit If the quote asks for a [deposit](/en/docs/pagos/anticipos), your client pays it on approval and the **balance** is due on the term's date. The link shows the payment plan with the balance marked "Due on [date]" until the day comes. ### Invoices An **invoice** can be paid as soon as you issue it: its due date marks when reminders and collections start, not when payment opens. The invoice for a quote on credit is born with the **same due date** (approval plus the term's days) and, from then on, that due date lives on the invoice. A new invoice without a quote proposes the due date from the term you choose when creating it. In Mexico, an invoice on credit that isn't paid yet is stamped as **PPD** (see [Invoicing and CFDI](/en/docs/pagos/facturacion)). ## Follow-up at the due date - **Automatic reminders**, on every plan: for a quote, your client gets a notice three days before the due date and another on the day it's due; for an invoice, the ones on the schedule you choose in **Settings › Invoicing › Reminders** (by default, 7 and 1 days before, and 3, 7, 14, and 30 days after). You can turn them off or pause a client. See [Reminders](/en/docs/pagos/recordatorios). - **Notice to your team**: the day after the due date, if it's still unpaid, Cord alerts you with the payment overdue notification. See [Notifications](/en/docs/gestion/notificaciones). - **[AI collections](/en/docs/pagos/cobranza-ia)**, from the Professional plan: if you turn it on, the agent includes the overdue account in its daily review and drafts the email with the payment link. - **Late interest**: automatic application is suspended while the legal review by country concludes and generates no charges today. See [Receivables and follow-up](/en/docs/pagos/cartera-cobranza). ## Credit limit Each client can have a **credit limit**. It's a signal, not a block: Cord shows you how much open balance they carry against that limit on their profile and in Collections, but it doesn't stop you from quoting them more. ## Limits - The term counts calendar days, not business days. - A [recurring retainer](/en/docs/pagos/igualas) only exists with Due on receipt: with a credit term, the retainer switch disappears. - Online payment on the due date depends on your country and on your [Cord Payments](/en/docs/pagos/onboarding) or [Mercado Pago](/en/docs/pagos/mercado-pago) account being active. ## Troubleshooting **My client approved and doesn't see the pay button.** That's expected with a credit term: the button appears on the due date. If you need to collect sooner, issue them an invoice or switch the quote to Due on receipt before sending it. **The due date landed on a different day than I expected.** It's counted from the approval date, not from when you sent it. Check the approval date in the quote's timeline. **I want a term that isn't on the list, like Net 120.** Today the terms are the seven on this page. For a different arrangement, use [installments](/en/docs/pagos/cuotas) or set the due date directly on the invoice. ## Related - [Advanced quote options](/en/docs/cotizacion/opciones) - [Deposits](/en/docs/pagos/anticipos) - [How your client accepts and pays](/en/docs/pagos/aceptar) - [Automatic reminders](/en/docs/pagos/recordatorios) - [Receivables and follow-up](/en/docs/pagos/cartera-cobranza) --- # Installment payment plans URL: https://docs.cordhq.app/en/docs/pagos/cuotas Last updated: 2026-10-15 How a monthly installment plan works: who proposes it, how your customer accepts it, how the balance is split, what your customer sees on the link, how each installment is collected, and what happens to the previous balance. ## What it is An **installment plan** replaces the outstanding balance of an overdue quote with **2 to 6 monthly installments** that add up to exactly that balance. Each installment is a separate charge: your customer pays it from the same quote link, with the methods you have active, and the quote is paid once the last one is covered. Today installment plans are proposed by the [AI collections agent](/en/docs/pagos/cobranza-ia) and only exist if your customer accepts them: there's no button to create a plan by hand from the quote. If you want to split a charge **from the start**, use [upfront and balance](/en/docs/pagos/anticipos) or a [credit term](/en/docs/pagos/credito). ## Requirements | Requirement | Detail | |---|---| | Plan | Pro, Scale, or Developer (the plans that include AI collections). | | Permission | **Collections**, to approve the email that proposes the plan (approval mode). | | Setup | Collections agent turned on, with **Maximum instalments** and **Propose a plan after** configured. | | Document | An approved **quote** with an overdue balance. On invoices, the customer can pay part of the balance from the invoice link, but the agent doesn't build an installment plan on them. | | Online payments | Optional. Without Cord Payments or Mercado Pago, the customer sees the installments and due dates, and you record each payment by hand. | ## How a plan is created 1. **The account reaches the threshold.** The agent can propose installments only when the quote is at least as many days overdue as your **Propose a plan after** setting (15 by default) and has no proposed or active plan. 2. **Cord validates the numbers.** Cord checks that the number of installments is between 2 and your configured maximum, and that the proposal covers the full balance, with no discount on the principal. Cord calculates each installment amount, not the agent. 3. **The proposal goes out.** In approval mode, the email sits in the **Approval inbox** labeled "Proposes N instalments of [amount] · your customer decides whether to accept it" and goes out when you click **Approve and send**; in automatic mode, it goes out during the run. Sending the proposal doesn't change the quote's charges. 4. **Your customer decides.** The email carries a link where your customer sees each installment, its amount, and its date, and clicks **Accept plan** if it works for them. Neither you nor the agent can accept it for them. 5. **The plan activates.** Only when your customer accepts do its installments replace the quote's pending charges, and you get a notice. Your customer pays each installment from the same quote link. If your customer doesn't accept within **14 days**, the proposal expires and the quote's charges stay as they were. If you discard or regenerate a draft that proposed a plan, the proposed plan is deleted. Since it was never activated, there are no charges to undo. ## How the balance is split - The balance is divided into equal parts and **the last installment absorbs any rounding difference**, so the total is exact to the cent. - The dates are set when the proposal goes out: the **first installment is due on the last day to accept it, 14 days after it's sent**; each one after that, one month after the previous one. - Installments are in the quote's currency. For example, a balance of $10,000.00 MXN in 3 installments becomes two installments of $3,333.33 MXN and one of $3,333.34 MXN, due 14 days after the proposal is sent, one month later, and two months later. ## What your customer sees The quote link lists each installment with its number, amount, and status. The payment button charges **the next installment that's already due**, never the full balance or a future installment. When nothing is due today, the link explains when the next one is due instead of showing the button. Each installment is paid with your account's active methods: card, SPEI (quotes in MXN), [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) (quotes in EUR, GBP, or USD with a linked client, a new feature), or Mercado Pago. If your client pays by transfer, each installment has its own instructions: with SPEI, its own CLABE; with bank transfer with a reference, the client's same account and a reference of its own. ## Fees Each installment is a separate transaction for fee purposes: on payments in Mexican pesos (MXN), Cord Payments applies its fee to each installment separately; in other currencies there's no platform fee today. See [Cord Payments fees](/en/docs/pagos/condiciones). ## Tracking - **Collections agent › Payment plans** shows each plan with its progress ("2 of 3 instalments paid") and the next installment's date. - **Collections agent › Active payment plans** adds up what's committed in installments. - While the customer is **on track** (no overdue unpaid installment), the agent doesn't email them: in **Up next** they show as "Plan on track". If an installment falls due unpaid, the account returns to collections and the email points to that installment, not the full balance. - When your customer accepts, the quote timeline records it and Cord creates a high-priority task to let you know. ## Limits - 2 to 6 monthly installments; you set the maximum between those values (3 by default). - Monthly installments only. - One proposed or active plan per quote. - Only your customer can accept the plan; the proposal expires after 14 days. - No discounts on the principal and no added interest. - Quotes only, not invoices. - Not created from the quote editor. ## Common problems **The agent doesn't propose installments.** Check that the account reached the **Propose a plan after** days, that it doesn't already have a proposed or active plan, and that your customer hasn't opted out of collection emails. **I approved the email and the plan isn't active.** Approving sends the proposal; the plan activates when your customer clicks **Accept plan**. If they don't within 14 days, the proposal expires. **A customer with a plan stopped getting emails from the agent.** They're on track: no installment is overdue. They return to collections if an installment falls due unpaid. **The customer paid the old balance after the plan activated.** If a transfer that was already on its way arrives later, Cord still records it, because the money did arrive. Review the quote's charges and, if there's an overpayment, arrange the refund with your customer. ## Related - [AI collections](/en/docs/pagos/cobranza-ia) - [Upfront and balance](/en/docs/pagos/anticipos) - [Credit terms](/en/docs/pagos/credito) - [Receivables and operating collections](/en/docs/pagos/cartera-cobranza) --- # Payments dashboard URL: https://docs.cordhq.app/en/docs/pagos/dashboard Last updated: 2026-10-11 A tour of Revenue › Payments: who can see it, what each of its 12 widgets measures, where the data comes from, how to customize it, and how to refund from the recent payments table. ## What it is **Payments** (sidebar › **Revenue**) is the dashboard to **see** money that already came in: collected, net of fees, payouts, disputes, and the health of your payments account. It's different from **Settings › Payments**, where you **configure** Cord Payments across four tabs: **Account** (verification), **Payment methods**, **Payouts**, and **Fees**. ## Requirements | Requirement | Detail | |---|---| | Plan | All plans. | | Permission | **Collections**. Without it, the page shows "No access". | | Refunds | Also the **Refunds** permission, which the owner grants explicitly. | | Payments account | Needed for Available balance, Deposits, Net deposited, Open disputes, and Where every peso goes. Without it, those widgets don't appear and the rest works with your recorded payments. | ## Date range and customization - **Date range:** the selector at the top applies to every period widget (up to one year back). Changing it updates the whole dashboard at once. It's remembered in your browser and written into the page address, so a copied link opens the same period. Balance, Deposits, and Account status always show the current state. - **Customize:** the sliders-icon button enters edit mode. There, three round icon buttons with tooltips appear: **Library**, **Reset** (restores the original layout), and **Done**. You can drag, use **Move up** and **Move down**, choose **Compact** or **Expanded**, and hide any widget, also with the keyboard. The configuration is personal and follows you to other devices. On a phone, widgets are reordered with 44 px move up, move down, and hide buttons. The details are in [Home and views](/en/docs/gestion/dashboard#customize-home). - **Library:** a floating card (a bottom sheet on a phone) with search, thumbnails, and the **Add** button. Besides bringing back widgets you hid, you can add **Recurring contracts** (current recurring revenue from your retainers). Widgets that need the payments account don't appear in the library until you have one. ## The widgets ### Your money today **Available balance.** How much is available for payout, how much is still **on the way** (collected but not released yet), and how much is **reserved**. **Deposits.** Transfers to your bank account with arrival date, amount, currency, and status: **Scheduled**, **In transit**, **Deposited**, **Failed**, or **Canceled**. The history is stored in Cord and survives frequency changes. If there are none yet, the widget says so. See [Payouts to your bank](/en/docs/pagos/depositos). **Account status.** Three independent indicators: | Indicator | What it says | |---|---| | **Payments** | Whether your account can collect online right now (Active / Inactive). | | **Payouts** | Whether it can transfer to your bank, and to which account ("Payouts to [bank] ••••1234"). | | **Verification** | Whether it's complete, how many requirements are missing, how many are under review, and their deadline. | When something is pending, **Manage** appears and takes you to complete it in **Settings › Payments › Account**. If you haven't activated Cord Payments yet, the widget explains it: you can quote and record manual payments, but not collect online with Cord Payments. In Colombia, Argentina, Chile, and Peru, where Cord Payments isn't available, it tells you that collecting inside the link is turned on with [Mercado Pago](/en/docs/pagos/mercado-pago). ### Key indicators **Collected.** The amount collected in the period, the number of transactions, the change versus the previous period, and a daily mini chart. It includes manually recorded payments. **Net deposited.** What you collected **after the Cord Payments fee**, with the period's fee and the effective rate (which varies with the methods your customers pay with). If the period has more than 1,000 transactions, it warns that it's a partial sample. **Active retainers.** How many [recurring payment](/en/docs/pagos/igualas) contracts are active and how many have a failed charge that needs attention. **Open disputes.** How many chargebacks there are in the period and the amount at stake, with the response deadline for each. Each dispute opens its [evidence page](/en/docs/pagos/disputas). With no disputes, it says so. ### Movement and reconciliation **Collection over time.** Money that came in day by day, against the same number of days in the previous period (in a lighter tone). **Monthly volume.** What you collected month by month within the period. **Where every peso goes.** From the gross collected: how much lands net in your bank, how much went to fees, how much was deducted for refunds, and how much is tied up in disputes. **Breakdown by method.** How much you collected by card, SPEI, bank transfer (with a reference), and manual transfer, with the number of transactions. Tap a method to filter the recent payments table. **Recent payments.** Number, customer, method, date, and amount of the latest payments. With the **Refunds** permission, every reconciled payment has a **Refund** button. See [Refunds](/en/docs/pagos/reembolsos). ## Where the data comes from - **Collected, Retainers, Monthly volume, Breakdown by method, and Recent payments** come from payments recorded in Cord, so they load with the page. - **Balance, Deposits, Net, Where every peso goes, and Disputes** fill in a few seconds later with your payments account's information. If that request fails, you'll see "Could not refresh the dashboard" instead of made-up numbers. - Mercado Pago payments are recorded as payments, but their balance and payouts live in your Mercado Pago account. ## Limits - The dashboard doesn't show which payments make up each payout. - It doesn't include invoices pending collection: for what you're owed, use [Collections](/en/docs/pagos/cartera-cobranza). - It doesn't read Mercado Pago chargebacks. ## Common problems **Balance and Deposits don't appear.** Your payments account isn't connected yet. **Net deposited says "We couldn't reconcile the fees".** The request to your payments account failed. Reload later. **I don't see the Refund button.** You need the **Refunds** permission, and the payment must have been reconciled through Cord Payments. This table lists quote payments: an invoice payment is refunded from the invoice's detail page (see [Refunds](/en/docs/pagos/reembolsos#refunding-an-invoice-payment)). ## Related - [Payouts to your bank](/en/docs/pagos/depositos) - [Refunds](/en/docs/pagos/reembolsos) - [Disputes and chargebacks](/en/docs/pagos/disputas) - [Cord Payments fees](/en/docs/pagos/condiciones) - [Reports and performance](/en/docs/gestion/informes) --- # Payouts to your bank URL: https://docs.cordhq.app/en/docs/pagos/depositos Last updated: 2026-10-11 How the money you collect with Cord Payments reaches your bank: daily, weekly, monthly, or manual frequency, the status of each payout, history, payout account by country, and why a payout can be paused. ## What a payout is When your customer pays by card, bank transfer (SPEI or with a reference), or bank debit, the payment first lands in the **balance of your payments account**, in your business's name. A **payout** is the transfer of that balance to your bank account. Cord doesn't hold the money or move it through an account of its own: you choose the pace and Cord shows you every movement. [Mercado Pago](/en/docs/pagos/mercado-pago) payments don't go through here: they land in your Mercado Pago account and you withdraw them from there. Manual transfers don't either, because the money is already in your bank. ## Requirements | Requirement | Detail | |---|---| | Plan | All plans. | | Country | Mexico, United States, Canada, Spain, United Kingdom, Germany, and France (where Cord Payments operates). | | Account | A verified [payments account](/en/docs/pagos/onboarding) with status **Active**. | | Permission to configure | **Payment settings**, to change the frequency or the payout account. | | Permission to view | **Collections**, to see the history in **Revenue › Payments**. | | Currency | Payouts arrive in the currency of your payments account's country: MXN in Mexico, USD in the United States, CAD in Canada, EUR in Spain, Germany, and France, GBP in the United Kingdom. | ## Choose your payout frequency 1. Open **Settings › Payments › Payouts**. The **Payout frequency** section appears once your account is active. 2. Under **Frequency**, choose **Daily**, **Weekly**, **Monthly**, or **Manual**. 3. If you chose **Weekly**, pick the **day of the week** (Monday to Friday). If you chose **Monthly**, pick the **day of the month**, from 1 to 28. 4. Click **Save changes** in that same section. Cord asks you to confirm your identity with your password or your two-step verification code: deciding how fast your money leaves is as sensitive as changing where it goes. 5. You'll see **Payout frequency updated**. What gets saved is what your payments account confirmed, not just what you picked. ### Which option fits | Frequency | When the money leaves | Use it if | |---|---|---| | **Daily** | Every business day, whatever is available goes out. | You need constant liquidity. You pay each transfer's fixed cost more often. | | **Weekly** | Once a week, on the day you choose. | You reconcile weekly or pay suppliers on a fixed day. | | **Monthly** | Once a month, on the day you choose. | You prefer to pool the money and reconcile once. The money stays away from your bank longer. | | **Manual** | It doesn't leave automatically. | Read the warning below before choosing it. | Days 29, 30, and 31 don't exist in every month: a payout scheduled for the 31st would silently skip February. That's why Cord only accepts 1 through 28. With **Manual**, payments pile up in your payments account balance and are not sent to your bank on their own. Today Cord has no button to request a one-off payout from the app. If you choose Manual and need to release the money, switch to Daily, Weekly, or Monthly, or write to us. ## Payout statuses Each payout appears in the **Deposits** widget of [Revenue › Payments](/en/docs/pagos/dashboard) with its amount, currency, arrival date, and one of these statuses: | Status | What it means | |---|---| | **Scheduled** | The payout was created and is waiting its turn. | | **In transit** | It left for your bank and arrival isn't confirmed yet. | | **Deposited** | Your bank received it. Final status. | | **Failed** | The bank rejected it (for example, the account no longer exists or the holder doesn't match). Final status. | | **Canceled** | It was canceled before leaving. Final status. | A final status never goes backwards: if a late notice arrives after a payout is **Deposited**, Cord doesn't move it back to **In transit**. In **Settings › Payments › Payouts**, the **Balance and next payout** section shows what's **Available**, what's **Processing**, the **Next payout** with its arrival date, and your last five payouts with their status. **See payout history** takes you to **Revenue › Payments**. ### History Cord stores every payout as its status changes. The history loads with the page, survives changes of frequency or account, and helps you reconcile against your bank statement: look for the same amount and arrival date. Today Cord doesn't show which payments make up each payout. To match a payout to its payments, use the date and amount, plus the **Recent payments** table on the same dashboard. ### Payout events If you use the API or Workflows, Cord emits two events: - **A payout is paid to your bank** (`payout.paid`): with amount, currency, arrival date, and method. - **A payout fails** (`payout.failed`): also includes the failure reason. Use them to alert finance in Slack or record the payout in your accounting. See [Workflow triggers](/en/docs/automatizacion/workflows/disparadores) and [webhooks](/en/docs/desarrolladores/herramientas/webhooks). ## Your payout account The account is registered in the **Bank account** step when you [connect your account](/en/docs/pagos/onboarding) and uses your business country's banking format. Cord checks the format **before** sending it, so a mistyped digit is flagged by Cord instead of a bank rejection days later. | Country | What you enter | What Cord checks | |---|---|---| | Mexico | CLABE (18 digits) | Length and check digit. | | Spain, Germany, and France | IBAN | Structure and check digits (mod 97). | | United States | Routing number (ABA, 9 digits) and account number (4 to 17 digits) | Length and the routing number's check digit. | | United Kingdom | Sort code (6 digits) and account number (8 digits) | Length and format. The sort code has no check digit. | | Canada | Transit number (5 digits), institution number (3 digits), and account number (5 to 12 digits) | Length and format. | Besides the number, you enter the **account holder name**. The account must be in the name of the business or its legal representative. ### Change your payout account 1. Open **Settings › Payments › Payouts** with the **Payment settings** permission. 2. In the **Bank account** section, click **Change** next to the account (or **Edit bank account** if you haven't registered one yet). 3. Enter the full new account and the holder name. For security, Cord never shows the previous account again, only its last four digits. 4. Confirm your identity when Cord asks. 5. The next payouts go to the new account. The **Bank account** section shows the bank and the last four digits. The payout account is stored encrypted. Every change is recorded in your organization's audit log. ## Paused payouts If the frequency section says **Payouts are paused until verification completes**, **Settings › Payments › Account** shows **Payouts: Paused**, or the **Account status** widget shows **Payouts: Inactive**, your payments account may still have pending requirements. Meanwhile, payments keep accumulating in your balance but don't leave for your bank. The usual causes: - **A pending or overdue verification requirement**, such as an unreadable photo, an expired document, or an unverified person. The **Account status** widget shows how many requirements are missing and their deadline; **Manage** takes you straight to them. - **A rejected payout account**, for example a closed account or one in someone else's name. Register a valid account. - **A review of the payments account.** If the widget says your account is temporarily paused, review the requirements to reactivate it. Once you complete what's pending, payouts resume at the frequency you had. ## Limits - Frequency and account can only be configured when the payments account is **Active**, and only in the seven Cord Payments countries. - The weekly day ranges from Monday to Friday; the monthly day from 1 to 28. - No instant or on-demand payouts from Cord. - No breakdown of which payments each payout contains. - The country and currency of the payments account can't be changed after it's created. ## Common problems **I don't see the frequency section.** Your account isn't **Active** yet, your country doesn't have Cord Payments, or you don't have the **Payment settings** permission. **I saved the frequency and it asked for my password again.** Identity confirmation lasts a few minutes. If more time passed, Cord asks again. **A payout shows Failed.** Check that the account is still open and in the correct holder's name. If it changed, register it again. If the account is correct, write to us with the payout's date and amount. **My balance grows but nothing reaches my bank.** Check whether you chose **Manual** or whether payouts are paused for verification. **The payout amount doesn't match what I collected.** Payouts are net: they already deduct fees, refunds, and amounts held by disputes. Check the **Where every peso goes** widget on the [payments dashboard](/en/docs/pagos/dashboard). ## Related - [Connect your account](/en/docs/pagos/onboarding) - [Payments dashboard](/en/docs/pagos/dashboard) - [Cord Payments fees](/en/docs/pagos/condiciones) - [Disputes and chargebacks](/en/docs/pagos/disputas) --- # Disputes and chargebacks URL: https://docs.cordhq.app/en/docs/pagos/disputas Last updated: 2026-10-11 What to do when a customer disputes a card charge: where the dispute appears, who can respond, what evidence Cord builds from your data, how to submit it before the deadline, and what happens to the money and the fee. ## What a dispute is A dispute (chargeback) happens when a cardholder asks their bank to reverse a charge: because they don't recognize it, because they say they didn't receive what they paid for, or for another reason. The bank holds the amount while it's resolved, and you have a limited time to present evidence that the charge was legitimate. It applies to **card** payments processed by Cord Payments. A bank transfer (SPEI or [with a reference](/en/docs/pagos/transferencia-referencia)) or a manual transfer has no card chargeback, and a [bank debit](/en/docs/pagos/domiciliacion) charge is claimed under its scheme's rules. [Mercado Pago](/en/docs/pagos/mercado-pago) chargebacks are handled from your Mercado Pago account: Cord doesn't read them today. ## Requirements | Requirement | Detail | |---|---| | Plan | All plans. | | Permission | **Collections** or **Payment settings**. Without them, the dispute page shows "No access". | | Submission | Also confirming your identity with your password or your two-step verification code. | ## Where it appears 1. Cord records the dispute as soon as the processor reports it, with amount, currency, reason, status, and deadline. 2. In [Revenue › Payments](/en/docs/pagos/dashboard), the **Open disputes** widget shows the total at stake and, for each dispute, "respond before [date]". 3. Opening a dispute takes you to its evidence page, **Build a clear response**, with the amount, the status, and the **due date** at the top. The account owner also gets an email, in your account's language, with the subject **Action required: dispute for [amount]**, and Cord adds to [Tasks](/en/docs/gestion/tareas) a high-priority task titled "Respond to the [amount] chargeback" (in your account's language), unassigned, linked to the payment's quote, and due on the day, in your business's time zone, the evidence deadline falls on. Because it's unassigned, the email reminder for that task goes to the account owner. Like any task, it emits **A task is created** (`task.created`). If you use the API or Workflows, Cord emits **A dispute is opened** (`dispute.created`) and **A dispute is closed** (`dispute.closed`, with the outcome). See [Workflow triggers](/en/docs/automatizacion/workflows/disparadores). If you don't submit evidence before the deadline, you normally lose the dispute. The deadline is set by the card network, not by Cord: start working on it as soon as you see it. ## Statuses The status appears next to the amount with the processor's name for it: | Status | What it means | |---|---| | `needs response` | Evidence must be submitted before the deadline. | | `under review` | You already submitted evidence and the customer's bank is reviewing it. | | `won` | You won: the held money returns to your balance. | | `lost` | You lost: the amount leaves your balance. | | `warning needs response`, `warning under review`, `warning closed` | An early inquiry from the bank that isn't a chargeback yet. Respond anyway: it can become one. | ## The evidence The page arrives **prefilled** with what Cord already knows about the transaction. Review and correct each field: | Field | What Cord proposes | |---|---| | **Customer name** and **Customer email** | Those on the quote's customer record. | | **Service date** | The quote's approval date. Change it to the actual delivery date. | | **Approval IP** | The IP address from the quote's electronic signature, if there is one. | | **What the customer purchased** | The quote's items with their quantities. | | **Customer communication** | Empty: paste the relevant messages here (acknowledgments, delivery confirmations). | | **Additional context** | Empty: explain the case in your own words. | | **Receipt or supporting file** | Optional: your own PDF, JPG, or PNG. If you don't choose one, Cord prepares an automatic receipt. | ### What Cord builds for you On submission, Cord generates two PDFs: 1. **Transaction receipt:** your business, the customer, the amount, the method, the transaction, the items and, when available, **who signed the quote, on what date, and from which IP address**. If you uploaded your own receipt, yours is used. 2. **Customer communication:** a PDF with the text you pasted in that field. ## Save a draft and submit 1. Click **Save draft** as many times as you like. The draft stores only text in Cord: it doesn't upload files or send anything to the processor. 2. When ready, click **Review and submit evidence**. You'll see a **preview** with the exact list of what will be transferred. 3. Click **Confirm and transfer** and confirm your identity when Cord asks. 4. You'll see **Evidence submitted** and return to Payments. Once submitted, the evidence can't be edited or completed. Review every field before confirming. Saving, preparing the PDFs, and submitting are recorded in your organization's audit log. ## What happens next The processor delivers the evidence and **the customer's bank decides**. It can take weeks and the outcome isn't guaranteed: Cord helps you build the best possible case, but doesn't decide. The status updates on its own on the dispute page. | If… | Then | |---|---| | You win | The held amount returns to your balance. | | You lose | The amount leaves your balance, along with a processor dispute fee. | | Either way | Cord's fee on the original payment isn't returned. See [Fees](/en/docs/pagos/condiciones). | ## How to prevent disputes - Require an **electronic signature** on approval: the signature's name, date, and IP are your best evidence. See [Electronic signature](/en/docs/interaccion/firma). - Use clear item descriptions and a recognizable business name. - Answer your customers' questions in the quote chat: that history is evidence too. ## Limits - Card payments processed by Cord Payments only. - A single evidence submission per dispute. - No Mercado Pago disputes in Cord. ## Common problems **I can't find the dispute.** Check the dashboard's date range and that you have the **Collections** or **Payment settings** permission. **The approval IP is empty.** The quote had no electronic signature. Explain in the additional context how your customer confirmed the purchase. **Submitting asks for my password again.** Identity confirmation lasts a few minutes; if more time passed, Cord asks again. ## Related - [Payments dashboard](/en/docs/pagos/dashboard) - [Refunds](/en/docs/pagos/reembolsos) - [Cord Payments fees](/en/docs/pagos/condiciones) - [Electronic signature](/en/docs/interaccion/firma) --- # Bank debit URL: https://docs.cordhq.app/en/docs/pagos/domiciliacion Last updated: 2026-10-11 Collect invoices with a direct debit from your client's account: SEPA in euros, ACH in US dollars, Bacs in pounds, and pre-authorized debit in Canadian dollars. How to turn it on, how long each scheme takes, automatic payments, retries, and refunds. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. ## What it is With bank debit, your client pays with a **direct debit from their bank account** instead of a card. When paying they accept an authorization (the mandate) and the bank confirms the debit days later. Cord offers the scheme that matches your business's country, always in its currency. It's different from [bank transfer with a reference](/en/docs/pagos/transferencia-referencia): with a transfer your client sends the money from their bank; with a debit, you collect it with their authorization. ## Schemes by country | | SEPA Direct Debit | ACH bank debit | Bacs Direct Debit | Pre-authorized debit (Canada) | |---|---|---|---|---| | **Businesses in** | Spain, Germany, and France | United States | United Kingdom | Canada | | **Currency** | EUR only | USD only | GBP only | CAD only | | **Client's account** | IBAN in the SEPA area | US bank account | UK account (sort code and account number) | Canadian bank account | | **Confirmation** | Up to 6 business days | Up to 4 business days | 4 business days; 7 with a new mandate | Up to 5 business days | | **Refunds** | Full or partial, up to 180 days | Full only, up to 180 days | Full or partial, up to 180 days | Full or partial, up to 180 days | | **Account holder disputes** | Can return a debit without giving a reason for 8 weeks | Under ACH rules | Can dispute a debit with their bank at any time | 90 days on a personal account; 10 business days on a business account | | **Save the account for automatic payments** | From the portal, without paying | From the portal, without paying | Only when paying an invoice from the portal | From the portal, without paying | The scheme's notices (the mandate confirmation and the notice for each debit) are sent by the payment processor to the email your client enters in the payment form. ## Requirements - **Country and currency:** a business in one of the countries in the table and an invoice in its scheme's currency. An invoice in another currency doesn't offer bank debit. - **An active payments account** and the method activated on your account by the payment processor. - **Payment settings permission** to turn it on. ## Turn it on 1. Open **Settings › Payments › Payment methods** with the **Payment settings** permission. Your payments account has to be active; before that, the Cord Payments methods appear locked. 2. Under **Online payments**, turn on your country's scheme: **SEPA Direct Debit** (Spain, Germany, and France), **ACH bank debit** (United States), **Bacs Direct Debit** (United Kingdom), or **Pre-authorized debit (Canada)**. 3. Cord requests the method from the payment processor for your account. While it's under review, it isn't offered to any client yet. 4. Once the processor activates it, it appears as an option on your invoice links in the scheme's currency, in the [client portal](/en/docs/pagos/portal-facturas), and in [automatic payments](/en/docs/pagos/cobro-automatico). If the screen says the method isn't available, the processor didn't enable it: check the pending requirements of your [payments account](/en/docs/pagos/onboarding). ## How a debit works - **Where it's offered:** on the invoice link, in the client portal, and as the saved method for automatic payments, only on invoices in its currency. It isn't offered on the quote link or for retainers. - **It takes days.** While the bank confirms, the invoice shows that a payment is in progress: it can't be charged again or voided, and the invoice detail says so. When the debit is confirmed, the payment is applied like any other; if the bank rejects it, the invoice goes back to unpaid. - **Where Cord charges a fee (today, in MXN), it isn't offered.** Cord's fee is a card fee and there's no approved rate for debits. Outside MXN, Cord charges no platform fee; see [Fees](/en/docs/pagos/condiciones). - **Turning it off** stops offering it on new payments; debits already in progress continue. - **A confirmed debit can still be disputed** under its scheme (see the table). Keep that in mind before handing over something of high value against a recently confirmed debit. ## Canadian pre-authorized debit - **Business or individual.** Before the payment form, the link asks **Paying from your bank account?** with **Yes, as a business** and **Yes, as an individual**. The answer is recorded in the debit authorization and adds the option to the form. If you also accept cards, your client can pay by card without answering; the question is only required when the debit is the only method. - **Micro-deposit verification.** Some accounts are verified with a small deposit. The link then tells your client that within 1 to 2 business days they'll receive that deposit and an email with instructions, with the **Verify my account** button. The payment completes once they confirm the account. Meanwhile, the invoice can't be paid twice: if your client opens the link again, they see the verification link again. - **Automatic payments.** When the account is authorized from the portal, the authorization says the debit is made on each invoice's due date and on retries if a debit fails. ### In the client portal In the [portal](/en/docs/pagos/portal-facturas), the same question appears in the **Pay selected** sheet before **Continue**, and also when turning on automatic payments. If the account is verified with micro-deposits, the sheet hides the pay button and shows the same notice with **Verify my account**. The invoices in that payment stay in **Payment processing** until your client confirms the account or the verification expires: neither the portal nor each invoice's link charges them again. ## Bacs Direct Debit - **Saved when paying.** A Bacs account can't be registered for automatic payments without paying anything: your client saves it when paying an invoice from their portal, by ticking **Save this method for automatic payments.** - **Who appears as the collector.** Your client's bank statement and the scheme's emails show the payment processor as the collector, not your business's name. Let your client know so they recognize the debit. - **Disputes with no time limit.** The account holder can dispute a debit with their bank at any time, even after a refund. If you refund a payment, let them know so they don't receive it twice. ## Automatic payments and retries Your client can authorize their account in their portal so their invoices are collected when due. If a debit fails: - **It's only retried for insufficient funds**, within its scheme's window and limit: two retries within 30 days for SEPA and Bacs, two within 40 days for ACH, and one within 30 days for pre-authorized debit. - **A revoked mandate** turns the method off and isn't retried. For Bacs, so does an account that changed owner. - Your client gets an email with their portal and you get a task when collection stops. Details in [Automatic payments](/en/docs/pagos/cobro-automatico). ## Refunds A bank debit payment is refunded from the invoice detail, up to 180 days after the charge. SEPA, Bacs, and pre-authorized debit support partial refunds; ACH, full refunds only. The dialog tells you the deadline and what your client will see before you confirm. See [Refunds](/en/docs/pagos/reembolsos). ## Limits - Each scheme only in its currency and only for businesses in its country. - Only on invoices, the portal, and automatic payments: not on quotes or retainers. - Not offered where Cord charges a fee (today, in MXN). - A Bacs account isn't saved without paying. ## Common problems **My client doesn't see bank debit.** The invoice isn't in the scheme's currency, the method is turned off in **Settings › Payments › Payment methods**, or the processor hasn't activated it on your account yet. **My client in Canada doesn't see the debit in the form.** They haven't answered whether they're paying as a business or an individual yet: the option appears once they answer. **The invoice says a payment is in progress and my client wants to pay by card.** You have to wait for the bank to confirm or reject the debit. If it's a pre-authorized debit awaiting verification, your client has to finish the verification from the link on the invoice page. **My client doesn't recognize a Bacs debit.** The debit appears under the payment processor's name, not your business's. Confirm the amount and the invoice with them. ## Related - [Payment methods](/en/docs/pagos/metodos) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Client portal: invoices and payments](/en/docs/pagos/portal-facturas) - [Automatic payments](/en/docs/pagos/cobro-automatico) - [Refunds](/en/docs/pagos/reembolsos) - [Invoicing by country](/en/docs/pagos/paises/resumen) --- # E-invoicing: Factur-X, XRechnung, Peppol, and Facturae URL: https://docs.cordhq.app/en/docs/pagos/factura-electronica Last updated: 2026-10-13 Download each invoice as Factur-X, XRechnung, or Peppol BIS (EN 16931), or as Facturae in Spain, attach it to the email, issue it through an approved platform in France, and get ready for e-invoicing between businesses with the AEAT. If your business is established in the European Union, every invoice issued in Cord is also available as an **e-invoice** under the European standard **EN 16931**. It is not a different document: it has the same number, the same date, and the same amounts as the PDF, written so your client's system can process it without keying it in. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. ## Formats - **Factur-X (PDF):** the invoice PDF with the XML inside (EN 16931 profile). It opens like any PDF, and systems that accept Factur-X or ZUGFeRD also read it. It is the usual format in France. - **XRechnung (UBL) and XRechnung (CII):** the format required by the German public sector and accepted by many companies in Germany. UBL is the most common; CII is there in case your client asks for it. - **Peppol BIS 3.0 (UBL):** the format of the Peppol network, used across much of Europe. - **Facturae 3.2.2 (XML):** the Spanish format, only for businesses established in Spain and invoices in euros. It is the only one that declares the **IRPF withholding**. Your client's document language doesn't change any XML: the same document produces the same file in any language. In Factur-X, the visible PDF does follow the invoice's language (in France, with French first); the XML inside doesn't change. See [Invoice language](/en/docs/pagos/facturacion#invoice-language). Cord **generates** these files, lets you download them, and can attach them to the invoice email. It **does not send them** over the Peppol network or to FACe. If your client asks to receive them over Peppol, download them and upload them to your access provider. In France, Cord does transmit them through an approved platform: see [E-invoicing in France](#e-invoicing-in-france). ## Set up your data once 1. In **Settings › Tax profile**, **European e-invoicing** section, fill in the **billing contact** and the **contact phone**. XRechnung requires a contact with name, phone, and email (your business email is used). 2. Add your **electronic address**: the scheme (for example GLN, SIRET, or your VAT number) and the identifier. Peppol requires it; XRechnung uses your email if there is none. 3. If you have them, add your **company registration number** and your bank's **BIC**. The IBAN on the invoice is the one under **Manual bank transfer**, in **Settings › Payments › Payment methods**; XRechnung requires it to state how to pay. 4. On each client that needs it, open the **E-invoicing** section and enter their **electronic address** and **buyer reference**. In Germany, for public bodies, the reference is the **Leitweg-ID** and it is mandatory (see [Leitweg-ID](#leitweg-id)). When you create an invoice you can also enter the **buyer reference** and the **purchase order** in the editor summary. If you leave the reference empty, the client's is used. Peppol requires at least one of the two. ## Download Open the issued invoice. In the right column, the **E-invoice** section lists every format that invoice can already produce, ready to download. For the others, it says which data is missing and links to the place where you fix it. Your client can also download the available formats from the invoice's public link, next to the PDF. An issued invoice keeps the data it was issued with. If you correct your contact, your electronic address, or the client's, the change applies to the **next** invoices; the issued one is not rewritten. ## Attach to the email In **Settings › Tax profile › Attach to invoice emails** you choose what goes with the email: - **Automatic:** Factur-X in France, PDF plus XRechnung XML in Germany, and the PDF only elsewhere. - **PDF only.** - **Factur-X PDF:** replaces the regular PDF (it looks the same and carries the XML inside). - **PDF + XRechnung XML.** - **PDF + Facturae XML** (Spain only): signed if you turned signing on, unsigned otherwise. In Spain the automatic value is the PDF only: your client does not expect an XML they did not ask for. If an invoice is missing data for the chosen format, the email goes out with the regular PDF and the invoice tells you what is missing. Sending never stops because of this. ## Taxes and exemptions Each line is classified with the European VAT category: - with a rate above zero, **standard or reduced rate**; - at 0%, the **reason** you chose on the exempt profile in **Settings › Taxes** (reverse charge, intra-community supply, export, not subject to VAT, zero rated, or an exemption of the VAT Directive). In Spain, the Verifactu reason is used; - at 0% without a reason, Cord infers it: the issuer's small-business scheme, a client in another EU country with a VAT number (reverse charge), a client outside the EU (export), or a domestic exemption. **Canary Islands, Ceuta, and Melilla.** If your business is in the Canary Islands, each line is declared with **IGIC** (category L of the European standard); in Ceuta or Melilla, with **IPSI** (category M), always with its rate, 0% included. Those territories are outside the EU VAT area, so your NIF travels as a tax registration and not as a VAT number, and a line cannot carry an exemption reason: remove it from the exempt profile and keep the rate. **IGIC at 0%** can be downloaded as XRechnung (UBL), Peppol, and Facturae, but not as Factur-X or XRechnung (CII): the official validator of that syntax requires a rate above zero. A [document discount or a coupon](/en/docs/cotizacion/descuentos) appears as it does on the PDF: each line with its amount before the discount and the discount subtracted in the totals, split by VAT category and rate, so the total matches the invoice to the cent. In the Facturae, each line carries its share of the discount. ## Facturae (Spain) If your business is in Spain, every invoice in euros issued with Verifactu is also downloadable as **Facturae 3.2.2**, from the invoice detail and from its public link; a pro forma has no electronic version. It comes from the same issued invoice, with the same amounts: - **IRPF** as a withholding (not as a discount: the invoice base and total do not change); - **VAT**, **IGIC**, or **IPSI** with its rate, and exempt or non-taxable supplies with their reason; - **reverse charge** with its legal wording; - a **credit note** as a corrective invoice by differences, with the invoice it corrects. 1. To **sign it**, upload your electronic certificate in **Settings › Tax profile › Verifactu**. 2. In the **European e-invoicing** section, turn on **Sign the Facturae with my electronic certificate**. The signature is made in your name, so it only applies if you turn it on. Without a signature, the Facturae is downloaded as an unsigned XML and the invoice detail says so: it works for your client, but **to submit it to FACe it must be signed**. FACe, the Spanish public sector's invoice entry point, also requires the DIR3 codes of the public body, which Cord does not collect yet. Cord does not submit invoices to FACe. ## E-invoicing between businesses in Spain Spanish law requires businesses and professionals to issue and receive e-invoices when the client is another business or professional established in Spain (Law 18/2022 and Royal Decree 238/2026). Order HAC/1028/2026 started the clock on 6 October 2026: - **6 October 2027:** businesses invoicing more than 8 million euros a year. - **6 October 2028:** all other businesses and professionals. - **6 October 2029:** self-employed people invoicing up to 8 million euros start reporting payment of the invoices they receive. Cord will send each invoice to a client established in Spain through the **AEAT public e-invoicing solution**, which is free, and will tell it when you were paid. Only full payment is reported: a partial payment is not. If the invoice was already paid when you issued it, the invoice itself says so and your client does not have to report the payment. **Coming soon.** The AEAT has not yet published the technical specification of its service. Cord will turn sending on as soon as it does. Until then nothing is sent, and the invoice detail and **Settings › Tax profile** say so. Get ready now: 1. Upload your electronic certificate in **Settings › Tax profile › Verifactu**: it is the same one your business will use to identify itself to the AEAT. 2. On each Spanish client, enter their **NIF** and full address: street and number, town, postal code, and province. The AEAT does not accept the invoice without them. 3. Open an invoice issued to a client in Spain. The **E-invoice (AEAT)** section says whether it already has what the AEAT requires or what is missing. These will not go through the public solution: - invoices to clients outside Spain, which are outside the obligation; - invoices with **IRPF withholding**, until the AEAT publishes how its format declares them. Until then, download them as **Facturae**, one of the syntaxes the law accepts; - invoices from businesses in the Basque Country and Navarre, which depend on agreements with their regional tax authorities that have not been published yet; - credit notes for a simplified invoice. ## E-invoicing in France Since **1 September 2026** every business established in France must be able to **receive** e-invoices through an approved platform (PA), and large and mid-sized companies must also **issue** them and **report** their other transactions (e-reporting). Small and micro businesses issue and report from **1 September 2027**. Cord issues and reports for you, from the invoices you already issue: - an invoice to another business established in France (with a SIREN) travels as **Factur-X** through the platform, and Cord shows on the invoice each status the platform reports: submitted, received by your client's platform, approved, rejected…; - a sale to a **consumer** is reported in the daily summary, and an invoice to a **business in another country**, one by one; - if your VAT is due on payment (services without the option to pay VAT on debits), Cord reports **each payment** you record. **Coming soon.** Issuing through an approved platform is not active in Cord yet. Your invoices already carry the mentions the reform requires, and **Settings › Tax profile** and each invoice's detail say whether it has everything or what is missing. French invoices already carry the four new mentions: the **client's SIREN**, the **transaction category** (goods, services or both), the **option to pay VAT on debits** if you took it, and the **delivery address** when it is not the client's. 1. In **Settings › Tax profile**, fill in your **SIREN** (or your VAT number, which contains it) and, under **E-invoicing in France**, your **VAT regime**, whether you opted to pay VAT **on debits**, and whether lines typed by hand are **goods or services**. 2. In the catalog, choose each product's **type**: a product is a supply of goods; a service, subscription or license is a supply of services. 3. If you deliver somewhere other than the client's address, enter the **delivery address** in the invoice editor. 4. Once the feature is active, click **Register with the platform** and, on its page, verify your identity and sign the mandate. Cord only transmits what you issue after the registration is complete. Cord **only issues**. To receive your suppliers' invoices you need your own reception platform, mandatory since 1 September 2026; registering in Cord does not change it. ### Statuses of a transmitted invoice Each status the platform reports is kept on the invoice detail, with its date and reason, and in its history: | Code | Status | What to do | |---|---|---| | 200 | Submitted to the platform | Nothing: the invoice went out. | | 201 | Issued by the platform | Nothing. | | 202 | Received by the client's platform | Nothing. | | 203 | Made available to the client | Nothing. | | 204 | Acknowledged by the client | Nothing. | | 205 | Approved by the client | Nothing. | | 206 | Partially approved by the client | Talk to your client about the part that wasn't approved. | | 207 | Disputed by the client | Resolve the disagreement with your client. | | 208 | Suspended: the client asks for supporting documents | Send them the documents they ask for. | | 209 | Completed with supporting documents | Nothing. | | 210 | Refused by the client | Cancel it with a credit note and issue a new invoice. | | 211 | Payment sent | Nothing: your client reported that they paid. | | 212 | Payment received | Nothing: the payment was reported. | | 213 | Rejected by a platform | Cancel it with a credit note and issue a new invoice. | | 501 | File not accepted by the platform | Check the reason, cancel it, and issue a new invoice. | If your client or a platform **rejects** an invoice (210, 213, or 501), the invoice says so with the reason. It is not corrected: cancel it with a **credit note** (it is an accounting cancellation and is not transmitted) and issue a new invoice with the right data. ### What's reported about your sales and payments | Sale | How Cord reports it | Its payments | |---|---|---| | To a business established in France, with a SIREN | Transmits the invoice (Factur-X) through the platform. | If VAT is due on payment, each payment as status **212 Payment received**. | | To a business in another country, with a tax ID | Reports it one by one in the e-reporting. | In the payments e-reporting. | | To a consumer, French or not | The day's total, per currency and per type (goods, services, or transactions outside the scope of French VAT). | The day's collected amount. | - **Which payments are reported:** only those for **services**, when you didn't opt to pay VAT on debits. On a mixed invoice only the services part is sent, split by VAT rate. - **Refunds:** on a transmitted invoice, a refund is reported as a negative payment with its reason. In the payments e-reporting the platform doesn't accept negative amounts: Cord leaves it flagged so you can regularize it in the platform's console. - **Currency:** the payments e-reporting goes in euros, with the invoice's locked exchange rate. - **Deadlines:** Cord sends every day as soon as it closes. The platform groups what was sent into the period that matches your **VAT regime**: by ten-day periods in the monthly standard regime, by month in the quarterly and simplified ones, and every two months under the franchise. **Settings › Tax profile** counts what's overdue. ## Leitweg-ID The Leitweg-ID identifies a German public body and ends with **two check digits**. Cord checks them on any electronic address with scheme 0204 (yours or a client's) and on the buyer reference of a client with that address: on the client, in the invoice editor, and in the API. If they do not match, it is not saved and Cord says why; copy it again, complete, from the purchase order or the public body. A Leitweg-ID saved before this check is not changed on its own: the client page flags it as **Leitweg-ID to correct**, and their e-invoices are not generated until you fix it. ## When it cannot be generated Cord does not produce an e-invoice that differs from the real invoice. There is no electronic version for: - drafts, voided invoices, pro formas, and test documents; - in Factur-X, XRechnung, and Peppol, invoices with **withholdings** (for example Spanish IRPF): the European standard has no place to declare them, and subtracting them as a discount or prepayment would change the base or the amount due. In Spain, download it as **Facturae**; - an IGIC or IPSI line with an exemption reason; - a Leitweg-ID whose check digits do not match; - older invoices whose totals are not the exact sum of their lines; - a supply **not subject** to VAT mixed with lines of another category: issue them separately. ## Common problems - **"XRechnung requires the buyer reference":** enter it on the client or on the invoice before issuing it. - **"Peppol requires your participant identifier":** add your electronic address in **Settings › Tax profile** with a scheme other than email. - **"XRechnung requires payment instructions":** add your IBAN under **Manual bank transfer**, in **Settings › Payments › Payment methods**. - **"The Leitweg-ID check digits do not match":** copy it again, complete, from the purchase order or the public body, and correct it on the client. - **"Facturae requires the client's tax ID":** enter it on the client; the Facturae is not generated without it. - **"Each line must say whether it is goods or a service"** (France): choose the product's type or, for lines typed by hand, the option in **Settings › Tax profile**. An issued invoice keeps its lines: it applies to the next ones. ## Related - [Invoicing by country](/en/docs/pagos/facturacion) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Recurring invoices](/en/docs/pagos/facturas-recurrentes) --- # Invoicing by country URL: https://docs.cordhq.app/en/docs/pagos/facturacion Last updated: 2026-10-13 Which document Cord issues by country and plan: invoices with sales tax, VAT or GST/HST, CFDI 4.0 in Mexico, Verifactu in Spain, and quotas. ## What it is Cord doesn't treat an invoice as a generic PDF with a number. The **document type** issued depends on your business country, your plan, and the tax setup you have ready. Once issued, a document keeps its type even if you later change plan or setup: a proforma doesn't become a CFDI or vice versa. The type is chosen when you create the invoice, in step 3 of the editor (**Terms**), in the **Document type** field: **Pro forma** in Mexico and Spain or **Commercial invoice** (a standard invoice) in the other markets, plus **CFDI 4.0** or **VERI\*FACTU** when your plan and tax setup allow it. An option your account can't use yet appears disabled. Below it, the editor reminds you: "Commercial documents are included in Free. Integrated tax issuance requires Starter and an enabled tax setup. A pro forma does not replace a tax invoice." For the full life of an invoice (draft, issue, delivery, payment, credit notes, and voiding), see [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas). ## Which document is issued | Country | Free plan | Starter or higher | |---|---|---| | **Mexico** | Proforma (number with the `PRO` series) | **CFDI 4.0** stamped with the SAT, with your CSD uploaded. You can also choose a proforma. | | **Spain** | Proforma (`PRO` series) | Invoice registered with the AEAT through **Verifactu** (beta), with an electronic certificate uploaded. Without it, pro forma; see [Spain](#spain-verifactu). | | **Argentina, Brazil, Chile, Colombia, and Peru** | Standard invoice | Standard invoice. When issuing with the country's authority is active on your account, the authorized e-invoice (new feature; see [Other markets](#other-markets-standard-invoice)); the **Commercial invoice** option then becomes a proforma (`PRO` series). | | **United States, Canada, United Kingdom, Germany, and France** | Standard invoice | Standard invoice | - **Proforma:** a commercial document that explicitly states it doesn't replace a tax invoice. It's for collecting and for your customer to process payment, not for tax deductions. - **Standard invoice** (**Commercial invoice** in the editor): an invoice with a sequential number, per-line taxes (sales tax, VAT, or GST/HST) and withholdings, and both parties' tax details. Cord doesn't file it with any authority. In the United States, Canada, and the United Kingdom no authority receives each invoice, so this is your invoice. - **CFDI 4.0:** Mexico's digital tax receipt, stamped with the SAT using your business's certificate. - **Authorized invoice:** in Argentina, Brazil, Chile, Colombia, and Peru, the e-invoice authorized by the country's tax authority, with its legal number. In all three cases, tax is calculated **per line**: you can mix a taxed item with an exempt one, and each prints your country's tax name (IVA in Mexico and Spain, VAT in the United Kingdom, GST in Canada, Sales tax per state in the United States). In the United States, from the Starter plan, you can turn on sales tax **by the client's address** in **Settings › Taxes**: each line takes the combined state, county, city and special district rate for that address, and the document prints one row per jurisdiction. It needs your full business address, the states where you collect, and your payments account set up. In a state where you don't collect, the line carries 0 % and the document says so; mark an exempt client in its profile with its certificate. If something is missing (for example, the client's ZIP) or the calculation isn't available, the document isn't saved and tells you what's missing: it never uses an estimated rate. Each plan includes a number of invoices with automatic sales tax per month; see [Your Cord subscription](/en/docs/cuenta/suscripcion). If a document shows as a **Test document**, no tax provider issued it: it has no validity with the authority, the link warns your customer, and it can't be paid online. A test issue doesn't become valid by changing the setup. In Mexico it shows as **Not valid for tax purposes**, and the PDF and the link carry the mark “SIN VALIDEZ FISCAL” across the document. ## Invoice language The invoice takes its language when issued: the one your client has in their record or, if they have none, your account's (see [Document language](/en/docs/gestion/clientes#document-language)). That language stays with the invoice: its PDF, its link, the email, and the reminders use it even if you change the record later. An invoice created from a quote takes the language the client has when it is issued, not the quote's; a credit note, a debit note, or an invoice that replaces another takes its original invoice's language. An invoice issued before per-client language existed keeps its PDF in the language of your business's country. The language changes the text Cord writes, not what the law requires: - **France:** the invoice must be in French. With a client in another language, the PDF puts French first and the client's language alongside ("FACTURE / INVOICE"), with dates and numbers in French format. - **Legal notices:** the ones the law requires in its own language (reverse charge in Spain, France, and Germany, the VAT exemption for small businesses in France and Germany, France's business-to-business payment terms, and the Verifactu legend and QR code) stay in that language. - **Documents Cord doesn't draw:** the stamped CFDI PDF in Mexico comes out in Spanish, and the NF-e DANFE in Brazil, in Portuguese. In Argentina, Chile, Colombia, and Peru, the data the authority returns stays as it returns it. - **E-invoicing:** the XML files don't change with the client's language. Each country's PDF language is in [Invoicing by country](/en/docs/pagos/paises/resumen). ## Quotas per plan Invoices have their own monthly quotas, separate from quote sends: | Plan | Standard invoices and proformas per month | Tax documents (CFDI or Verifactu) included per month | |---|---|---| | Free | 10 | No tax issuing | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | - Beyond the included tax quota, from Starter up, additional documents are billed as usage overage on your subscription. See [Subscription](/en/docs/cuenta/suscripcion). - In Mexico, each **payment complement** Cord stamps counts as one more tax document. - On Free, after 10 standard invoices and proformas in a month, issuing stops until the next month or until you change plans. - Drafts and test documents don't consume quota. - Running out of quota or downgrading does **not** block downloading, sending, or collecting documents already issued. Subscribing to a plan doesn't turn on tax issuing by itself: in Mexico you also need your CSD uploaded, and in Spain, your electronic certificate. ## Mexico: CFDI 4.0 With Starter or higher, Cord stamps with the SAT through a certified provider, **under your business's RFC and Digital Seal Certificate (CSD)**. You upload the CSD once in **Settings › Tax details** and never attach it again. See [Digital Seal Certificate](/en/docs/cuenta/csd). ### Recipient details Cord takes the recipient's tax details from the customer record: | Item | Source | If missing | |---|---|---| | RFC | Customer record | Issued with the generic RFC XAXX010101000, in the customer's name and with your business's tax postal code. The name "PUBLICO EN GENERAL" is reserved for the global invoice. | | Tax regime | Customer record | 601 (General corporate regime) if the customer has an RFC; 616 (No tax obligations) whenever it is issued with the generic RFC. | | CFDI use | Customer record, or your account's default use | G03 (General expenses). | | Tax postal code | Customer record | There's no value that can safely replace it: CFDI 4.0 requires the postal code on the recipient's tax certificate, and stamping may be rejected. | The defaults may not match your customer's tax certificate (constancia de situación fiscal). Cord doesn't invent them from other data: complete them in the record before issuing so the CFDI is useful to whoever receives it. ### Customers abroad If the customer's country in their record isn't Mexico, the CFDI is issued to a **foreign resident**: with the SAT generic foreign RFC (XEXX010101000), their **tax residence** (the country in the record), use **S01** and, if you entered their tax ID (EIN, NIF, VAT…), that number as the **foreign tax registration number**. The tax regime and CFDI use in the record don't apply to a foreign customer and aren't sent. The VAT rate on each item is your call with your accountant; for example, exported services usually go at 0%. ### SAT keys for each item Each product can carry its **product or service key** (c_ClaveProdServ, 8 digits) and its **unit key** (c_ClaveUnidad) under **Products › E-invoicing (SAT)**. You search the product key by description in the SAT catalog; if you leave the unit key empty, it's derived from the product's unit ("hour" → HUR, "month" → MON, "kg" → KGM). In the quote and invoice editors, each item can carry **its own keys**, which win over the product's; duplicating a document keeps them. Items with no keys of their own and no classified product are stamped with the SAT generic keys: 01010101 and H87, and the editor tells you how many are left that way before issuing. Keys are read when stamping and saved in the document. ### Taxes and issuing Cord sends each item's taxes as you entered them: 16% IVA, 8% IVA, or exempt, plus IVA and ISR withholdings. It doesn't collapse them into a single rate. If the quote is in a currency different from your accounting currency, the CFDI declares the exchange rate locked at quoting time. A [document discount](/en/docs/cotizacion/descuentos) travels spread per item in the **Descuento** attribute. In the invoice editor, the **CFDI details** section lets you set that invoice's **CFDI use** (by default, **From the client's record**) and **Payment method** (by default, **Automatic from the payments**). If you replace the invoice, the replacement inherits them. A confirmed payment and an issued invoice are different states. Paying doesn't create, stamp, or send an invoice by itself; check each document's tax and delivery status. If stamping succeeds and the email fails, the number is kept and you can resend from the detail page. Credit notes for a Mexican invoice are an expense CFDI (egreso) related to the original UUID. A cancellation request doesn't void the CFDI until the SAT confirms it; meanwhile you can click **Check cancellation status** on the detail page. ### Payment method: PUE or PPD This feature is new and may not be enabled on your account yet. If you don't see it, write to us. When stamping, Cord sets the CFDI's **payment method** from what actually happened with the money: | Situation when stamping | Method | Payment form | |---|---|---| | The invoice is already **fully paid** (on its link, on the source quote, or with payments you recorded) | **PUE**, single payment | The payment's: 04 card, 03 transfer (including SPEI), 01 cash, 02 check. If you set one under **CFDI details**, that one. | | The invoice will be collected **later**, in full or in installments (for example, Net 30) | **PPD**, installments or deferred | 99, to be defined | | The recipient is the **general public** (generic RFC XAXX010101000) | Always **PUE**: that recipient doesn't accept payment complements | The payment's, or 03 if there's none yet | Cord used to stamp everything as PUE even when the invoice was on credit. Not anymore: an invoice that isn't paid when issued goes out as PPD, as the SAT requires. ### Automatic payment complement For each payment a **PPD** invoice receives, the SAT requires a **payment receipt complement** (type P CFDI, also called REP) no later than the 5th of the following month. Cord stamps it **by itself**, as soon as the payment is recorded: - **However the payment is recorded:** a card, SPEI, or Mercado Pago payment on the invoice link (SPEI is recorded only when the full transfer arrives), a payment from the [client portal](/en/docs/pagos/portal-facturas) or [automatic payments](/en/docs/pagos/cobro-automatico), a payment you record by hand, or the source quote's payments applied to the invoice. - **One complement per payment.** Each payment gets its own, related to the invoice's UUID and with its installment number and previous balance. A retry never stamps the same payment twice. - **Complement payment form:** the payment's (04 card, 03 transfer, including SPEI on the invoice or the quote, 01 cash, 02 check); if it can't be known, 03. - **It uses your tax quota:** each complement counts as one tax document for the month. - **It's recorded in the invoice history:** "Payment complement issued" with its tax folio (UUID). If it couldn't be stamped, the history says "Payment complement pending" with the reason. Cord does **not** issue it by itself, and says so in the invoice history, in two cases the SAT documents differently: | Case | What to do | |---|---| | The payment is in **a currency other than MXN**. | The complement needs the official exchange rate for the payment date, which Cord doesn't have. Issue it with your accountant. | | The payment is **earlier than the invoice** (an advance). | It's documented with the SAT's advance-payment procedure, not with a payment complement. | **If a complement doesn't go out** (because of an error, because the payment is in another currency or because an attempt got stuck), Cord creates a high-priority task linked to the invoice, due two days before the 5th of the month after the payment, and closes it on its own once the complement is issued. An advance payment doesn't create a task. Today Cord doesn't send the complement to your client or offer it for download from the invoice detail, and a complement that's left pending isn't retried on its own. If your client needs a complement's XML or PDF, or one is pending, write to us. ### Cancellation and replacement When you void an issued CFDI, Cord asks for the **SAT reason**: 02 (with errors, without a replacement), 03 (the transaction did not take place) or 04 (named transaction in a global invoice, only on the global invoice). Reason 01 is used through **Replace CFDI**: Cord creates a draft with the original's data, relates it to the original when you issue it (relationship 04), moves the original's payments to it and requests the original's cancellation under reason 01 with the replacement's UUID. An invoice with valid credit notes or issued payment complements can't be replaced: the SAT doesn't allow cancelling a CFDI with valid related documents. The SAT only allows cancelling a CFDI until the month of the annual return for the year it was issued: March of the following year if the issuer's RFC belongs to a legal entity and April if it belongs to an individual. Within that period, the void dialog tells you until when you can cancel it; after it, Cord no longer offers to void or replace it, and you correct it with a credit note. ### Global invoice Sales collected without the customer asking for an invoice are documented under **Invoices › Global invoice**: you choose the frequency, month and year, Cord lists the quotes collected in the period with no invoice of their own and no other global invoice, and issues a CFDI to PUBLICO EN GENERAL (XAXX010101000, regime 616, use S01, PUE) with one item per sale (key 01010101, unit ACT and the quote number as identification number). A sale in a valid global invoice can't be invoiced separately; if the customer asks for their invoice, the global invoice is cancelled under reason 04 and issued again without that sale. ### What Cord doesn't do in Mexico today - **Payment complement for a payment in another currency or an advance.** See [Automatic payment complement](#automatic-payment-complement). - **Foreign trade complement (Comercio Exterior).** Definitive export of goods (key A1) requires it and Cord doesn't issue it. That's why, if a CFDI has goods items (SAT keys for goods) for a client with an address outside Mexico, Cord stops before stamping and asks you to confirm it isn't an export, for example because the goods are delivered in Mexico; the CFDI and its history keep that confirmation. If it is an export, issue that CFDI with your accountant. Through the API you confirm with `sin_comercio_exterior: true` when issuing; a recurring invoice or a workflow can't confirm it and stops. ## Spain: Verifactu Verifactu is the invoicing system required by Spanish law: each invoice generates a record chained to the previous one and sent to the Spanish Tax Agency. ### What Cord does today - **It registers every invoice.** With Starter or higher and your electronic certificate uploaded, each invoice is registered with the Tax Agency through Verifactu. This feature is in beta. - **Without Verifactu, everything goes out as a pro forma invoice.** Without a certificate, on the Free plan or with registration not active, the document goes out as a **pro forma invoice** with the `PRO` series: its PDF is titled “FACTURA PROFORMA” and says it isn't an invoice, it carries no fingerprint or verification QR, and it isn't registered with the Tax Agency. The law requires the system used to invoice in Spain to register every invoice (Royal Decree 1007/2023), so Cord doesn't issue invoices in Spain outside Verifactu. A pro forma invoice doesn't allow credit notes or e-invoices. - **It doesn't fake tax issuing.** If you explicitly request a tax invoice without Verifactu ready, Cord rejects it and tells you how to turn it on, instead of issuing a document that pretends to have a record. The law makes it mandatory from January 1, 2027 for businesses that pay Corporate Income Tax, and from July 1, 2027 for everyone else (Royal Decree-law 15/2025). ### How to turn it on In **Settings › Tax profile**, **Verifactu** section (Spain accounts only), upload your **electronic certificate** (`.p12` or `.pfx`) with its password. Cord validates the password, reads the expiry date, and stores the certificate encrypted; from then on the section says **Verifactu active**. Also make sure your NIF is in your tax details. ### What each registered invoice carries With Starter or higher and a valid certificate: - Each invoice generates a **chained record** with a digital fingerprint that links it to your business's previous invoice. - The PDF carries the Tax Agency's **verification QR code** at the top, with the legend "Factura verificable en la sede electrónica de la AEAT" below it. - The record is sent to the Tax Agency after issuing. Issuing doesn't wait for that response: the submission status (accepted, rejected…) shows on the invoice detail, and a rejected one is corrected from there with **Correct and resend**. - A registered invoice isn't edited: it's corrected with a new correction or cancellation record. Full details in [Spain](/en/docs/pagos/paises/espana). ## Other markets: standard invoice In the United States, Canada, Brazil, the United Kingdom, Germany, France, Colombia, Argentina, Chile, and Peru, Cord issues a **standard invoice** with a sequential number per organization, per-line taxes and withholdings, and both parties' tax details. Cord doesn't file it with the local tax authority. Whether you must issue, report, or complement that document depends on your country and regime; confirm with your tax advisor. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. - **Argentina, Brazil, Chile, Colombia, and Peru.** Cord can issue the e-invoice **authorized by each country's tax authority** (ARCA in Argentina; NFS-e and NF-e in Brazil; SII in Chile; DIAN in Colombia; SUNAT in Peru), with Starter or higher and your business's credentials in **Settings › Tax profile**. When issuing is active on your account, the invoice carries the legal number the authority assigns and the **Commercial invoice** option goes out as a proforma. Until then, you keep issuing standard invoices. - **Germany, France, and Spain.** Each invoice can also be downloaded as a European e-invoice (Factur-X, XRechnung, Peppol, and, in Spain, Facturae). In France, issuing through an approved platform is built and coming soon. See [European e-invoicing](/en/docs/pagos/factura-electronica). ## The tax receipt for Cord's fee (Mexico) Besides the CFDIs you issue to your customers, in Mexico Cord issues its **own income CFDI** for the fee it charges on your MXN Cord Payments payments (see [Fees](/en/docs/pagos/condiciones)). It's the receipt for the processing service Cord provides you, not for your sale. - **It's monthly and consolidated:** one CFDI per month with the sum of that month's fees, not one per payment. - **Cord reviews it before stamping:** at the start of each month the previous month's draft is prepared and recipient, base, IVA, and total are checked before issuing. - **It's issued to your tax details:** RFC, tax regime, and postal code from **Settings › Tax details**, with your account's CFDI use or G03 if there's none, and the PUE payment method. - **Mexico only.** Outside Mexico, the payment receipt is your document. The CFDI for your Cord **subscription** is requested separately, from your subscription billing, for each payment already settled. See [Subscription](/en/docs/cuenta/suscripcion). If your RFC, tax regime, or postal code aren't complete in **Settings › Tax details**, the fee CFDI can't be issued. If you didn't receive it or need a month's XML and PDF, write to us. ## Limits - CFDI: Mexico only, from Starter, with a CSD uploaded. - Spain: invoice registered with Verifactu (beta) from Starter, with a certificate uploaded; without it, pro forma. - Argentina, Brazil, Chile, Colombia, and Peru: authorized invoice only when its issuing is active on your account; otherwise, standard invoice. - Other markets: standard invoice not filed with the authority. - Free: 10 standard invoices and proformas per month and no tax issuing. - Mexico: the payment complement is automatic for MXN payments after the invoice; payments in another currency and advances are documented outside Cord. ## Common problems **My invoice came out as a proforma and I expected a CFDI.** Check your plan (Starter or higher), that your CSD is uploaded and valid, and that **CFDI 4.0**, not **Pro forma**, is selected in **Document type** (step 3, **Terms**). **My CFDI came out PPD and I expected PUE.** When it was stamped, the invoice wasn't fully paid. Cord will issue a payment complement for each payment it receives. If the invoice was already paid, check that the payment was recorded before issuing it. **My customer says their CFDI is unusable.** Check their tax regime, postal code, and CFDI use in their record; if they were missing, Cord used defaults. **I'm in Spain and uploaded my certificate, but I still issue pro formas.** Check your plan (Starter or higher), that **Settings › Tax profile** says **Verifactu active**, and that **VERI\*FACTU**, not **Pro forma**, is selected in **Document type**. **I hit the document limit on Free.** Issuing resumes next month or when you change plans. Your issued documents remain available. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen): one page for each of the 12 markets - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Recurring invoices](/en/docs/pagos/facturas-recurrentes) - [Digital Seal Certificate](/en/docs/cuenta/csd) - [Stamping from the quote](/en/docs/cotizacion/timbrado) - [Discounts and coupons](/en/docs/cotizacion/descuentos) - [European e-invoicing](/en/docs/pagos/factura-electronica) - [Subscription](/en/docs/cuenta/suscripcion) --- # Create, issue, and collect invoices URL: https://docs.cordhq.app/en/docs/pagos/facturas-emitidas Last updated: 2026-10-13 Create an invoice, assign its number when issuing, deliver it, and track its balance in Cord. ## Where to find invoices Open **Revenue › Invoices**. The inbox shows the invoice number, client, creation date, due date, total, balance, and operational status. Drafts do not have an official number yet. Cord labels them **No number** and adds a temporary `BOR-...` reference so you can recognize them. The sequential number is reserved only when you issue the invoice. Opening a draft from the inbox takes you straight to the editor. ## Create an invoice **New invoice** opens the same editor as quotes (see [Quote creation overview](/en/docs/cotizacion/resumen)), with invoice wording and its own step 3. 1. **Build with AI (optional).** The **Build the invoice with AI** block takes the order as text, a photo, or a PDF and fills the line items from your catalog (see [Cord AI](/en/docs/cotizacion/ia)). 2. **Who are you invoicing?** Search the client by name, contact, email, or tax ID, or choose **+ Create new client…**. Cord reads their email, payment terms, and tax details from their record. Terms are chosen with chips (Due on receipt, Net 15, Net 30, Net 60, or **Other term**: Net 7, Net 45, or Net 90) and recalculate the due date. 3. **What are you charging for?** Add catalog products, kits, or a free line. Each item carries its quantity, its price, and its own tax rate. You can duplicate, reorder, and remove lines with **Undo**, just like in a quote (see [Products and discounts](/en/docs/cotizacion/productos)). 4. **Terms.** Set the **Due date** (a date; changing the payment terms recalculates it, and you can pick another by hand), the **Document type**, and the **Invoice currency**. The document type offers **Pro forma** in Mexico and Spain or **Commercial invoice** in the other markets, plus **CFDI 4.0** (Mexico) or **VERI\*FACTU** (Spain) when your plan and tax setup allow it. In Argentina, Brazil, Chile, Colombia, and Peru, once issuing with the country's authority is active on your account, the fiscal option is its authorized e-invoice and the commercial option becomes a pro forma (see [Fiscal invoicing by country](/en/docs/pagos/facturacion)). If the currency differs from your business's, the exchange-rate panel appears: "The rate is stated on the invoice." When it applies, the invoice also carries: - **CFDI details** (Mexico): that invoice's **CFDI use** and **Payment method**. See [PUE or PPD](/en/docs/pagos/facturacion#payment-method-pue-or-ppd). - **Date of supply** and **End of period**: only if the sale or service happened on a date other than the issue date. It's required in Germany; if empty, the invoice says it matches the issue date. - **Buyer reference** and **Purchase order** (optional): printed on the invoice and carried by its [e-invoice](/en/docs/pagos/factura-electronica). If you leave the reference empty, the client's is used. - **Delivery address** (France): only if the goods are delivered somewhere other than the client's address. 5. **Note for your client** (optional). It's shown on the PDF and on the invoice page. 6. **Review and issue.** The summary shows subtotal, taxes per rate, withholdings, the **Total** and, below it, the terms and due date (for example "Net 30 · due Nov 7"). If it applies, add a **discount or coupon** with **+ Add discount or coupon** (see [Discounts and coupons](/en/docs/cotizacion/descuentos)). The **Delivery** block shows the email it will go to: "The email includes the PDF and the payment link." Click **Preview** to see the approximate sheet your client will receive. 7. **Issue.** **Issue and send** assigns the number and emails the invoice in the same flow; **Issue without sending** issues it and leaves delivery for later; **Save and exit** saves the draft without issuing. Before issuing, Cord opens a **Final review** ("Issue this invoice?") with the client, total, due date, and delivery; confirm with **Issue and send** or **Issue invoice**, or go back with **Go back**. Each line item is rounded on its own and the total is the sum of the already-rounded lines, so the invoice total matches the sum of its rows. ### Draft saving and shortcuts - **A draft that's already saved saves itself** a few seconds after your last change (the summary says "Saved at …"). A new invoice is created as a draft the first time you click **Save and exit** or issue; until then, your browser keeps a local copy that Cord offers to **Restore** if you close without saving (it expires after 7 days). - On desktop, **⌘ Enter** (Ctrl Enter) opens the final review to issue and send, **⌘ S** (Ctrl S) saves the draft and exits, and **/** jumps to the catalog search. On a phone, a bar pinned to the bottom shows the **Total** and **Issue and send**. - **Issue and send** needs the client to have an email. If they don't, Cord tells you ("This client has no email. Add one to their record or choose "Issue without sending"."). - If an issuance failed with certainty, **Fix and retry** on the detail opens the same editor as **Fix** with the reserved number: you correct it and issue again keeping that number. Issuing is irreversible: it assigns the official number and locks the fiscal document. To correct an issued invoice, use a void or credit note according to its payment state. ## What your client receives The email goes out in the invoice's language, which the invoice takes when issued: the one your client has in their record or, if they have none, your account's (see [Document language](/en/docs/gestion/clientes#document-language)). It includes the PDF and the public invoice link. From that page, the client can review the balance and payment history; if your payments account is enabled, they can also pay by card, and with [Mercado Pago](/en/docs/pagos/mercado-pago) if you connected it. In Mexico, on MXN invoices with SPEI turned on, they can also pay by SPEI transfer to that invoice's CLABE, which reconciles on its own; it's a new feature (see [SPEI on the invoice link](/en/docs/pagos/metodos#spei-on-the-invoice-link)). In Spain, Germany, France, the United Kingdom, and the United States, on invoices in EUR, GBP, or USD with a linked client, they can pay by [bank transfer with a reference](/en/docs/pagos/transferencia-referencia), which also reconciles on its own; it's a new feature. They can pay the full balance or choose **Pay another amount** to pay part of it. If you turned on [bank debit](/en/docs/pagos/domiciliacion), on invoices in EUR (SEPA), USD (ACH), GBP (Bacs), or CAD (pre-authorized debit) they can also pay with a debit from their account. Besides each invoice's link, you can give your client their [portal](/en/docs/pagos/portal-facturas), with all their invoices and paying several in a single charge. If they turned on [automatic payments](/en/docs/pagos/cobro-automatico), each invoice's email tells them on which day and to which method it will be charged. The public page presents your business brand, invoice number, balance, parties, line items, and downloads in one view. If the document was created in test mode or without fiscal issuance, Cord displays a clear warning and disables online payment. If issuance succeeds but email delivery fails, Cord keeps the issued invoice and marks only delivery as pending. Open the invoice detail and use **Send invoice** again without generating another number. ## Inbox statuses - **Draft**: editable and without an official number. - **Open**: issued with a remaining balance. - **Overdue**: open and past its due date. - **Paid**: fully settled. - **Issue error**: the fiscal provider did not confirm issuance; open the detail and use **Retry issuing**. - **Void** or **Uncollectible**: no longer in the normal collection flow. The primary badge always represents financial status. Cord shows delivery and environment context separately underneath it, for example **Sent · Test**. This keeps **Test** from replacing or contradicting states such as **Open** or **Paid**. ## Actions from the invoice detail You can resend the email, record manual or partial payments, copy the public link, download PDF and XML when available, void, create a credit note, use **Duplicate invoice** to open a new copy in the editor, or start a monthly recurrence with **Repeat monthly**. In Mexico, **Replace CFDI** also corrects an issued CFDI under SAT reason 01, and the history records the **payment complement** for each payment on a PPD invoice (see [Invoicing by country](/en/docs/pagos/facturacion#automatic-payment-complement)). The progress bar separates five moments: **Draft**, **Issued**, **Sent**, **Viewed**, and **Paid**. The action column provides direct access to open or copy the client link, download the PDF, and share through WhatsApp. Exceptional actions, such as voiding or marking an invoice uncollectible, stay under **More actions**. After the first delivery, the inbox shows **Sent** and removes that invoice from bulk selection. Resending remains available in the invoice detail next to the recipient's email, which helps prevent accidental duplicate delivery. **Test document** means there was no valid fiscal issuance. In Mexico, it is not a CFDI before the SAT. Configure fiscal issuance and create a new invoice; Cord preserves the previous document without rewriting its history. The **Activity** section records issuance, delivery, views, reminders, payments, and status changes, so you can understand what happened without relying on the seller's inbox. ## Bulk delivery and export Select issued invoices that have not been sent yet to deliver them in a batch. Drafts, previously sent invoices, and non-deliverable documents keep a visible but disabled checkbox; hovering it explains why the invoice is excluded from that delivery. **Export CSV** downloads the current view and respects the active status filter and search. To repeat issuance, open **View recurring** and see [Recurring invoices](/en/docs/pagos/facturas-recurrentes). To review the available document —CFDI 4.0 in Mexico, a commercial invoice in other markets, and Verifactu's operating conditions in Spain—, see [Fiscal invoicing by country](/en/docs/pagos/facturacion). ## Payments, credits and refunds are different Cord keeps payments, issued credit notes and confirmed refunds separate. This helps prevent counting the same movement twice and explains balance changes. **Amount due = total − issued credits − recorded payments + confirmed refunds**, with a minimum of zero. A draft credit note does not reduce the balance. A pending or failed refund does not count as money returned. | Example in MXN | Result | | --- | --- | | 1,000 invoice; 400 payment | 600 remains due | | 1,000 invoice; 200 issued credit; 800 payment | Zero balance | | Paid 1,000 invoice; 200 issued credit | Zero balance and 200 to return | | Same case, with a confirmed 200 refund | Zero balance and nothing to return | | Paid 1,000 invoice; 200 refund without a credit | 200 becomes due again | The last case requires reviewing the agreement with the customer. Returning money does not itself reduce the document amount. Issuing a credit does not send money. ### Refunding a payment An online payment that came in through the invoice link, the client portal or automatic payments —by card, bank debit (SEPA, ACH, Bacs or pre-authorized debit), bank transfer (SPEI or with a reference) or Mercado Pago— is refunded from the **Payments** section of the detail page, with the **Refund** button, fully or partially depending on the method. You need the **Refunds** permission and to confirm your identity again. Before you confirm, the dialog says how much can be returned and, when it can't, why (an ACH debit can only be returned in full, for example). A manually recorded payment has no such button: Cord did not move that money. In Mexico, the refund doesn't cancel the CFDI; document the return with a credit note. All the details, including the allocation of a charge that paid several invoices, are in [Refunds](/en/docs/pagos/reembolsos#refunding-an-invoice-payment). ## Partial payments and confirmation After a partial payment is applied, a new payment is prepared for the current balance. An attempt still in progress must be resolved before opening another. A repeated notification for the same payment must not add the amount again. After returning from payment, use **Refresh balance**. Returning to the link is not confirmation: status depends on the payment record. If the bank shows a charge but the balance has not changed, contact the business before paying again. ## When the balance does not match Open the invoice detail and compare payments, issued credits, confirmed refunds and activity. Check currency and the relevant document. If a movement is pending, wait for confirmation or request a review; do not add another manual payment to force the balance to zero. Cord does not silently recalculate older documents. If an older invoice does not match, review it individually. Commercial documents are included in Free (10 per month); integrated fiscal issuance starts at Starter where enabled. The commercial option in Mexico and Spain is a pro forma, not a test invoice. It has no fiscal XML and does not replace a tax invoice. --- # Recurring invoices URL: https://docs.cordhq.app/en/docs/pagos/facturas-recurrentes Last updated: 2026-10-13 How to repeat an invoice every month, what data is frozen, how each document is issued, and what happens when it pauses, fails, or is deleted. A **recurring invoice** schedules new documents. It isn't the same as a **recurring retainer payment**: one repeats document issuance; the other creates a client-authorized monthly payment subscription. Creating an invoice recurrence doesn't currently store or automatically charge a payment method. Every new invoice enters collections according to its due date and recorded payments. ## Create one from an existing invoice Open an issued invoice, choose **Repeat monthly** under **More actions**, and Cord creates the recurrence and takes you to **Invoices › View recurring**. The recurrence the app creates is **monthly**: it issues on the 1st of each month, due on the issue date (0 credit days). Its internal name is the client's name or, if there isn't one, the base invoice's number. The app doesn't currently let you change the cadence, day, credit days, or an end date afterwards; from the list you can pause, resume, or delete it. Cord copies the client, currency, notes, and line snapshot from the issued document. It doesn't reread current catalog prices, so later Product edits don't silently alter the schedule. ## Calendar and due date - Cadence: monthly. - Day of month: the 1st. The issue day never goes past the 28th, so February is never skipped. - Credit days: 0; each invoice is due on its issue date. - First issue: Cord calculates the next period from the cadence and day. - End date: none; the recurrence stays active until you pause or delete it. A daily process selects active, due recurrences. Sandbox organizations don't issue recurring documents. ## What each run does Cord first advances the next scheduled date, creates a new draft from frozen lines, calculates its due date, issues through the country's appropriate document rail, and attempts email delivery in the invoice's language (the one on the client's profile or, if it has none, your account's). Every issue receives its own number and immutable snapshot. The date advances even when issuance fails. This prevents automatic duplicate invoices. The list exposes **Last error** so the cause can be corrected; don't assume it retries the same period every hour. ## Manage the list Open **Invoices > View recurring**. Pause stops future issues without deleting setup. Resume enables it again when the plan allows. Delete removes the schedule but preserves every issued invoice. Pausing remains available after a downgrade. Creating, resuming, and each scheduled run validate Pro-or-higher access. ## Email failure An issued invoice remains valid even if email fails. Open it from Invoices and resend; don't create another recurrence merely to replace delivery. ## Common problems **Option is missing.** Check Collections permission, Pro-or-higher plan, and that the base invoice was issued. **New catalog price isn't reflected.** The recurrence keeps copied lines. Create a new schedule from an updated invoice for future terms. **Next date moved after an error.** This is duplicate protection. Correct the error and decide whether that period needs a manual invoice. ## Scheduled-period protection Cord checks that the recurrence is still active and retains the date and settings read before claiming the period. This prevents two runs from claiming the same issuance or overlooking a concurrent edit or pause. The next date is calculated from the scheduled period and respects the end date. Invalid dates and an end before the start are rejected. Creating a recurrence does not add automatic charging. If issuance fails, review **Last error** and the document before repeating it; automatic recovery of every failed period is not implemented. --- # Monthly retainers URL: https://docs.cordhq.app/en/docs/pagos/igualas Last updated: 2026-10-11 Turn your quotes into automatic monthly subscriptions where the client authorizes their card only once. ## Goodbye to the hassle of collecting every month If you are a marketing agency, a consulting firm, or you sell a service on a "Retainer" basis, you know how painful it is to have to send a payment link or a manual invoice to your client every 1st of the month and chase them down to pay it. Cord Payments solves this by turning your quote into a **real subscription**, natively integrated with your bank account. ### How to enable a monthly retainer? For the recurring model to work, it is strictly required that you have Cord Payments connected (see [Connect your account](/en/docs/pagos/onboarding)) and the **Credit/debit card method enabled**. *(Note: automatic monthly billing cannot work with SPEI or with bank transfer with a reference, because the client initiates a transfer from their bank every month).* 1. Open your quote editor and, in step 1, **Who are you quoting?**, leave the term on **Due on receipt**: with a credit term the retainer switch doesn't appear. 2. In step 3, **Terms**, turn on the **Monthly recurring charge (retainer)** switch. 3. Turning it on hides the **Deposit (%)** field, because a recurring charge is a fixed fee, and a note shows you the amount that will be charged every month. ## The client experience When you send the quote link, the client will read their proposal normally, but they will notice the approval button is different: 1. The button will say **"Authorize monthly charge"**, next to the monthly amount and its currency (for example, $12,000.00 MXN). On the payment screen, the final button shows that same amount per month. 2. Upon clicking, the client will securely enter their credit or debit card. 3. The system will make the **first charge immediately** to activate the retainer, marking the quote as Approved. 4. Cord Payments handles **tokenizing the card** and charging that exact amount automatically every month, sending the funds straight to your bank account. You never store card data — the system handles tokenization and automatic retries if the client's card fails one month due to insufficient funds. If a monthly charge fails, you'll see it flagged in the "Active retainers" widget on the [payments dashboard](/en/docs/pagos/dashboard). Every monthly charge pays the same total fee as a normal card payment — there's no volume discount for recurring charges. That total fee (4% + $3.00 MXN + VAT, which includes card processing) is the current rate for retainers charged in Mexican pesos (MXN). On a retainer in another currency, Cord applies no platform fee today; **Settings › Payments › Fees** shows this in your account's currency. See the details in [Fees and advantages](/en/docs/pagos/condiciones). ## Cancellation Unlike traditional quotes (which switch to a "Paid" status once fully paid), a recurring retainer **is never marked as fully paid**, because it is continuous. In your dashboard, inside the details of that quote, you will see a status card indicating that the subscription is "Active". When you decide to end the business relationship with the client, simply press the red **"Cancel retainer"** button. This will instantly stop all automatic charges for the following months. --- # What's new in payments and invoicing URL: https://docs.cordhq.app/en/docs/pagos/mejoras-confiabilidad Last updated: 2026-10-11 Recent changes to how you collect, invoice, and receive your money in Cord, and where to find them. ## Summary | What's new | What changes for your business | Guide | | --- | --- | --- | | Discounts and coupons | A discount on the subtotal by percentage or amount, and coupons with a code, validity dates, and a usage cap, on quotes, invoices, and the API | [Discounts and coupons](/en/docs/cotizacion/descuentos) | | Invoice portal | One link per client with all their invoices, their balance per currency, and paying several in a single charge | [Invoice portal](/en/docs/pagos/portal-facturas) | | Automatic payments | Your client saves a method and Cord charges each invoice on its due date, with retries and notices | [Automatic payments](/en/docs/pagos/cobro-automatico) | | Bank debit | On invoices in euros (SEPA: Spain, Germany, and France), US dollars (ACH: United States), pounds (Bacs: United Kingdom), or Canadian dollars (pre-authorized debit: Canada), your client pays by debit from their bank account | [Bank debit](/en/docs/pagos/domiciliacion) | | Bank transfer with a reference | In EUR, GBP, or USD, your client pays by transfer to an account of their own with a reference per payment, and Cord reconciles it on its own | [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) | | Refunding a grouped charge | When you refund a charge that paid several invoices, Cord splits the refund among them and reopens their balance | [Refunds](/en/docs/pagos/reembolsos) | | Mexico: PUE or PPD and payment complement | The CFDI picks its payment method from what's already collected and, if it's PPD, each payment generates its automatic complement; plus the global invoice and CFDI replacement | [Invoicing and CFDI](/en/docs/pagos/facturacion) | | US sales tax by address | The combined rate for each address, with a monthly quota per plan and overage | [Subscription](/en/docs/cuenta/suscripcion) | | Partial invoice payments | Your customer can pay part of the balance, and the next payment is calculated on what remains | [Invoices](/en/docs/pagos/facturas-emitidas) | | Credit notes | Reduce the amount of an issued invoice without voiding it; in Mexico it is stamped as a related expense CFDI | [Invoices](/en/docs/pagos/facturas-emitidas) | | Downloads on the invoice link | Your customer downloads the PDF and, in Mexico, the XML from the same page where they pay | [Invoices](/en/docs/pagos/facturas-emitidas) | | Commercial invoices on Free | The Free plan includes 10 commercial invoices per month; from Starter they are unlimited | [Invoicing by country](/en/docs/pagos/facturacion) | | Subscription prices in euros | In Spain, Germany, and France, self-service plans are purchased at fixed EUR prices | [Subscription](/en/docs/cuenta/suscripcion) | | Mercado Pago | A second online payment rail, with your own account, on quotes and invoices | [Mercado Pago](/en/docs/pagos/mercado-pago) | | Safe switching between bank transfer and card | Switching methods can't create a duplicate charge when money has already been received or is in progress | [Payment methods](/en/docs/pagos/metodos) | | Payout frequency | You choose how often your money goes out to your bank | [Payouts to your bank](/en/docs/pagos/depositos) | ## Partial invoice payments On an invoice link, your customer can pay the full balance or choose **Pay another amount** and type how much they want to pay. Cord caps that amount at the invoice's real balance. After a partial payment, the next payment is prepared for the current balance, not the original total, and a repeated notice for the same payment is not added twice. ## Credit notes and the invoice balance From the detail of an issued invoice you can issue a credit note. In Mexico it is stamped as an expense CFDI related to the original invoice's fiscal folio. Cord keeps payments, issued credit notes, and confirmed refunds separate, and calculates the balance as: **total − issued credits − recorded payments + confirmed refunds**, with a minimum of zero. Details and examples are in [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas). ## Downloads from the invoice link The invoice's public page includes the PDF download and, for invoices stamped in Mexico, the XML. Your customer no longer needs to ask you for them by email. ## Commercial invoices on the Free plan The Free plan includes **10 commercial invoices per month**, separately from quote sends. From Starter they are unlimited. Fiscal issuance (CFDI in Mexico) starts on Starter, with its own monthly allowance. ## Prices in euros In Spain, Germany, and France, the Cord subscription is purchased at fixed prices in euros (EUR) for the self-service plans. If you already have a contract in another currency, Cord keeps it. Developer has no self-service euro price; it is purchased through sales. See [Subscription](/en/docs/cuenta/suscripcion). ## Mercado Pago as a second payment rail You can connect your own Mercado Pago account in **Settings › Payments › Payment methods**. Your customer sees it on the quote's payment page and on the invoice link, including partial payments. Refunds you issue from Mercado Pago are reflected in the balance automatically. See [Mercado Pago](/en/docs/pagos/mercado-pago). ## Safe switching between bank transfer and card If your customer starts paying with one method and switches to another (for example, from a SPEI transfer or a bank transfer with a reference to card), Cord first checks the previous attempt. If it has already received money or has a payment in progress, it isn't replaced and the customer is asked to wait for confirmation. See [Payment methods](/en/docs/pagos/metodos). ## Payout frequency In **Settings › Payments › Payouts** you choose how often your money goes out from Cord Payments to your bank account: daily, weekly (choosing the day), monthly (from the 1st to the 28th), or manual. If your account's verification has pending requirements, that same screen tells you payouts are paused. ## Refunds with a fee notice When you refund a payment from **Revenue › Payments**, or an invoice's online payment from its detail page, the dialog asks you to confirm that you understand Cord's platform fee is not refunded automatically. See [Refunds](/en/docs/pagos/reembolsos). See the [roadmap](https://cordhq.app/en/roadmap) for what's coming next. --- # Mercado Pago URL: https://docs.cordhq.app/en/docs/pagos/mercado-pago Last updated: 2026-10-11 Collect quotes with your Mercado Pago account: which countries it applies to, how to connect, what your client sees, how payments are confirmed, and what it does not do yet. ## When it applies Mercado Pago is a second online payment rail, next to [Cord Payments](/en/docs/pagos/onboarding). Its role depends on your account's country: | Country | Cord Payments | Mercado Pago | |---|---|---| | Mexico | Available, the main rail | Alternative on the same payment page | | Brazil, Colombia, Argentina, Chile, and Peru | Not available | The way to collect online | | Other Cord countries | Depends on the country | Not offered | Cord offers Mercado Pago to accounts in **Mexico, Brazil, Colombia, Argentina, Chile, and Peru**. In all of them you get paid with your own account, and the payment methods, currency, and fees are the ones Mercado Pago has enabled for your account in your country. End-to-end payment has been verified in Mexico; in the other countries, before sharing the link with your clients, make a test payment for a small amount (see the [FAQ](#faq)) and contact us if something doesn't work as you expect. ## Connect your account 1. Open **Settings › Payments › Payment methods**. You need the **Payment settings** permission. In Colombia, Argentina, Chile, and Peru, **Settings › Payments › Account** brings you here with the **Connect Mercado Pago** button. 2. Under **Other processors**, on the **Mercado Pago** row, click **Connect Mercado Pago**. 3. Sign in to Mercado Pago with the account that will receive the money and authorize Cord. 4. You return to **Payment methods** and the row says **Connected**. Mercado Pago is added to the **Your client will see** line. Use a business account in your company's name: it is the seller shown at checkout and the one that receives each payment. Cord stores that access encrypted and renews it on its own. It only uses it to open the payment for your quotes and to read whether it was paid. If Mercado Pago stops accepting the renewal, for example because you removed the authorization from your account, the row asks you to connect again and Mercado Pago is no longer offered to your clients until you do. To disconnect, click **Disconnect** on the same row. Open payments can no longer be paid with Mercado Pago; paid ones keep their history. ## What your client sees On the **quote's** payment page and on the **invoice's** public link: - **If Mercado Pago is your only rail**, they see a blue **Pay with Mercado Pago** button with the Mercado Pago logo. - **If you also have Cord Payments**, they first see the Cord Payments form and, below a divider, the **Pay with Mercado Pago** button. Clicking it opens Mercado Pago's checkout, where they pay with the methods Mercado Pago offers in their country. Once the payment is approved, they return to your link. If the quote has a deposit and balance, or installments, each part is collected separately, and the quote is paid once no balance remains. On an invoice they can **pay part of it**: click "Pay another amount", type how much, and Cord caps it at the real balance. ## How payments are confirmed 1. Mercado Pago notifies Cord that there was a payment. The notice arrives signed, and Cord rejects any notice whose signature does not match. 2. Cord **reads the payment in Mercado Pago** with your account's access. It never treats a payment as done based on the notice alone. 3. Only an **approved** payment marks the charge as paid. A payment that stays pending, such as cash, is marked paid when Mercado Pago approves it. 4. Mercado Pago resends its notices by design. A repeated notice does not record the payment twice. If the same charge ends up paid through both Cord Payments and Mercado Pago, Cord notes it in the quote history so you can decide whether to refund one. ## Refunds An **invoice** payment collected with Mercado Pago is refunded from Cord, fully or partially: on the invoice detail page, the **Refund** button next to the payment (see [Refunding an invoice payment](/en/docs/pagos/reembolsos#refunding-an-invoice-payment)). Cord requests it from Mercado Pago through your account's connection, so the money leaves your Mercado Pago account, just as it came in. A **quote** payment is refunded **from your Mercado Pago account**. In both cases, and also if you refund an invoice from Mercado Pago, Cord reads the refund: once Mercado Pago confirms the money went out, it lowers the paid amount, reopens the balance, and records it in the document's history. If the quote had already been invoiced, refunding its payment also reopens the invoice. A refund Mercado Pago has not confirmed yet does not touch the balance. ## What it does not do yet | Case | Today | |---|---| | Recurring retainers | Not offered: a retainer needs the Cord Payments subscription. | | Scheduled charges | Mercado Pago charges when your client opens the link; it does not store their card to charge later. | | Chargebacks | Cord does not read Mercado Pago chargebacks today: if a client disputes a payment, the case doesn't appear in the **Open disputes** widget of [Payments](/en/docs/pagos/dashboard) and the balance in Cord doesn't change. Handle it from your Mercado Pago account. | ## FAQ **Does Cord charge with my account or Cord's?** Yours. The money never goes through Cord. **What fee does Mercado Pago charge?** Your account's fee, under the terms you have with Mercado Pago. It is deducted from each payment. **Can I test without charging for real?** Create a quote for a small amount, pay it from another browser without a session using a card that is not from the same Mercado Pago account (Mercado Pago does not let you pay yourself), and refund it afterwards from Mercado Pago. --- # Payment methods URL: https://docs.cordhq.app/en/docs/pagos/metodos Last updated: 2026-10-14 Which payment methods Cord offers by country and currency, how to turn them on, how each one is confirmed, bank transfer with a reference, SEPA, ACH, Bacs, and pre-authorized bank debit, what the quote, the invoice, and the portal accept, and how to switch between bank transfer and card without charging twice. ## What it is Cord has **two online payment rails** and one manual option: - **Cord Payments:** card; a transfer that reconciles on its own (SPEI in Mexico and bank transfer with a reference in Spain, Germany, France, the United Kingdom, and the United States); and bank debit (SEPA, ACH, Bacs, and Canadian pre-authorized debit). The money lands in your own [payments account](/en/docs/pagos/onboarding) and from there reaches your bank at the [payout frequency](/en/docs/pagos/depositos) you choose. - **[Mercado Pago](/en/docs/pagos/mercado-pago):** your customer pays with your own Mercado Pago account, using the methods Mercado Pago offers in your country. - **Manual transfer:** you share your bank details and record the payment yourself once you verify it. ## Method by country and currency | Method | Countries | Payment currency | Quote | Invoice | Client portal | Retainer | Automatic payments | |---|---|---|---|---|---|---|---| | **Card** (Cord Payments) | MX, US, CA, ES, GB, DE, FR | The document's sale currency, if the processor supports it | Yes | Yes | Yes | Yes | Yes | | **[Interest-free installments (meses sin intereses)](https://cordhq.app/en/support/msi-meses-sin-intereses)** (Cord Payments, Mexican credit card) | MX only | MXN only, from MXN 300 | Yes | Yes | Yes | No | No | | **[Bizum](https://cordhq.app/en/support/cobrar-con-bizum)** (Cord Payments, from your customer's banking app) | ES only | EUR only, from €0.50 to €5,000 per payment | Yes | Yes | Yes | No | No | | **Automatic SPEI** (Cord Payments) | MX only | MXN only | Yes | Yes | No | No | No | | **Bank transfer with a reference** (Cord Payments) | ES, DE, FR · GB · US | EUR only · GBP only · USD only | Yes | Yes | No | No | No | | **SEPA Direct Debit** (Cord Payments) | ES, DE, FR | EUR only | No | Yes | Yes | No | Yes | | **ACH bank debit** (Cord Payments) | US only | USD only | No | Yes | Yes | No | Yes | | **Bacs Direct Debit** (Cord Payments) | GB only | GBP only | No | Yes | Yes | No | Yes, saved when paying | | **Pre-authorized debit** (Cord Payments) | CA only | CAD only | No | Yes | Yes | No | Yes | | **Mercado Pago** | MX, BR, CO, AR, CL, PE | Whatever Mercado Pago supports on your account | Yes | Yes | No | No | No | | **Manual transfer** | All 12 Cord countries | Any | Yes | Yes (manual record) | No | No | No | In Mexico both rails coexist: Cord Payments is the primary one and Mercado Pago appears as an alternative on the same page. In Brazil, Colombia, Argentina, Chile, and Peru, Mercado Pago is the way to collect online. See [Cord Payments fees](/en/docs/pagos/condiciones) for the cost of each method. ## Turn methods on 1. Open **Settings › Payments › Payment methods** with the **Payment settings** permission. Each switch saves right away, and the **Your client will see** line at the top sums up the methods you have turned on. 2. Under **Online payments**, turn on **Credit and debit card** and, depending on your country, the transfer that reconciles on its own —**Automatic SPEI transfer** (Mexico), **Automatic SEPA transfer** (Spain, Germany, and France), **Automatic bank transfer** (United Kingdom), or **Automatic ACH and wire** (United States)— and bank debit —**SEPA Direct Debit** (Spain, Germany, and France), **ACH bank debit** (United States), **Bacs Direct Debit** (United Kingdom), or **Pre-authorized debit (Canada)**. Each method shows its status and, under its description, its fee. They can be turned on once your payments account is **Active**; before that they show **Needs an active account**. 3. Under **Automatic payments**, leave **Allow automatic payments** on if you want your clients to be able to save a method in their portal. See [Automatic payments](/en/docs/pagos/cobro-automatico). 4. If there's a fee version you haven't accepted yet, review and accept it in **Settings › Payments › Fees**. See [Cord Payments fees](/en/docs/pagos/condiciones#how-your-fee-schedule-is-activated). 5. To offer manual transfer, under **Manual bank transfer** turn on **Transfer to your account**, enter the **bank**, the account in your country's format, and the **beneficiary**, and click **Save changes**: the bank details are the only thing on this tab saved with that button. 6. For Mercado Pago, click **Connect Mercado Pago** on its row, under **Other processors**. See [Mercado Pago](/en/docs/pagos/mercado-pago). The rows depend on your business's country: a business in Mexico sees card, interest-free installments, SPEI, and Mercado Pago; one in Spain, card, Bizum, SEPA transfer, and SEPA Direct Debit (see [Bank debit](#bank-debit)). ## Card Your customer reviews the amount and enters their card details in a form inside the link, without leaving for another page. Their bank may ask for additional verification. The payment shows up once confirmation arrives; closing the screen or returning to the link doesn't prove it was paid. Card is the only method for [recurring retainers](/en/docs/pagos/igualas), because it's the only one that can charge itself every month. ## Apple Pay and Google Pay This feature is new and is being enabled: it doesn't appear on your customer's payment page yet. This page will be updated when it's available. Once it's active, your customer will be able to pay with **Apple Pay** or **Google Pay** on the same screen as the card: on the quote's payment page, on the invoice link, and in the client portal. - **They aren't turned on separately:** they come with **Credit and debit card** in **Settings › Payments › Payment methods**. If you turn the card off, they aren't offered either. - **They're charged as a card:** the same [fee](/en/docs/pagos/condiciones), the same confirmation, and the same refunds. - **Only on compatible devices:** Apple Pay on an iPhone, iPad, or Mac with a card in Wallet; Google Pay in a browser with a card saved to the Google account. If the device doesn't have them, your customer sees the usual card form. ## Automatic SPEI SPEI is Mexico's interbank transfer system and only settles in pesos. It appears only on **MXN** payments of businesses in Mexico with SPEI turned on, on the quote link and on the invoice link; if the document is in another currency, your customer pays by card even if SPEI is on. When choosing **SPEI transfer**, your customer sees the **SPEI instructions**: | Item | Detail | |---|---| | Amount | The outstanding amount of that charge, with its currency. | | CLABE | A CLABE tied to that charge, with a **Copy** button. | | Bank | The receiving bank. | | Beneficiary | Your business name. | | Reference | The charge reference, with a **Copy** button. | | Valid until | If the instructions have a deadline, it appears here. | From that screen they can **Print or save PDF**, or click **Email these to me**. ### SPEI instructions by email **Email these to me** sends the same instructions (amount, CLABE, bank, beneficiary, and reference), with your business branding, to **the customer email registered on the quote**. No other recipient can be typed: if your customer needs them at another address, update their record. If the quote has no customer email, the button returns an error and your customer can print or save the PDF. For security, sending is limited to three emails every ten minutes per link. ### How it's confirmed Each charge keeps its own bank reference, so Cord recognizes the funds without anyone cross-checking receipts. When the money arrives, the charge is marked paid and the quote changes status. Confirmation depends on the bank's notice and **isn't always instant**: if your customer already transferred, they should check the status before trying a card. ### SPEI on the invoice link This feature is new and may not be enabled on your account yet. If you do not see it, write to us. On **MXN** invoices of businesses in Mexico with SPEI turned on, the invoice link offers **SPEI transfer**. If you also accept cards, your customer chooses the method; if you only have SPEI, they go straight to **Pay [amount] by SPEI transfer**. - **One CLABE per invoice.** Each invoice has its own CLABE and keeps it on every visit and every partial payment. Money sent to that CLABE can only pay that invoice: if your customer owes you several, they transfer to each invoice's CLABE. - **Instructions.** Amount, CLABE and reference (both with **Copy**), bank, beneficiary, and expiry if there is one. Your customer can **Print or save PDF**. The invoice doesn't have the **Email these to me** button: the invoice email already carries its link. - **Partial payment by SPEI.** With **Pay another amount**, your customer transfers only part of it. The rest stays as the balance of the same invoice and the CLABE doesn't change; the reference can change, so they should always use the one on screen. - **How it's confirmed.** When the transfer for the full amount arrives, Cord records the payment on the invoice without you doing anything, recalculates the balance and, if it reaches zero, marks it **Paid**. If the invoice is a CFDI stamped as PPD, Cord issues its payment complement with payment form 03, electronic funds transfer. - **If they transfer less.** What arrived is held for that payment but isn't recorded yet: the invoice history shows **SPEI transfer** with what arrived and what's missing, and your customer sees the pending amount when they open SPEI on the invoice again. The payment is recorded when the rest arrives. If they try to pay by card in the meantime, Cord asks them to finish the transfer. - **If they transfer more.** Only the requested payment is recorded; the difference stays in your customer's favor and isn't charged. If the invoice still has a balance, it's applied when your customer chooses SPEI on it again. If it's already paid, the history says so and the difference must be returned: write to us to arrange it. If nobody uses it, the processor tries to return it to your customer after 75 days. - **Fee.** The SPEI fee from your [fee schedule](/en/docs/pagos/condiciones), the same as on the quote. - **Where it doesn't appear.** In the customer portal or in automatic payments: from the portal, your customer opens each invoice and pays it by SPEI from its own link. ## Bank transfer with a reference This feature is new and may not be enabled on your account yet. If you don't see it, write to us. Outside Mexico, the transfer that reconciles on its own is the **bank transfer with a reference**: SEPA transfer to an IBAN in EUR for businesses in Spain, Germany, and France (Spanish businesses get a French IBAN), sort code and account number in GBP in the United Kingdom, and ACH or domestic wire in USD in the United States. - **One fixed account per client and one reference per payment.** Cord reconciles by the reference and, if a transfer arrives without it, by the exact amount among that client's open payments. - **On the invoice link and the quote's payment page**, in the rail's currency and only if the document has a linked client. Not in the portal, automatic payments, or retainers. - **Less or more:** what doesn't complete a payment isn't recorded, and any excess stays in your client's favor. - **No Cord fee** outside MXN. Full details in [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). ## Bank debit This feature is new and may not be enabled on your account yet. If you don't see it, write to us. With bank debit, your client pays with a **direct debit from their bank account** instead of a card. Cord offers the scheme that matches your business's country: | | SEPA Direct Debit | ACH bank debit | Bacs Direct Debit | Pre-authorized debit (Canada) | |---|---|---|---|---| | **Businesses in** | Spain, Germany, and France | United States | United Kingdom | Canada | | **Currency** | EUR only | USD only | GBP only | CAD only | | **Client's account** | IBAN in the SEPA area | United States bank account | UK bank account | Canadian bank account | | **Confirmation** | Up to 6 business days | Up to 4 business days | 4 business days; 7 with a new mandate | Up to 5 business days | | **Refunds** | Full or partial | Full only | Full or partial | Full or partial | | **Notice to the account holder** | The processor notifies them before each debit | The processor confirms the authorization | The processor sends them the mandate and a notice for each debit | The processor sends them the mandate and a notice for each debit | Bacs and pre-authorized debit have their own rules (a Bacs account is saved when paying, and the bank statement shows the processor as the collector; in Canada your client states whether they pay as a business or an individual, and some accounts are verified with micro-deposits). Details in [Bank debit](/en/docs/pagos/domiciliacion). ### Turn it on 1. Open **Settings › Payments › Payment methods** with the **Payment settings** permission. Your payments account must be **Active**. 2. Under **Online payments**, turn on **SEPA Direct Debit**, **ACH bank debit**, **Bacs Direct Debit**, or **Pre-authorized debit (Canada)**, depending on your country. The change saves right away. 3. Cord requests the capability for your payments account. While the processor reviews it, the method shows **In review** and isn't offered to any client yet. 4. Once approved, it changes to **Active** and shows up as an option on the link of your invoices in the scheme's currency (EUR, USD, GBP, or CAD), in the [client portal](/en/docs/pagos/portal-facturas), and in [automatic payments](/en/docs/pagos/cobro-automatico). If it shows **Unavailable: check your verification**, the processor didn't enable the capability: review the pending requirements of your [payments account](/en/docs/pagos/onboarding). ### How a debit works - **Where it's offered:** on the invoice link, in the client portal, and as the saved method for automatic payments, only on invoices in its currency. It isn't offered on the quote link or for retainers. - **It takes days.** While the bank confirms, the invoice shows **Payment processing**: it can't be charged again or voided, and the invoice detail says so. When the debit is confirmed, the payment is applied like any other; if the bank declines it, the invoice goes back to being payable. - **Where Cord charges a fee (today, in MXN), it isn't offered.** Cord's fee is a card fee and there's no approved rate for debits. Outside MXN, Cord charges no fee; see [Fees](/en/docs/pagos/condiciones). - **Turning it off** stops offering it on new charges; debits already in progress carry on. - **A confirmed debit can still be disputed:** with SEPA, without giving a reason for 8 weeks; with Bacs, at any time; with pre-authorized debit, 90 days on a personal account or 10 business days on a business account. Keep it in mind before handing over something of high value against a debit that was just confirmed. ## Mercado Pago The quote's payment page and the invoice link show **Pay with Mercado Pago**. Your customer goes to Mercado Pago's checkout and returns to your link when done. Cord marks the charge paid only when it **reads the approved payment** in your Mercado Pago account. Details in [Mercado Pago](/en/docs/pagos/mercado-pago). ## Manual transfer Your customer sees your bank details and transfers from their bank. When you verify the deposit in your bank, you record the payment in Cord: on the quote, on the invoice, or with **Record payment** from [receivables](/en/docs/pagos/cartera-cobranza). A receipt sent by the customer doesn't replace that verification. Refunding a manual transfer is handled directly with your customer. ## What the quote, the invoice, and the portal accept | | Quote link | Invoice link | Client portal | |---|---|---|---| | Card | Yes | Yes, if **Card** is turned on | Yes | | Automatic SPEI | Yes, in MXN | Yes, in MXN, with that invoice's CLABE | No | | Bank transfer with a reference | Yes, in EUR, GBP, or USD, with a linked client | Yes, in EUR, GBP, or USD, with a linked client | No | | Bank debit (SEPA, ACH, Bacs, or pre-authorized debit) | No | Yes, in the scheme's currency | Yes, in the scheme's currency | | Mercado Pago | Yes | Yes | No | | Partial payment | In defined parts: deposit, balance, or installments | Free amount: your customer chooses how much to pay | No: each invoice is paid at its balance | | Several invoices in one charge | No | No | Yes, in the same currency | | Retainers | Yes, by card | No | No | ### Partial payment of an invoice On the invoice link, your customer can pay the full balance or click **Pay another amount** and enter how much they want to pay, by card, SPEI, bank transfer with a reference, or Mercado Pago: - Cord **caps the payment at the real balance**: if they enter more than they owe, only the balance is charged. - There's a **minimum that can be charged online**: 0.50 in the invoice currency (for example, 0.50 USD or 0.50 EUR), or 50 units in currencies without decimals. If the amount is lower, Cord asks them to pay a bit more or settle the balance. - Each payment is recorded in the invoice's payment history and the balance is recalculated. The invoice becomes **Paid** when the balance reaches zero. - If the balance changes while your customer is paying (for example, because you recorded another payment), Cord asks them to refresh before continuing. See [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas). ## Switch between bank transfer and card Your customer can choose another method on the same page, on the quote and on the invoice. Before offering the new one, Cord checks the previous attempt: - If the previous attempt **received no money**, it's canceled and the new method opens. - If it **already received money or has a payment in progress** (a partial transfer, SPEI or with a reference, a bank debit in progress, or a card being authorized), it isn't replaced: your customer sees there's a payment pending confirmation. - If two attempts arrive at the same time, the same one is reused instead of creating another. - If Cord can't confirm the previous attempt's status, it **doesn't open another one**: it prefers a review over risking a double charge. While a payment is pending clarification, your customer shouldn't repeat the transfer or try another method: they should refresh the link or contact you. Cord doesn't automatically return a transfer that arrives late at old instructions; you resolve that case with your customer. ## Limits - SPEI: Mexico only and MXN only, on the quote link and on the invoice link. Not in the portal or in automatic payments. - Bank transfer with a reference: only in EUR (Spain, Germany, and France), GBP (United Kingdom), or USD (United States), with a linked client, on the invoice link and the quote's payment page. Not in the portal, automatic payments, or retainers. No international wire. - Bank debit: SEPA only in EUR for businesses in Spain, Germany, and France; ACH only in USD for businesses in the United States; Bacs only in GBP for businesses in the United Kingdom; pre-authorized debit only in CAD for businesses in Canada. Only on invoices, the portal, and automatic payments. - The invoice doesn't offer retainers. - Mercado Pago doesn't run recurring charges and Cord doesn't read its chargebacks today. - In Colombia, Argentina, Chile, and Peru there's no Cord Payments: online collection is through Mercado Pago. - A test document (without a valid fiscal issue) can't be paid online. ## Common problems **My customer doesn't see the SPEI option.** The quote or the invoice isn't in MXN, SPEI is off in **Settings › Payments › Payment methods**, or your account isn't active. SPEI doesn't appear in the customer portal: it's paid from each invoice's link. **My customer doesn't see a pay button on the invoice.** Your payments account isn't active; or **Card** is off, no other method applies to that invoice (SPEI only in MXN, bank transfer with a reference in your country's currency and with a linked client, bank debit in its scheme's currency) and Mercado Pago isn't connected; or the invoice is a test document. **My customer doesn't see the bank transfer with a reference.** The document isn't in EUR, GBP, or USD (depending on your country), it has no linked client, the method is turned off in **Settings › Payments › Payment methods**, or the processor hasn't activated it on your account yet. **My customer doesn't see bank debit.** The invoice isn't in the method's currency (EUR for SEPA, USD for ACH, GBP for Bacs, CAD for pre-authorized debit), the method isn't **Active** in **Settings › Payments › Payment methods**, or it's a charge in MXN. **"Email these to me" fails.** The quote has no customer email or the sending limit was reached. Your customer can **Print or save PDF**. **My customer transferred less than they owed to an invoice's CLABE.** The invoice history shows it as **SPEI transfer** with what's missing. Ask them to transfer the rest to the same CLABE: the payment is recorded when it arrives in full. **My customer transferred to another charge's CLABE.** Each charge has its own reference. Contact your customer and review the quote's charges before recording anything by hand. ## Integrations using the previous checkout If an integration still requests a quote's previous checkout, it receives a link to Cord's current payment screen, with the same attempt record and the balance due. The response keeps the `url` field and doesn't change the accepted fees. ## Related - [Accepting a payment](/en/docs/pagos/aceptar) - [Cord Payments fees](/en/docs/pagos/condiciones) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Client portal: invoices and payments](/en/docs/pagos/portal-facturas) - [Automatic payments](/en/docs/pagos/cobro-automatico) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [Your Cord subscription currency](/en/docs/cuenta/suscripcion) --- # Connect your account URL: https://docs.cordhq.app/en/docs/pagos/onboarding Last updated: 2026-10-15 The 8 steps to verify your business and activate Cord Payments inside Cord: identity documents by country, people and beneficial owners, phone capture, photo quality, payout account, and account statuses. ## What it is To collect by card, bank transfer, or bank debit from a quote or invoice link you need a verified **payments account** in your business's name. Financial regulations require knowing who you are, who controls the business, and where the money goes (KYC, *Know Your Customer*). Cord runs the whole process **inside the app**: the wizard, the camera, and the bank account are Cord screens, with no redirects to a third-party form. On payments in Mexican pesos (MXN), Cord charges a fee per payment; in any other currency there's no platform fee today. See [Cord Payments fees](/en/docs/pagos/condiciones). ## Requirements | Requirement | Detail | |---|---| | Plan | All plans. | | Permission | **Payment settings**. | | Country | Mexico, United States, Canada, Spain, United Kingdom, Germany, and France. | | Documents | A valid, color government ID for each person you declare. | | Bank account | In the name of the business or its legal representative, in your country's banking format. | The payments account is opened in your business country (**Settings › General**) and in that country's currency, and **neither can be changed later**: regulatory verification requires it. Cord blocks country changes once the account exists. If the country is wrong, fix it before you start. ### Where it's available Cord Payments works today in **Mexico, the United States, Canada, Spain, the United Kingdom, Germany, and France**. In **Brazil, Colombia, Argentina, Chile, and Peru** you can use everything else (quote, invoice, follow up on collections, and record payments received by transfer) and collect online with [Mercado Pago](/en/docs/pagos/mercado-pago). **Settings › Payments › Account** tells you Cord Payments isn't available before you start a verification that couldn't be completed, and takes you to connect Mercado Pago in **Payment methods**. ## The 8 wizard steps 1. Go to **Settings › Payments › Account**, the first Payments tab. 2. If you haven't connected your account yet, the wizard appears on that same tab, at step 1. Move forward with **Continue**. 3. Complete the steps. Whatever you save is kept: if you leave halfway, you pick up where you left off. | Step | What it captures | |---|---| | **1. Entity type** | Whether you operate as an **Individual** or a **Company**, and your line of business. | | **2. Business details** | Legal name, your country's tax ID (RFC in Mexico, NIF/CIF in Spain, EIN in the United States), and contact details. | | **3. Registered address** | The business's registered tax address. | | **4. Identity** | Personal details of the legal representative or the individual. Only the fields your country's verification requires appear: in the United States, for example, the last 4 digits of the SSN; in Spain, Germany, and the United Kingdom no personal ID number is requested. In a company, if the representative's details belong to someone else, you declare that you're authorized to provide them and that you informed that person. | | **5. People** | Who controls the business, with their role and ownership. An individual skips this step. See [People and beneficial owners](#people-and-beneficial-owners). | | **6. Verification** | The photo of each person's ID and, if requested, a proof of address or a company document. | | **7. Bank account** | The payout account in your country's format. See [Payouts to your bank](/en/docs/pagos/depositos#your-payout-account). Before saving it you authorize, in a checkbox separate from the terms, the processing of your financial data; Cord records that authorization with its version, date, IP address, and browser. | | **8. Terms** | You accept the processing of your data, the Cord Payments terms, and your payments account agreement. The acceptance is recorded with date, IP address, and terms version. The Cord fee is activated separately, in **Settings › Payments › Fees** (see [Fees](/en/docs/pagos/condiciones#how-your-fee-schedule-is-activated)). | If verification finds something specific missing (a blurry photo, a detail that doesn't match), the wizard takes you straight to that step instead of starting over. ## Verification decides what's requested Cord has no fixed list of fields per country. The data, documents, and declarations you see come from what your account's verification reports as pending, and the country only decides **what each item is called** (RFC, NIF, EIN; INE, DNI, Personalausweis). That's why two businesses in the same country can see different steps: a company with several partners declares more people than an individual, and a new requirement appears as soon as verification asks for it. ## People and beneficial owners In the European Union, the United Kingdom, and Canada, declaring **beneficial owners** (people with 25% or more ownership) is a legal obligation. The **People** step is a list you build: - **Add each person** with their details, ownership, and roles. - **A person can have several roles**, each marked separately: | Role | When to mark it | |---|---| | **Legal representative** | Operates the account and signs for the business. | | **Owner** | Owns 25% or more of the business. Their percentage is captured. | | **Director** | Is a director, administrator, or board member. | | **Executive** | Holds an executive management role. Their job title is captured. | - **The total percentage is informational.** Cord shows "Declared: N% ownership", but doesn't force you to reach 100%: there are legitimate structures where the named owners don't add up to the total. - **Each person has their own verification**, with a visible status: **Details captured**, **Under review**, **Verified**, or **Action required**. - **Adding, editing, or removing a person requires confirming your identity**, just like changing the payout account. - **When you save a person you declare** that you're authorized to provide their details and that you informed them that Cord processes them and sends them to the financial verification system. Next to the checkbox is the link to the Privacy Notice so you can share it with **Copy link**. Cord records the declaration with date, IP address, and browser. A partnership with three partners at 30% each declares all three. If it declared only one, the account wouldn't activate: verification would keep asking for the missing ones. ### Declarations When your country's verification requires it, a declaration appears at the end of the list, for example: "I confirm I've added every owner with ≥25%". It's a **legal declaration under your responsibility** and is sent as is. It only appears **after** you've built the list, and Cord records on its server the date, IP address, and browser from which you accepted it. ID numbers, dates of birth, home addresses, and document images go straight to the financial verification system. Cord keeps each person's name and roles to show you the list. That's why, when you edit a person, the date of birth, ID, and address are entered again; if you leave them blank, the ones already on file are kept. ## Identity documents by country Before taking the photo, you choose which document you'll use. That choice adjusts the shape of the camera frame (a card or a passport page) and decides whether you'll be asked for the back. | Country | Suggested documents | Back side | |---|---|---| | Mexico | Voter ID (INE), passport, driving licence | INE and licence yes; passport no | | United States | State driving licence, state ID card, passport | Licence and ID yes; passport no | | Canada | Passport, provincial driving licence, provincial ID card | Licence and ID yes; passport no | | Spain | DNI, NIE / TIE, passport, driving licence | DNI, NIE / TIE, and licence yes; passport no | | United Kingdom | Passport, photocard driving licence, biometric residence permit | Licence and permit yes; passport no | | Germany | *Personalausweis*, passport, electronic residence permit | Yes, except the passport | | France | *Carte nationale d'identité*, passport, *titre de séjour* | Yes, except the passport | This list translates the three categories verification accepts (passport, driving licence, and government-issued photo ID) into the name you recognize your document by. It's not a guarantee of acceptance: if verification rejects a document, Cord tells you why. If a person's country of residence differs from the payments account's country, verification **only accepts a passport**. Cord detects this and tells you before you take the photo, so you don't wait days for a certain rejection. ### Proof of address and company documents If verification asks for it, a **proof of address** is added: a recent utility bill or bank statement in the person's name. It must be a **different** document from the ID: one document can't cover two requirements. If a **company document** is requested, it's uploaded in the same step. | File | Formats | Maximum size | |---|---|---| | ID (front and back) | JPG or PNG, in color | 10 MB | | Proof of address or company document, from the computer | JPG, PNG, or PDF | 10 MB | | Any photo from the phone | JPG or PNG | 10 MB | ## Continue on your phone A phone camera almost always gives better light and focus than a webcam or a scan. In the **Verification** step, the **With your phone** option is marked as recommended. 1. On your computer, in the **Verification** step, choose **With your phone** and click **Generate QR code**. You can also copy the link with **Copy** and open it on your phone. 2. Scan the code with your phone's camera. **Verify your identity** opens with the steps you'll need; tap **Start**. 3. Choose which document you'll use. If your address is in another country, the screen tells you only a passport is accepted. 4. Take the photo of the **front**. If you prefer the camera app or already have the photo, use **Choose a photo instead**. 5. Take the photo of the **back**, if your document has one. With a passport, tap **Skip — it's a passport**. 6. If requested, take the photo of the **proof of address**. You can skip it when it wasn't requested. 7. When you finish you'll see **Done**. Go back to your computer: the screen, which says "Waiting for you to finish on your phone…", continues on its own. ### Link rules The QR code link is a single-use credential and is treated as one: | Rule | Detail | |---|---| | Validity | 30 minutes from when you generate it, and 15 minutes from the first photo you upload. Whichever comes first. | | One person | It only works for the person you generated it for. Generating another one for that person closes the previous one. | | When you finish | Once the phone finishes, the link closes and no longer accepts photos. | | One device | It's tied to the first phone that uploads a photo. You can move from a messaging app's browser to the same phone's browser, but if it's used on more devices it's blocked with "For security this link is tied to the first phone that opened it". | | Attempts | It allows up to 12 uploads and is blocked after 6 failures in a row. When exhausted it says the link's attempts ran out. | | Same photo | The same photo isn't accepted twice: if a document was rejected, take a new photo. The same photo isn't accepted for front and back either. | | Privacy | The link page records no analytics and isn't stored in the browser cache. | If the link expires or is blocked, generate a new one from your computer with **Generate a new one**. What you already uploaded is kept. ## Photo quality The most common cause of a rejection isn't an invalid document: it's a photo that can't be read. Before sending, Cord measures the image. Almost everything it detects is **advice**: you can send the photo anyway if you think it's fine. Only two things stop the upload, because verification always rejects them: | What Cord detects | What it does | What it suggests | |---|---|---| | Very low resolution | **Blocks** | Move closer to the document, or use **Choose a photo** to take it with the camera app. | | ID in black and white | **Blocks** | Take it again in color. | | Photo too dark | Warns | Move near a window or turn on a light. | | Too much light | Warns | Move away from the lamp or direct sunlight. | | Glare on the document | Warns | Tilt it slightly to remove it. | | The document blends into the background | Warns | Place it on a differently colored surface. | | Blurry photo | Warns | Rest it on a flat surface and wait for it to focus. | | Readable, but could be better | Warns | Move closer and let it focus. | A black-and-white proof of address is accepted: the color rule applies only to photo IDs. ## If a document is rejected When verification rejects a photo, Cord shows **the reason** on that person's card: the image can't be read, the document is expired, the name doesn't match the one entered, or the back is missing. Fix that specific issue and take a new photo. Images are transmitted encrypted to the financial verification system and Cord doesn't store them. Before sending them, Cord **strips their metadata**, including the GPS location many phones save inside the photo, and keeps only the orientation so the photo doesn't arrive rotated. Cord does keep a **compliance record** of each upload: which side of the document was sent, when, from which IP address, the photo's quality measurements, and what verification answered. Never the image, the document number, or a thumbnail. That record is kept for five years, the period required by anti-money-laundering rules. ## Account statuses | Status | What you see in Settings › Payments › Account | What you can do | |---|---|---| | **New** | The wizard at step 1. | Quote, invoice, and record manual payments. Online methods (card, bank transfer, and bank debit) are locked. | | **Pending** | **Verification pending**: verification is in progress or a requirement is missing. The screen refreshes on its own during review. | Complete what's pending. Online methods stay locked. | | **Active** | **All set, you can accept payments now!**: identity and bank account confirmed. | Collect with the methods you turn on and [receive payouts](/en/docs/pagos/depositos). | Once the account is connected, **Your account status** also shows **Payments** and **Payouts** (Enabled or Paused), **Verification** (Complete, In review, or how many items are due) and, if details are missing, their **Deadline**. An active account can ask for information again later, for example when a document expires or requirements change. **Settings › Payments › Account** then asks you to provide the missing details, with their deadline if there is one, so your payments and payouts aren't paused, and shows you what's missing so you can complete it right there. The **Account status** widget on [Revenue › Payments](/en/docs/pagos/dashboard) also shows how many requirements are missing and their deadline. To stop collecting with Cord Payments, click **Disconnect Cord Payments** in the **Danger zone** of the same tab, confirm, and verify your identity when Cord asks. You stop receiving online payments with Cord Payments; your manual transfer details and payment history are kept. ## Limits - Cord Payments is available in seven countries; the account's country and currency don't change later. - Cord doesn't run liveness checks or selfies: document authenticity is checked by the verification system on the photo you upload. - The phone link lasts at most 30 minutes and allows 12 uploads. - IDs are uploaded as JPG or PNG, in color, up to 10 MB. ## Common problems **The wizard asks for something another account didn't.** What's requested depends on your country, entity type, and verification status. That's normal. **The camera won't start on my phone.** Check that the browser has camera permission. If you opened the link inside a messaging app, open it in the phone's browser. You can always use **Choose a photo instead**. **It says the link is tied to another phone.** Generate a new link from your computer and open it only on the phone you'll use. **The same photo was rejected again.** Resending the same file fails again. Take a new photo fixing the reason shown. **I can't change the business country.** That's intentional once the payments account exists: the account's country can't be modified. ## Related - [Payouts to your bank](/en/docs/pagos/depositos) - [Cord Payments fees](/en/docs/pagos/condiciones) - [Payment methods](/en/docs/pagos/metodos) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Team and security](/en/docs/cuenta/equipo-seguridad) --- # Invoicing in Germany URL: https://docs.cordhq.app/en/docs/pagos/paises/alemania Last updated: 2026-10-13 Invoice in German with USt. per line item, Leistungsdatum, Kleinunternehmer, downloadable XRechnung UBL and CII, ZUGFeRD/Factur-X and Peppol, Leitweg-ID with check digit, validated USt-IdNr., and collection by card or SEPA. ## What it is In Germany Cord issues an invoice with a sequential number, in **German** or in your client's language, with each line item's USt. and the mentions required by § 14 UStG. Each issued invoice can also be downloaded as an **e-invoice** under the European standard EN 16931: **XRechnung** (UBL and CII), **ZUGFeRD/Factur-X** (the PDF with the XML inside), and **Peppol BIS 3.0**. By default, the invoice email carries the PDF and the XRechnung XML. Cord **generates** these files and can attach them to the email; it **does not** transmit them over the Peppol network or to a public administration platform. | | In Germany | |---|---| | Default currency | EUR | | Tax | Umsatzsteuer (USt.) | | Tax ID | Steuernummer / USt-IdNr. (the USt-IdNr. with its check digit) | | Document | Invoice with downloadable XRechnung, ZUGFeRD/Factur-X, and Peppol | | Authority | Not applicable: Cord does not transmit | | PDF language | Your client's or, if they have none, your account's; legal notices, in German | | Online payments | Card, SEPA transfer with a reference, and SEPA Direct Debit (EUR) with Cord Payments | European e-invoicing is new. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. ## Requirements - **Plan:** any (Free: 10 invoices per month). E-invoices are generated on every plan. - Your **Steuernummer** or your **USt-IdNr.**: the invoice carries one of the two. - For XRechnung: a **billing contact** with name, phone, and email, your IBAN in **Settings › Payments › Payment methods** (Manual bank transfer), and, on each client, their city, postal code, and **buyer reference**. - **Permissions:** **Settings** for the tax profile; **Quotes** to issue. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, your **Steuernummer / USt-IdNr.**, address, and invoice prefix. If you apply the small business scheme, turn on **Small business (§ 19 UStG)**. 2. Under **European e-invoicing**, complete the **billing contact** and their phone, your **electronic address** (scheme and identifier), your company registration number, and the **BIC**. The IBAN is the one under **Manual bank transfer**, in **Settings › Payments › Payment methods**. 3. Choose what to **attach to invoice emails**: by default, PDF and XRechnung XML. 4. On each public administration client, enter their **Leitweg-ID** as the buyer reference. ## Taxes - **USt. 19%** (default) and **USt. 7%** (reduced), per line item. - **Steuerfrei** for exempt transactions. On the exempt profile you can choose its **e-invoice classification** (for example, reverse charge or export); empty, Cord derives it from the client. - **Small business (§ 19 UStG):** with the option on, your tax-free invoices carry the legal notice that explains it. If an invoice charges tax, the notice is not printed. ## Leistungsdatum § 14 Abs. 4 Nr. 6 UStG requires the **date of supply**. In the invoice editor, **Date of supply** accepts a date or a period (start and end); the PDF prints it as **Leistungsdatum** or **Leistungszeitraum**. If you leave it empty because it matches the issue date, the invoice says "entspricht dem Rechnungsdatum", which is the accepted form. ## E-invoice The detail of each issued invoice lists the formats it can already generate, ready to download, and for the rest it says which data is missing and where to fix it. Your client also downloads them from the invoice link. | Format | What for | |---|---| | **XRechnung (UBL)** | The format the German public administration requires and many businesses accept. | | **XRechnung (CII)** | The same invoice in CII syntax, if your client asks for it. | | **ZUGFeRD / Factur-X (PDF)** | The usual PDF with the XML inside (EN 16931 profile). | | **Peppol BIS 3.0 (UBL)** | For clients receiving over the Peppol network (you upload it to your access provider). | **What each format requires:** XRechnung, the buyer reference, a contact with name, phone, and email, the client's city and postal code, and the IBAN; Peppol, the buyer reference or purchase order and both electronic addresses, and between German businesses also the IBAN. An issued invoice keeps the data it was issued with: what you correct later applies to the next ones. ## Leitweg-ID The **Leitweg-ID** identifies the public body receiving the invoice. Cord checks its **check digit** (ISO/IEC 7064 MOD 97-10, according to the KoSIT specification) wherever it knows it is a Leitweg-ID: in an electronic address with scheme 0204 and in the buyer reference of a client with that address. An invalid Leitweg-ID is rejected when saving, with the reason, and the e-invoice is not generated. If a value saved earlier no longer passes, the client profile flags it and asks you to correct it. ## Client and product data - **Client:** their USt-IdNr. (validated), city and postal code, **electronic address**, and **buyer reference** (Leitweg-ID for the public administration). - **Invoice:** the buyer reference and purchase order are entered in the editor's summary; if left empty, the reference comes from the client profile. - **Product:** its unit travels in the e-invoice. ## Void or correct An invoice is **voided** from its detail if it has no payments applied; with payments, it is corrected with a **credit note**, which is also generated as an e-invoice. ## Get paid online - **Card** with Cord Payments. - **SEPA transfer with a reference** in EUR, which you turn on with **Automatic SEPA transfer** in **Settings › Payments › Payment methods**: your client transfers to an IBAN of their own (the account holder is typed exactly as shown), with a reference per payment, and Cord reconciles it on its own. It's offered on the invoice link and the quote's payment page if the document has a linked client. This feature is new: see [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). - **SEPA Direct Debit** in EUR, which you turn on in **Settings › Payments › Payment methods**: up to six business days to confirm and the account holder can return it for eight weeks. This feature is new. - Your payouts arrive at your **IBAN**. See [Payouts](/en/docs/pagos/depositos). ## Plan limits | Plan | Invoices per month | |---|---| | Free | 10 | | Starter, Pro, Scale, Developer | Unlimited | ## What Cord does not cover yet - **Transmission** over the Peppol network or to the public administration's receiving platforms: Cord generates and attaches, you send. - **Withholdings** in the e-invoice: the European standard has no place to declare them, and an invoice with a withholding is not generated in these formats. - Currencies with three decimals in the e-invoice. ## Common problems **The detail says the buyer reference is missing.** XRechnung requires it: enter it in the editor or on the client profile. **Cord rejects the Leitweg-ID.** The check digit does not match. Ask your client for the full Leitweg-ID, with its hyphens. **My invoice does not show the date of supply.** If it matches the issue date, the invoice says "entspricht dem Rechnungsdatum". If not, enter it in the editor before issuing. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [European e-invoicing](/en/docs/pagos/factura-electronica) - [France](/en/docs/pagos/paises/francia) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in Argentina URL: https://docs.cordhq.app/en/docs/pagos/paises/argentina Last updated: 2026-10-13 Electronic invoice authorized by ARCA with CAE and QR code: types A, B, and C according to VAT status, credit note, web service point of sale, your CUIT's certificate, end consumers, foreign currency, what is not covered yet (type E), and collection with Mercado Pago. ## What it is In Argentina each invoice must be authorized by **ARCA**, which assigns its number and its **CAE** (electronic authorization code). Cord talks directly to ARCA's web services, without an intermediary, using **your** CUIT's certificate: it builds the document, requests authorization, and stores the response. The PDF prints the CAE, its expiration, and ARCA's QR code. Electronic invoicing with ARCA is built and being activated: Cord turns it on country by country. Meanwhile, Settings › Tax profile says **Coming soon** and your invoices are issued as commercial invoices without tax validity. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. | | In Argentina | |---|---| | Default currency | ARS (also foreign currency, with an exchange rate) | | Tax | IVA | | Tax ID | CUIT, validated with its prefix and check digit | | Document | Commercial invoice today; type A, B, or C invoice and credit note with CAE once activated | | Authority | ARCA | | PDF language | Your client's or, if they have none, your account's; ARCA data and legends, in Spanish | | Online payments | Mercado Pago | ## Requirements - **Plan:** Starter or higher to issue with ARCA. On Free, commercial invoice (10 per month). - A **point of sale** created in ARCA as **"Factura electrónica - Web services"**. - Your CUIT's **ARCA certificate** associated with the electronic invoicing service (`wsfe`): the `.crt` that ARCA issues and the private key you used to request it, or a `.p12`/`.pfx` file. You generate it in ARCA with your tax password (clave fiscal). - Your **VAT status**: Responsable Inscripto, Monotributo, or Exento. - **Permissions:** **Settings** for the tax profile; **Quotes** to issue; **Collections** for the credit note. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, your **CUIT**, and your address under **Invoice identity**. 2. Under **Electronic invoicing with ARCA**, complete the **point of sale (web service)**, your **VAT status**, **what you sell** (products, services, or both) and, if you want, your gross income tax number and the start of activities. 3. Under **ARCA certificate**, upload the `.crt` and `.key` (or the `.p12`) with the key password if it has one. Cord validates that it belongs to your CUIT and shows its validity. 4. On each Argentine client, choose their **VAT status** on their profile: it decides the invoice type. ## Taxes - **IVA 21%** (default), **10.5%**, **27%**, and **Exento**, per line item. ARCA receives IVA by rate; a 0% line item is reported as exempt. - **Monotributo and exempt** issuers issue type C, without itemized IVA. - The document discount (bonificación) travels already split across line items, so the net amount, the bases, and IVA match the invoice. ## Invoice type The type comes from ARCA's table using your status and your client's: | Your status | Client | Type | |---|---|---| | Responsable Inscripto | Responsable Inscripto or Monotributo | A | | Responsable Inscripto | End consumer, exempt, or others | B | | Monotributo or Exento | Any | C | - **Recipient:** with CUIT, with DNI, or an unidentified end consumer (types B and C only, and below 10,000,000 ARS). From that amount, the end consumer must be identified with their DNI or CUIT. - If your client has a CUIT and you did not capture their status, Cord asks for it before issuing. - **Services:** the invoice reports the billed period (from the service dates) and the payment due date. - **Foreign currency:** Cord reports the document's frozen exchange rate if your accounting currency is ARS; otherwise, ARCA's official rate. Without an exchange rate it is not issued. ## Status before ARCA | Status | What it means | |---|---| | Authorized by ARCA | It has a CAE; the panel shows the CAE and its expiration. | | Waiting for ARCA to confirm | It was sent and Cord checks the result. | | ARCA did not authorize the invoice | Rejected, with the reason. Correct it and issue again. | | ARCA did not register this attempt | It never arrived: the number is free. | If a response is lost, Cord **checks** ARCA's last authorized document before doing anything: it never requests two CAEs for the same invoice. In ARCA's test environment the number carries the `H-` prefix and the invoice says it has no tax validity. ## Void or correct A document with a CAE **is not voided**: it is offset with a **credit note** of the same type, to the same recipient and in the same currency, associated with the invoice it adjusts. **Void invoice** takes you down that path. ## Get paid online Cord Payments does not open accounts in Argentina: online collection is with **[Mercado Pago](/en/docs/pagos/mercado-pago)**, on the quote link and the invoice link, with the methods Mercado Pago has enabled on your account. You can also record a transfer by hand. ## Plan limits | Plan | Commercial invoices per month | Documents with CAE included per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | ## What Cord does not cover yet Rejected with a message **before** requesting the CAE: - Export **type E invoice** (client outside Argentina). - **MiPyME Electronic Credit Invoice**. - **Not categorized** recipient (requires a perception). - **Withholdings** and **taxes or perceptions**. - **CAEA** and type **M** documents. ## Common problems **Settings says Coming soon.** Electronic invoicing with ARCA is being activated. Your invoices come out as commercial invoices. **The client's VAT status is missing.** Choose it on their profile: it decides whether the invoice is A or B. **ARCA requires identifying the end consumer.** The amount exceeds 10,000,000 ARS. Add the client's DNI or CUIT. **The certificate is not accepted.** It must belong to your CUIT, be valid, and be associated with the electronic invoicing service in ARCA. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Clients and statements](/en/docs/gestion/clientes) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in Brazil URL: https://docs.cordhq.app/en/docs/pagos/paises/brasil Last updated: 2026-10-13 Being activated: today you issue a standard invoice and collect with Mercado Pago. Once live, NFS-e for services and NF-e model 55 for goods. ## What it is In Brazil the document depends on **what you sell**, and the two are not mixed: - **Services → national-standard NFS-e** (NFS-e de Padrão Nacional), generated by the national NFS-e system from a declaration (DPS) signed with your certificate. - **Goods → NF-e model 55**, authorized by your state's **SEFAZ** before the goods leave, with its DANFE. Cord talks directly to each authority, without an intermediary, using **your** ICP-Brasil certificate. An invoice that mixes products and services **is not issued**: Cord asks you to split it in two. The NFS-e and NF-e are being activated: Cord turns them on country by country. Meanwhile, Settings › Tax profile says **Coming soon** in both sections and your invoices are issued as commercial invoices. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. | | In Brazil | |---|---| | Default currency | BRL (the NFS-e and NF-e are only issued in reais) | | Tax | No national rate: ISS (services) and ICMS, IPI, PIS, and COFINS (goods) per rail | | Tax ID | CNPJ / CPF, validated; accepts the alphanumeric CNPJ | | Document | Commercial invoice today; NFS-e and NF-e once activated | | Authority | National NFS-e system; your state's SEFAZ | | PDF language | Your client's or, if they have none, your account's; the NFS-e data and the NF-e DANFE, in Portuguese | | Online payments | Mercado Pago, with your own account | ## Requirements - **Plan:** Starter or higher to issue NFS-e or NF-e. On Free, commercial invoice (10 per month). - An **ICP-Brasil A1 digital certificate** for your CNPJ (e-CNPJ, `.pfx`/`.p12`), or the e-CPF if you issue as an individual. You buy it from an ICP-Brasil certification authority and pay its cost directly to them. A headquarters e-CNPJ signs for its branches (same root CNPJ), and the same certificate works for the NFS-e and the NF-e. - **NFS-e:** your municipality must have joined the national issuer. - **NF-e:** you must be **enabled (credenciado) as an NF-e issuer** with your state's SEFAZ and have your Inscrição Estadual. - **Permissions:** **Settings** for the tax profile; **Quotes** to issue; **Collections** to void. ## Taxes Brazil **starts without a national rate** on purpose: state ICMS, municipal ISS, and PIS/COFINS don't fit in a single rate, and suggesting one would be worse than letting you choose. The catalog only has **Isento**; each document's taxes are declared by its tax data (Settings and product), not by a line percentage. The tax reform (CBS 0.9% and IBS 0.1% as a 2026 trial) is not seeded either: it is not charged to those who meet the ancillary obligations. ## NFS-e: services 1. In **Settings › Tax profile**, complete your **CNPJ** under **Invoice identity**. 2. In the **NFS-e** section, complete your establishment's **municipality** (seven-digit IBGE code), the municipal registration if your municipality requires it, your **Simples Nacional status** (not opted in, MEI, or ME/EPP; for ME/EPP, the assessment regime and the approximate tax percentage), the special municipal regime if you have one, and the **service** from the national list (LC 116/2003). 3. Choose a **DPS series** exclusive to Cord (1 to 49999) and, if you want, the first number. 4. If your clients withhold ISS from you, choose the **withholding profile** from **Settings › Taxes** that represents it. 5. Upload your **ICP-Brasil A1 certificate** with its password. Cord tests the connection with the national NFS-e system when you upload it, with no effects. **How it is built.** Cord declares **one service per NFS-e**: all the invoice's line items under the configured code, and the description lists them with quantity and price. The service is provided in your municipality and **ISS is included in the price**: line items cannot add tax on top. Your municipality sets the ISS rate. The document discount travels as an unconditional discount. **Not issued yet:** services taxed where they are provided or at the client, construction works and events, exports and foreign currency, base deductions, municipal benefits, immunity or non-incidence, federal withholdings (IRRF, CSLL, PIS/COFINS, INSS), intermediaries, and the reform group (IBS/CBS). Cord rejects them before sending, with the reason. **Cancel.** **Void invoice** asks the national system to cancel the NFS-e. Outside the period or the amount your municipality allows, the cancellation is rejected with the reason and the invoice stays valid. **No credit note.** The NFS-e has none: a credit note on an NFS-e is rejected and Cord asks you to void and issue again. **Printing.** Cord's PDF accompanies the NFS-e: it prints its number, competence period, DPS, service, base, rate, and ISSQN, the full access key, and the public lookup QR code. The NFS-e XML is kept. ## NF-e: goods 1. In **Settings › Tax profile › NF-e**, complete the **tax regime** (Simples Nacional, MEI, or Regime Normal), your **Inscrição Estadual**, the establishment address with its **IBGE municipality** (your state and its SEFAZ come from it), and the CEP. 2. Under **Operation and taxes**, choose an **NF-e series** exclusive to Cord (0 to 889), the nature of the operation, how you sell, freight, and the default **PIS and COFINS CST**. 3. On each catalog product, complete the **NF-e (sale of goods)** section: NCM, CEST if applicable, CFOP, origin, unit, GTIN, your regime's ICMS (CSOSN in Simples, or rate and FCP in Regime Normal), IPI, and the IBS/CBS classification. 4. On each client, complete number, district, IBGE municipality, whether they are an **ICMS contributor** (with their IE), exempt, or a non-contributor, and whether they buy as an end consumer. 5. If you already uploaded your e-CNPJ for the NFS-e, the NF-e uses it. You can upload another one of the same CNPJ just for the NF-e. Cord checks your SEFAZ's service status when you upload it, with no effects. **What it covers.** A sale in reais to a Brazilian recipient with a CNPJ or CPF: **Simples Nacional and MEI** within the state and to other states; **Regime Normal** within the state with its own ICMS, IPI, PIS/COFINS, and IBS/CBS (mandatory for Regime Normal since August 3, 2026). ICMS, PIS, COFINS, IBS, and CBS are included in the price; **the only tax added to the line is the product's IPI**, and the NF-e total equals Cord's, to the cent. **Technical contact.** The SEFAZ of **AM, MS, PE, PR, SC, and TO** require the system developer's details. Cord does not have them yet: if your business is in one of those states, Settings tells you and the NF-e is not issued. **Contingency.** If your state's SEFAZ does not respond, Cord authorizes your NF-e on the virtual contingency service assigned to your state and returns to your SEFAZ by itself when it is back. Settings shows the notice while it lasts. **Cancellation (24 hours).** **Void invoice** cancels the NF-e within 24 hours of its authorization; the invoice panel says until when. After that, the SEFAZ rejects it and the invoice stays valid. **Correction letter.** From the invoice panel you can issue up to 20 CC-e. Each letter replaces the previous one and must repeat everything still to be corrected. A CC-e **cannot** change amounts, quantities, rates, or bases, the issuer or recipient, or the issue or shipping date. **Inutilização.** A number that Cord reserved and that never became an authorized NF-e leaves a gap in the series. Settings lists the gaps and whoever manages the tax details declares the range to the SEFAZ, with a reason. Cord never declares them by itself. **DANFE and XML.** Cord prints the A4 DANFE with the access key as a barcode and keeps the authorized XML (nfeProc), which is downloaded from the invoice and its public link. **Not issued yet:** tax substitution (ST), DIFAL to non-contributors in another state, exports, fuels, withholdings, Regime Normal to another state, returns of goods (another NF-e with purpose 4), and Simples Nacional from January 4, 2027, when its IBS/CBS group becomes mandatory without published rules yet. ## Status before the authority Each invoice's side panel says where it stands with the authority: | Status | NFS-e | NF-e | |---|---|---| | Authorized | NFS-e issued, with its number and access key | NF-e authorized by the SEFAZ, with number, series, access key, and protocol | | Waiting | Waiting for the national NFS-e system to confirm | Waiting for the SEFAZ to authorize (or confirm) | | Rejected | Did not issue the NFS-e, with the reason | The SEFAZ rejected the NF-e, with the reason; or denied its use | | Test | Test environment: no legal validity | Homologação: no legal validity | If a response is lost, Cord **checks** with the authority before doing anything: it never resends a document that may have arrived. ## Get paid online Cord Payments does not open accounts in Brazil. Online collection runs on your own Mercado Pago account: - **[Mercado Pago](/en/docs/pagos/mercado-pago)**, on the quote link and the invoice link, with the methods Mercado Pago has enabled on your account. The money lands in your Mercado Pago account. - You can also record a transfer by hand. ## Plan limits | Plan | Commercial invoices per month | NFS-e and NF-e included per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | Homologação documents do not count. ## Common problems **My invoice is not issued and says it mixes products and services.** Split it in two: services go on the NFS-e and goods on the NF-e. **Settings says my state requires data Cord does not have.** Your business is in AM, MS, PE, PR, SC, or TO, which require the technical contact. Contact us. **I can't cancel an NF-e.** More than 24 hours have passed since its authorization. Correct it with a correction letter if what changes allows it. **The municipality rejected the NFS-e.** Your municipality has not joined or has no active agreement, or the service is taxed where it is provided. The message says which. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Products and pricing](/en/docs/cotizacion/productos) - [Clients and statements](/en/docs/gestion/clientes) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in Canada URL: https://docs.cordhq.app/en/docs/pagos/paises/canada Last updated: 2026-10-13 Invoices with GST or HST plus QST, PST or RST on separate lines, validated Business Number, and card payments; pre-authorized debit in beta. ## What it is In Canada Cord issues a **standard invoice** with a sequential number. Canada has no invoice that is filed with the authority, but it does have a rule the document must follow: in Quebec, British Columbia, Saskatchewan, and Manitoba the provincial tax (**QST**, **PST**, or **RST**) is charged **together with** the 5% **GST**, not instead of it, and in the harmonized provinces **HST** is charged. Cord stores one combined rate per line item and the document splits it into its taxes. | | In Canada | |---|---| | Default currency | CAD | | Tax | GST/HST and your province's tax | | Tax ID | BN / GST/HST no., validated; separate QST number | | Document | Invoice and credit note (**Commercial invoice** in the editor) | | Authority | Not applicable to the invoice | | PDF language | Your client's or, if they have none, your account's; in French it names the taxes TPS, TVQ, and TVH | | Online payments | Card with Cord Payments; pre-authorized debit in CAD (new) | ## Requirements - **Plan:** any (Free: 10 invoices per month). - **Province or territory** in **Settings › Tax profile**: the catalog and the name of the provincial tax come from it. - **Permissions:** **Settings** for the tax profile and taxes; **Quotes** to issue. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, your **BN / GST/HST no.** (nine digits, with or without the RT0001 program account), and your address, and choose your **province or territory** in the selector. 2. If you are registered for the Quebec sales tax, enter your **QST registration number** (ten digits, TQ, and four digits). It is printed next to your GST/HST number. 3. Open **Settings › Taxes** and review your province's catalog. If you created it before choosing a province and did not touch it, Cord seeds it again when you choose one. ## Taxes by province The catalog starts with **your province's rate as the default**, **GST 5%** alone (for selling to provinces without their own tax), and the **HST** of the harmonized provinces, which is charged when selling into them. Another province's provincial tax (QST, PST, or RST) is only charged if you are registered there: add it by hand. | Business's province | Default rate | Printed as | |---|---|---| | Quebec | 14.975% | GST 5% + QST 9.975% | | British Columbia | 12% | GST 5% + PST 7% | | Manitoba | 12% | GST 5% + RST 7% | | Saskatchewan | 11% | GST 5% + PST 6% | | Ontario | 13% | HST 13% | | Nova Scotia | 14% | HST 14% | | New Brunswick, Newfoundland and Labrador, Prince Edward Island | 15% | HST 15% | | Alberta, territories | 5% | GST 5% | The rates are the CRA's since April 1, 2025 (Nova Scotia went down from 15% to 14%). An exempt or zero-rated line item uses **Zero-rated**: Cord stores the rate, not the regime, so a single 0% row covers both cases. ## How the breakdown looks The federal tax is calculated on the base and the provincial tax keeps the rest, so the sum of the two is exactly what was charged. The breakdown appears on the PDF, on the invoice link, on the quote link (also while your client reviews it live), on the printout, on the quote and invoice detail, and in the three editors. If an older quote or recurrence still had a standalone provincial rate frozen (QST 9.975%, PST or RST 7%, PST 6%), Cord reads it as the equivalent combined rate: your intention was to charge that province's tax, not to leave out the GST. ## Client and product data - **Client:** their country and, if a business, their BN or GST/HST number, validated with its check digit. You choose each line item's rate according to where you sell: Cord does not calculate tax from the client's address in Canada. - **Product:** its default rate can be any in the catalog. ## Void or correct An invoice is **voided** from its detail if it has no payments applied; with payments, it is corrected with a full or partial **credit note**, which keeps the invoice's rates and breakdown. ## Get paid online - **Card** with Cord Payments, on the quote link and the invoice link. - **Pre-authorized debit** in CAD, on the invoice link, in the client portal, and in automatic payments: turn it on with **Pre-authorized debit (Canada)** in **Settings › Payments › Payment methods**. Your client states whether they're paying as a business or an individual, the debit takes up to 5 business days to confirm, and some accounts are verified with micro-deposits. New feature: see [Bank debit](/en/docs/pagos/domiciliacion). - Outside MXN, Cord charges no platform fee. See [Fees](/en/docs/pagos/condiciones). - Your payouts arrive at your account with a **transit number**, **institution number**, and account number. See [Payouts](/en/docs/pagos/depositos). In **Settings › Payments › Payment methods**, a business in Canada sees card and pre-authorized debit: Canada has no bank transfer with a reference, and outside MXN each method says it carries no Cord fee. On the link of an invoice in CAD, your client states whether they're paying as a business or an individual before the payment form: ## Plan limits | Plan | Invoices per month | |---|---| | Free | 10 | | Starter, Pro, Scale, Developer | Unlimited | ## What Cord does not cover yet - **Automatic calculation from the client's address**: in Canada you choose each line item's rate (the calculation by address is for the United States only). - **TPS, TVQ, and TVH on the invoice link**: with a French-speaking client, the PDF names the taxes TPS, TVQ, and TVH, but the invoice link still shows them as GST, QST, and HST. - **Automatic bank transfer**: Canada has no bank transfer with a reference; a transfer is recorded by hand. ## Common problems **My invoice shows only GST on a sale in Quebec.** The line item has the 5% rate. Choose **GST 5% + QST 9.975%** on the line. **My province is not in the catalog.** Check that the province is chosen in **Settings › Tax profile**. If you had already edited your catalog, Cord does not reseed it: add the rate with **+ New tax**. **Cord rejects my QST number.** It must have ten digits, TQ, and four digits, for example 1234567890TQ0001. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [United States](/en/docs/pagos/paises/estados-unidos) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Products and pricing](/en/docs/cotizacion/productos) - [Payment methods](/en/docs/pagos/metodos) - [Bank debit](/en/docs/pagos/domiciliacion) --- # Invoicing in Chile URL: https://docs.cordhq.app/en/docs/pagos/paises/chile Last updated: 2026-10-13 DTE issued directly to the SII: invoice 33, exempt 34, credit note 61 and debit note 56, CAF folios, IVA calculated per document, PDF417 seal and assignable copy, guided certification with test set and books, exchange with acknowledgments, and collection with Mercado Pago. ## What it is In Chile each invoice is an **electronic tax document (DTE)** that must reach the **SII**. Cord issues it directly, without an intermediary provider: it takes the folio from the file the SII authorized, applies the **electronic seal**, signs it with your certificate, sends it to the SII, checks the verdict, and prints the seal (PDF417) on the PDF, with the assignable copy. Electronic invoicing with the SII is built and being activated: Cord turns it on country by country. Meanwhile, Settings › Tax profile says **Coming soon** and your invoices are issued as commercial invoices without tax validity. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. | | In Chile | |---|---| | Default currency | CLP, in whole pesos (another currency would be an export) | | Tax | IVA 19%, calculated once per document | | Tax ID | RUT, validated with its check digit (including K) | | Document | Commercial invoice today; DTE 33, 34, 56, and 61 once activated | | Authority | Servicio de Impuestos Internos (SII) | | PDF language | Your client's or, if they have none, your account's; the SII box and legends, in Spanish | | Online payments | Mercado Pago | ## Requirements - **Plan:** Starter or higher to issue DTE. On Free, commercial invoice (10 per month). - Be authorized as an **electronic issuer** before the SII (with a market system), with the resolution it assigns you. - The **digital certificate of the person** authorized before the SII to sign your documents (`.pfx`/`.p12`), issued by an accredited certification authority. You pay its cost directly to them. - The **folios (CAF)** you download from the SII per document type. - **Permissions:** **Settings** for the tax profile, folios, and certificate; **Quotes** to issue; **Collections** for credit notes. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name and your **RUT** under **Invoice identity**. 2. Under **Issuer details**, enter your **line of business (giro)** as registered, your **economic activity** codes (up to 4), your **SII office**, your comuna, city, and branch if you have one, and your resolution's **number and date** (0 in certification). 3. Under **Folios (CAF)**, upload each type's folio file exactly as downloaded from the SII. Cord checks that it belongs to your RUT and to a type it issues. 4. Under **Digital certificate**, upload the `.pfx`/`.p12`, its password, and the **certificate holder's RUT** if Cord cannot read it from the certificate. 5. On each Chilean client, enter their **giro** and **comuna**: the SII requires them on every invoice. ## Document types | Type | When | |---|---| | Electronic invoice (33) | Sale with IVA. | | Non-taxable or exempt invoice (34) | When every line item is exempt. | | Credit note (61) | Voids (CodRef 1) or corrects amounts (CodRef 3) of an accepted document. | | Debit note (56) | Charges an additional amount on an accepted document (interest, price difference) or fully voids a credit note. | The **debit note** is created from the SII panel of an accepted document (**Issue a debit note**): it starts as a draft and is issued like any invoice. Its folios come from a CAF 56. ## Taxes and IVA per document - **IVA 19%** (default) and **Exento**. IVA is calculated **once per document**, on the total net amount, as the SII format requires: Cord calculates it that way throughout the app, not only in the DTE, so what your client saw is what is declared. - **Fees withholding 15.25%** (2026): applied by whoever pays the fees receipt (boleta de honorarios), it starts as non-default and **is not issued on a DTE**: Cord rejects an invoice with withholdings. - Amounts are in **whole pesos**. ## Folios (CAF) - Each document uses one folio from a file the SII authorizes. **A used folio is never reused**, even if the document is rejected. - Invoice, debit note, and credit note folios **expire six months** after their authorization. - Settings shows how many are left of each type and warns **"request more from the SII"** when few are left: 20, or 10% of the range if greater. - A folio file none of whose folios has been used can be removed and uploaded again. ## Status before the SII | Status | What it means | |---|---| | Accepted by the SII | With its folio and submission number; if there were objections, they are listed. | | Being validated by the SII | The SII validates each submission after receiving it; Cord checks the verdict and completes the invoice by itself. | | Waiting for the SII to confirm | Cord checks the status before doing anything. | | The SII rejected the document | With the reason. The folio is used; the retry takes another one. | Once the document is accepted, the panel offers the **DTE XML** (inside a submission addressed to your client's RUT) and the **assignable copy (cedible)** of invoices 33 and 34, with the Law 19,983 receipt acknowledgment. The PDF prints the box with RUT, type, and folio, the SII office, and the PDF417 seal with the verification legend. ## Void or correct An accepted DTE **is not voided** with the SII: it is voided or corrected with a **credit note** that references it (CodRef 1 if it voids the total, 3 if it corrects amounts). A credit note is voided with a **debit note**. ## Certification with the SII If you are not an electronic issuer yet, Cord guides you through certification from **Settings › Tax profile › Certification with the SII**, while your account is in the certification environment: 1. **Test set:** paste or open the file the SII assigned you. Cord builds each case, takes certification folios, signs them, and sends them in a single submission. You check the verdict by type; with objections or rejections, the retry uses new folios. 2. **Books:** when the SII accepts the set, Cord also sends the **sales book** and the **purchase book** your set requires (in the purchase book you add each supplier's RUT). 3. **Simulation:** issue representative documents from Invoices. 4. **Exchange:** receive the documents the SII sends you and answer them (see below). 5. **Printed samples:** download each case's PDF, with its assignable copy, and upload them on the SII site. 6. **Compliance declaration:** your legal representative signs it on the SII site. The set cannot include a dispatch guide (52) or its book, export documents, or an issued purchase invoice: Cord tells you when you load the file, with its attention number. ## Exchange with acknowledgments Cord receives the DTE your suppliers send you (in your exchange mailbox or by uploading the XML) and answers them, signed with your certificate: - **Receipt acknowledgment** of the submission and of each document when it arrives. - **Result:** accepted, accepted with discrepancies, or rejected with its reason. - **Goods or services receipt** (Law 19,983) for what was received as agreed. - The same decision is **registered with the SII** (acceptance or claim) within eight calendar days. A decision cannot be changed after it is registered. ## Get paid online Cord Payments does not open accounts in Chile: online collection is with **[Mercado Pago](/en/docs/pagos/mercado-pago)**, on the quote link and the invoice link. You can also record a transfer by hand. ## Plan limits | Plan | Commercial invoices per month | DTE included per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | Test set and certification documents do not count. ## What Cord does not cover yet - **Electronic receipt (boleta, 39/41)**: a client without a RUT is rejected before taking a folio. - **Dispatch guide (52)**, **export invoice (110–112)**, and **fees receipt (boleta de honorarios)**. - **Withholdings** on the DTE. - Sales and purchase books outside certification: since 2017 the SII's Purchase and Sales Register replaces them. ## Common problems **Settings says Coming soon.** Electronic invoicing with the SII is being activated. Your invoices come out as commercial invoices. **The invoice is not issued because the client's giro or comuna is missing.** Complete them on their profile. **Settings says "request more from the SII".** Few folios of that type are left: request a new CAF from the SII and upload it. **The document stayed in validation.** The SII validates after receiving; Cord checks and completes it by itself. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Clients and statements](/en/docs/gestion/clientes) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in Colombia URL: https://docs.cordhq.app/en/docs/pagos/paises/colombia Last updated: 2026-10-13 Electronic sales invoice validated by the DIAN as your own software: enablement with a test set, numbering resolution, CUFE and QR code, exempt or excluded IVA, ReteIVA and ReteFuente, credit note, ONAC-endorsed certificate, and collection with Mercado Pago. ## What it is In Colombia each invoice must be **validated by the DIAN before it is delivered** (Technical Annex 1.9). Cord signs each invoice and credit note with your certificate, sends it to the DIAN as **your own software**, and, once the DIAN validates it, prints the **CUFE** and the QR code on the PDF. Cord is not a technology provider and does not use one: you enable yourself as an issuer with your own software and register Cord as that software. Electronic invoicing with the DIAN is built and being activated: Cord turns it on country by country. Meanwhile, Settings › Tax profile says **Coming soon** and your invoices are issued as commercial invoices without tax validity. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. | | In Colombia | |---|---| | Default currency | COP (also another currency, with the document's rate to COP) | | Tax | IVA 19% and 5%; ReteIVA and ReteFuente withholdings | | Tax ID | NIT, with its check digit | | Document | Commercial invoice today; electronic sales invoice and credit note validated once activated | | Authority | DIAN | | PDF language | Your client's or, if they have none, your account's; DIAN data and legends, in Spanish | | Online payments | Mercado Pago | ## Requirements - **Plan:** Starter or higher to issue with the DIAN. On Free, commercial invoice (10 per month). - **Enablement in the DIAN portal** as an issuer with **your own software**: the software's name and a five-digit **PIN**. The DIAN assigns you the software ID and a **test set**. - A **digital signing certificate** for e-invoicing in your NIT's name, issued by a certification authority **endorsed by the ONAC**, with its full chain. You pay its cost directly to them. - For production, a **numbering resolution** requested from the DIAN and **associated with your software**. - **Permissions:** **Settings** for the tax profile; **Quotes** to issue; **Collections** for the credit note. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, your **NIT with its check digit**, and your address under **Invoice identity**. 2. Under **Your business in the RUT**, choose the person type, your IVA responsibility, the municipality of your tax address, and your **tax responsibilities** (box 53 of the RUT). 3. Under **Software and numbering**, enter the **software ID** and its **PIN**, and the numbering: during enablement, the test set's range with its technical key; in production, your resolution (number, prefix, range, and validity). **Get from the DIAN** checks the ranges the DIAN reports for your NIT and stores the technical key. 4. Choose the credit note prefix and whether your 0% sales are **exempt** or **excluded** from IVA. 5. Upload your **signing certificate** (`.p12`, or certificate and key) with its chain. 6. During enablement, click **Send test set** with the quantities your set's detail indicates, then **Check result**. When the DIAN accepts it, switch to production from its portal. ## Taxes and withholdings - **IVA 19%** (default) and **5%**, per line item. - **Exempt or excluded:** 0% line items are reported as **exempt** (IVA 0.00) or **excluded** (no IVA) according to what you choose in Settings. Without that decision, an invoice with 0% line items is not sent. - **ReteIVA 15%** is calculated **on the IVA**, not on the subtotal, and is reported to the DIAN. **ReteFuente 2.5%** is reported as an income tax withholding. A withholding on the subtotal that could be of another kind (ReteICA, for example) is not reported, but it still subtracts from your total. - The DIAN receives the total without withholdings; Cord's total is that amount minus the withholdings. ## Documents and numbering - **Electronic sales invoice** and **credit note**, with a voiding concept if it credits the total or a reduction concept if it credits part of it. The debit note is only used in the test set. - Cord assigns each number **within your resolution** (prefix, range, and validity). Outside the range or the validity period it is not sent. Settings warns you when fewer than 50 numbers (or 5%) or fewer than 30 days of validity are left. - A rejection frees its number. - The signed XML is stored before it is sent; once validated, the DIAN's response is joined to it and it is delivered as a **container** (`AttachedDocument`) that travels in the email in a single `.zip` with the PDF. ## Status before the DIAN | Status | What it means | |---|---| | Validated by the DIAN | With its CUFE (or CUDE on a note) and the validation's notifications. | | Waiting for the DIAN to confirm | Cord checks by CUFE before doing anything. | | The DIAN rejected the document | With the reason; the number is freed. | | Enablement environment | Without tax validity. | The PDF prints the CUFE in the footer of every page and the QR code on the first one, with the numbering authorization, the payment method, and the rate to COP when applicable. ## Client data On each Colombian client's profile, in the DIAN section, enter what Cord cannot infer: document type, whether they are a natural or legal person, their IVA responsibility, and their responsibilities. Without an ID, the client is invoiced as an **end consumer**. A client abroad is reported with their country's tax ID. ## Void or correct A validated invoice **is not voided**: it is adjusted with a **credit note** that carries the invoice's buyer, currency, and rate. ## Get paid online Cord Payments does not open accounts in Colombia: online collection is with **[Mercado Pago](/en/docs/pagos/mercado-pago)**, on the quote link and the invoice link. You can also record a transfer by hand. ## Plan limits | Plan | Commercial invoices per month | Validated invoices included per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | Enablement documents do not count. ## What Cord does not cover yet - **Export** and **contingency** invoices. - **INC, ICUI, ICA**, and health taxes; reported **ReteICA**. - AIU, mandates, tips, and document charges. - **Support document (documento soporte)**, **electronic payroll**, and **RADIAN** events (receipt, acceptance). Cord rejects them or says so before sending. ## Common problems **Settings says Coming soon.** Electronic invoicing with the DIAN is being activated. **An invoice with 0% line items is not sent.** Choose in Settings whether your 0% sales are exempt or excluded. **Settings says the range ran out or the resolution expired.** Request a new resolution from the DIAN, associate it with your software, and register it in Settings. **The DIAN rejects everything because of the certificate.** The certificate must be endorsed by the ONAC, be in your NIT's name, and include its full chain. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Clients and statements](/en/docs/gestion/clientes) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in Spain URL: https://docs.cordhq.app/en/docs/pagos/paises/espana Last updated: 2026-10-14 Verifactu with your certificate and the system's responsible declaration, Facturae with IRPF, IGIC, and IPSI, AEAT e-invoicing between businesses (coming soon), series per issuer and fiscal year, exemption reasons, and collection by card or SEPA Direct Debit. ## What it is In Spain Cord issues with the invoicing system the law requires (**Verifactu**, RD 1007/2023): with Starter or higher and your electronic certificate uploaded, each invoice generates a record chained to your business's previous one, which is sent to the Tax Agency, and its PDF carries the AEAT verification QR code. Without a certificate, or on the Free plan, Cord issues **pro formas** with the `PRO` series and registers nothing with the AEAT. Each invoice issued with Verifactu is also downloadable as **Facturae 3.2.2** (with IRPF, IGIC, or IPSI) and as Factur-X, XRechnung, and Peppol; a pro forma has no electronic version. Cord has also built **e-invoicing between businesses** through the AEAT public solution, which will be activated when the AEAT publishes its service. | | In Spain | |---|---| | Default currency | EUR | | Tax | IVA; IGIC in the Canary Islands; IPSI in Ceuta and Melilla; IRPF withholding | | Tax ID | NIF / CIF (NIF, NIE, and CIF validated, with or without the ES prefix) | | Document | Invoice registered with Verifactu from Starter, with a certificate; pro forma without one or on Free | | Authority | Tax Agency (AEAT) | | PDF language | Your client's or, if they have none, your account's; legal notices and the Verifactu legend, in Spanish | | Online payments | Card, SEPA transfer with a reference, and SEPA Direct Debit (EUR) with Cord Payments | Verifactu is in beta: with your certificate uploaded, Cord registers each invoice with the AEAT, and the invoice detail shows how its submission is going. E-invoicing between businesses is still coming soon. If something looks off, contact us. ## Requirements - **Plan:** Starter or higher for Verifactu. On Free you issue pro formas (10 per month). - A valid **NIF** for your business in **Settings › Tax profile**. - A **qualified electronic certificate** (`.p12` or `.pfx`) for your business or its representative, with its password. You get it from a certification service provider (for example, the FNMT); its cost, if any, you pay directly to them. - **Permissions:** **Settings** for the tax profile and the certificate; **Quotes** to issue and correct records; **Collections** to void. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, **NIF**, address, city, province, postal code, and **invoice prefix**. If your business is in the Canary Islands, Ceuta, or Melilla, write the province (or its code: 35, 38, 51, or 52): it decides which tax is seeded. 2. Review the catalog in **Settings › Taxes**: IVA 21, 10, and 4%, exemptions with their reason, and IRPF withholdings. 3. In the **Verifactu** section, upload your electronic certificate with its password. Cord validates it, reads its expiration, and stores it encrypted. 4. Under **European e-invoicing**, complete your billing contact and, if you want, turn on **Sign the Facturae with my electronic certificate**. ## Taxes - **IVA** at 21, 10, and 4%, per line item. - **Exemptions with a reason**: Exportación (art. 21, E2), Entrega intracomunitaria (art. 25, E5), Exenta art. 20 (E1), and Inversión del sujeto pasivo (S2). The line item **freezes** the reason when you choose it, Verifactu declares it, and the PDF cites the legal provision. Plain **Exento** lets Cord derive the reason from the client: not subject outside Spain or in an intra-community transaction with an EU VAT number, exempt inside. - **IRPF withholding** at 15% or 7% (new self-employed): it is subtracted from what you collect. It is not a tax you pass on to your client. - **Canary Islands:** the catalog starts with **IGIC** at 7, 3, and 0%. **Ceuta and Melilla:** only **Exento**, because each city sets its IPSI rates; add them by hand. ## Series per issuer and fiscal year A Spanish invoice is identified by **issuer's NIF + number**, so numbering belongs to the business, not to the Cord account: - The series carries the **fiscal year** attached to the prefix and numbering starts over every year. With the prefix `F`, the first invoice of 2026 is `F2026-000001`. - If another Cord organization has your same NIF, it cannot use your same series: when you save your tax details Cord asks you to choose another one (for example `F2`) so the two never repeat a number. ## Verifactu ### What it does once activated - Each invoice generates a **registration record** with a **hash** that chains it to your business's previous invoice. The chain is never edited: not even Cord can modify a record once generated. - The PDF carries the AEAT **verification QR code** at the top, with the legend "Factura verificable en la sede electrónica de la AEAT" below it. With IRPF, "Importe total factura" (the QR's amount) and "Total a pagar" are shown separately. - Issuing **does not wait** for the AEAT: the record is generated when you issue and the submission runs afterwards, in the background. The invoice detail says how it is going. - A client without a tax ID is registered as a simplified invoice (no recipient). - An invoice in another currency is converted with the document's exchange rate if your accounting currency is EUR. ### Status before the AEAT | Status | What it means | |---|---| | Waiting to be sent to the AEAT | The record exists and will go out in the next submission. | | Registered with the AEAT | The AEAT accepted it. | | Registered with errors | The AEAT accepted it with warnings: it is worth correcting. | | Rejected by the AEAT | The AEAT did not accept it, with its code and reason. | | Could not be sent to the AEAT | The record does not pass the AEAT schema and was set aside without being sent. | ### Correct and void - **Correct and resend:** an invoice that was rejected, set aside, or registered with errors is corrected from its detail with a **correction record**. You can set the exemption reason of 0% line items; amounts never change. **Settings › Tax profile** lists the invoices to correct. - **Void:** generates a chained **cancellation record**. If the invoice never reached the AEAT, it is voided "without a previous record". - **Credit note:** a corrective invoice by differences (R1, or R5 if the original was simplified) that cites the corrected invoice. ### Responsible declaration The **responsible declaration of the invoicing system** is Cord's, as the software producer (Orden HAC/1177/2024, art. 15): you do not sign it. With Verifactu active, **Settings › Tax profile** links to it (**Responsible declaration of the invoicing system**) so you can read and print it. ### What you see in Settings When you upload your certificate, Cord confirms "Certificate uploaded. Invoices now chain into the Verifactu registry." From then on the section says **Verifactu active**, with **Certificate valid until** its expiry date and, if any invoice needs it, the **Invoices to correct** block. ## Facturae, IRPF, IGIC, and IPSI Each invoice in euros issued with Verifactu is downloadable as **Facturae 3.2.2** from its detail and from its public link, with the same amounts as the PDF (a pro forma has no electronic version): - **IRPF** as a withholding (the base and total do not change); - **IVA**, **IGIC**, or **IPSI** with its rate, and exempt or non-subject transactions with their reason; - **reverse charge** with its legal mention; - the **credit note** as a corrective invoice by differences. Signed with your certificate (XAdES) if you turn signing on; unsigned otherwise. Cord does not submit it to FACe and does not capture the DIR3 codes FACe requires yet. Factur-X, XRechnung, and Peppol do not support withholdings: an invoice with IRPF can only be downloaded as Facturae. Details in [European e-invoicing](/en/docs/pagos/factura-electronica). ## E-invoicing between businesses (AEAT) The law requires issuing and receiving e-invoices between businesses and professionals (Ley 18/2022 and RD 238/2026). Cord will send each invoice to a client established in Spain through the **free AEAT public solution** and report when you collected it. - **Status: Coming soon.** The AEAT has not published its service's technical specification yet. When it does, Cord will activate it. All you need is your certificate uploaded (the same one as Verifactu). - **Obligation dates:** October 6, 2027 for businesses invoicing more than 8 million euros a year; October 6, 2028 for everyone else; October 6, 2029 for self-employed people up to 8 million to report payment of the invoices they receive. - **Meanwhile**, each invoice's detail says whether it already has the data the AEAT requires or what is missing (for example, the client's NIF or full address). - **Does not apply** to foreign clients, and invoices with **IRPF** will be sent once the AEAT publishes how they are declared: until then, download them as Facturae. The Basque Country and Navarre depend on their regional tax authorities. ## Client and product data - **Client:** validated NIF and full address (municipality, postal code, and province) for e-invoicing between businesses; their EU VAT number if they are in another EU country (for reverse charge); their electronic address and buyer reference if they ask for them for the e-invoice. - **Line item:** its rate and, at 0%, its exemption reason. ## Get paid online - **Card** with Cord Payments. - **Bizum** in EUR, which you turn on in **Settings › Payments › Payment methods**: your customer pays from their bank's app with their phone, up to €5,000 per payment, on the invoice link, the quote's payment page, and the portal. It confirms right away and isn't saved for automatic payments. Before turning it on, the processor reviews your account: Bizum doesn't accept some lines of business, such as jewelry or gambling, and may ask a sole proprietor for their DNI or NIE. This feature is new: see [Get paid with Bizum](https://cordhq.app/en/support/cobrar-con-bizum). - **SEPA transfer with a reference** in EUR, which you turn on with **Automatic SEPA transfer** in **Settings › Payments › Payment methods**: your client transfers to an IBAN of their own (Spanish businesses get a French IBAN, because the processor doesn't issue Spanish ones; the account holder is typed exactly as shown), with a reference per payment, and Cord reconciles it on its own. It's offered on the invoice link and the quote's payment page if the document has a linked client. This feature is new: see [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). - **SEPA Direct Debit** in EUR, which you turn on in **Settings › Payments › Payment methods**: each debit takes up to six business days to confirm and the account holder can return it for eight weeks. This feature is new. - Your payouts arrive at your **IBAN**, validated with its check digits. See [Payouts](/en/docs/pagos/depositos). ## Plan limits | Plan | Pro formas per month | Invoices registered with Verifactu per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | ## What Cord does not cover yet - **Verifactu with IGIC, IPSI, or equivalence surcharge:** today it registers invoices with IVA; an invoice from the Canary Islands or Ceuta and Melilla cannot be registered. - **FACe** and the public administration's DIR3 codes. - **E-invoicing between businesses** until the AEAT publishes its service, and with IRPF until it publishes how it is declared. ## Common problems **I uploaded my certificate and still issue pro formas.** Check your plan (Starter or higher), that the section says **Verifactu active**, and that **VERI\*FACTU**, not **Pro forma**, is selected in **Document type**. **Cord asks me for another series when saving my tax details.** Another organization with your same NIF already uses that series. Choose a different one so numbers are not repeated. **My Canary Islands invoice shows IGIC and cannot be registered.** Verifactu in Cord registers invoices with IVA today. Download it as Facturae. **The AEAT rejected an invoice.** Open it and click **Correct and resend**: Cord generates the correction. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [European e-invoicing](/en/docs/pagos/factura-electronica) - [Tax invoicing](/en/docs/pagos/facturacion) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Payment methods](/en/docs/pagos/metodos) - [Payouts to your bank](/en/docs/pagos/depositos) --- # Invoicing in the United States URL: https://docs.cordhq.app/en/docs/pagos/paises/estados-unidos Last updated: 2026-10-13 Invoices with sales tax by state or by your client's address (beta, from Starter), exempt clients, validated EIN, and card payments; ACH debit in beta. ## What it is In the United States there is no tax invoice filed with an authority: Cord issues a **standard invoice** with a sequential number, each line item's sales tax, and both parties' details. What does change by place is **sales tax**, which is the sum of the state, county, city, and special district rates. Cord gives you two ways to charge it: - **Catalog rate:** your state's base rate, seeded when you declare your state, plus any you add by hand. - **Sales tax by address** (from Starter): each line item takes the combined rate of the client's address, with one row per jurisdiction, and the sale is recorded for your filing. | | In the United States | |---|---| | Default currency | USD | | Tax | Sales tax by state; combined by address from Starter | | Tax ID | EIN / Tax ID, validated (nine digits and an assigned prefix) | | Document | Invoice and credit note (**Commercial invoice** in the editor) | | Authority | Not applicable to the invoice; you file sales tax in each state | | PDF language | Your client's or, if they have none, your account's | | Online payments | Card, ACH or wire transfer with a reference, and ACH bank debit (USD) with Cord Payments | ## Requirements - **Plan:** any to invoice (Free: 10 invoices per month). **Starter or higher** for sales tax by address. - **Your state** in **Settings › Tax profile**: the starter catalog comes from it. - For sales tax by address: an **active Cord Payments account**, your complete address, and the states where you have a permit to collect. - **Permissions:** **Settings** for the tax profile and taxes; **Quotes** to issue; **Collections** to void and credit. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, EIN, address, city, **state** (a selector with the 50 states and D.C.), ZIP, and invoice prefix. 2. Open **Settings › Taxes**. If your catalog is empty, click **Add the base rate** for your state: Cord adds `Sales tax %` and **Exempt / Resale**. 3. If you will use sales tax by address, first activate your account in **Settings › Payments › Account** and continue with the section below. ## Catalog sales tax The seeded rate is the **minimum statewide rate**: the state rate plus the local tax the law makes mandatory across the state (that is why California is 7.25% and not 6%). It does not include county or city. A state with no statewide sales tax (Oregon, Montana, New Hampshire, Delaware, Alaska) only gets **Exempt / Resale**: Cord does not make up a 0% consumption tax. If you don't use the calculation by address, adjust the rate with your accountant to your location's and add those of other jurisdictions where you sell. Sales tax calculated from the client's address is new. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. ## Sales tax from the client's address With **Calculate sales tax from the client's address** on in **Settings › Taxes**, each line of a quote or invoice for a client in the United States takes the combined rate of their address: state, county, city, and special districts. The calculation uses **your** registrations, not Cord's: you are the one registered with each state, who collects, and who files. 1. In **Settings › Taxes**, section **Sales tax by address**, enter your **business address** in full (street, city, state, and ZIP). 2. Choose **what you sell**: general services, general tangible goods, software as a service for business use, or general electronically supplied services. It decides whether a state taxes it. 3. Check the **states where you collect sales tax**, only those that gave you a permit. 4. Turn the switch on and click **Save**. If something is missing (plan, payments account, address, or at least one state), the screen says what, and the switch does not stay on. ### What the document prints - **One row per jurisdiction** on the PDF, the client's link, the preview, and the detail: for example, California 6%, Los Angeles County 0.25%, and the special districts. The sum is exactly the tax charged. - The line item column shows the **combined legal rate** (9.5% in that example). - **State where you don't collect:** the line carries 0% and the document says "No obligation to collect sales tax in Texas". It is not an error. - **Sale the state does not tax** (for example, a service where services pay no sales tax): the line carries 0% and the document says "Not subject to sales tax in" that state. - **Exempt client:** the line carries 0% and the document cites their certificate. - The rate and breakdown are **frozen** on the document: if your client changes address later, what was issued is not recalculated. ### When the document is not saved The calculation **fails closed**: if it cannot be calculated with certainty, the quote or invoice is not saved and the editor tells you what is missing, instead of using an estimated rate. It happens when: - the client has no state or no five-digit ZIP (street and city improve accuracy); - the address cannot be located; - the client is marked exempt without a certificate, or with an expired certificate; - the document has more than 100 line items; - you have no active payments account, your address is incomplete, or you checked no state; - the calculation is not available at that moment or a usage limit was reached. A draft without a client uses the catalog rate; to send it you need a client. ### Exempt clients On the client's profile, section **Sales tax exemption** (US businesses only), mark the client as exempt (resale, nonprofit, government) and enter their **certificate**: number, issuing state, and expiration. Without a certificate number the exemption is not saved; with an expired certificate, the document is not saved. ### The recorded sale Each **issued invoice** and each **paid quote** in a state where you collect is recorded once for your sales tax filing. A quote and the invoice that comes from it are the same sale: they are recorded only once. Voiding an invoice reverses its whole sale, unless that sale is already paid on its quote. ### Quota and overage | Plan | Invoices with automatic sales tax per month | Each additional one | |---|---|---| | Free | Not included | Not available | | Starter | 10 | 0.75 USD · 15.00 MXN · 0.70 EUR | | Pro | 25 | 0.75 USD · 15.00 MXN · 0.70 EUR | | Scale | 60 | 0.75 USD · 15.00 MXN · 0.70 EUR | | Developer | 150 | 0.75 USD · 15.00 MXN · custom in EUR | - Each sale recorded in a state where you collect counts once. Previews do not count, a sale to a state where you don't collect does not either, and voiding an invoice does not give the unit back. - The price of an additional one is charged in your Cord subscription's currency. - Today that overage is not billed yet: when you reach the included amount, Cord asks you to upgrade your plan or enter the rate by hand. A sale that arrives without quota is not lost: it waits and is recorded automatically when your quota renews or you upgrade, and **Settings › Plans & subscription** says how many are waiting. - Cord covers the cost of the calculation; your plan only counts recorded sales. Details in [Your Cord subscription](/en/docs/cuenta/suscripcion). ## Client and product data - **Client:** country United States, state and five-digit ZIP (required for the calculation by address), street and city recommended, optional EIN, and, if applicable, their exemption with a certificate. - **Product:** it carries no sales tax classification of its own: classification is one per business (what you chose in **What you sell**). ## Void or correct An invoice is **voided** from its detail if it has no payments applied; with payments, it is corrected with a full or partial **credit note**. Voiding an invoice with sales tax by address reverses its recorded sale. ## Get paid online - **Card** with Cord Payments on the quote link and the invoice link. - **Bank transfer with a reference** in USD, which you turn on with **Automatic ACH and wire** in **Settings › Payments › Payment methods**: your client transfers by ACH or domestic wire (never international) to an account and routing number of their own, with a reference per payment, and Cord reconciles it on its own. It's offered on the invoice link and the quote's payment page if the document has a linked client. This feature is new: see [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). - **ACH bank debit** in USD: you turn it on in **Settings › Payments › Payment methods**. It takes up to four business days to confirm and only supports full refunds. This feature is new. - Outside MXN, Cord charges no platform fee. See [Fees](/en/docs/pagos/condiciones). - Your payouts arrive at your account with a **routing number (ABA)**, validated with its check digit, and an account number. See [Payouts](/en/docs/pagos/depositos). In **Settings › Payments › Payment methods**, the transfer (**Automatic ACH and wire**) and the bank debit (**ACH bank debit**) are two separate switches: you can offer one without the other. Here the transfer is active and the debit is off. On the link of an invoice in USD, your client chooses **Bank transfer** and sees a routing number (ABA) and account number of their own, with no SWIFT: On the quote's payment page, the deposit, the balance, or each installment has its own reference, and your client can send the instructions to their email with **Email these to me**: ## What Cord does not cover yet - **Filing reports** for sales tax: Cord records each sale, but does not show you the report by state yet. - **Partial credit note** on an invoice with sales tax by address: it copies the breakdown to print it, but does not partially reverse the recorded sale. - **Classification by product:** today it is one per business. - The API and the MCP server do not expose the client's exemption or the breakdown by jurisdiction (the documents they create do calculate by address). ## Common problems **My catalog is empty.** Add your state in **Settings › Tax profile** and go back to **Settings › Taxes** to add the base rate. **I can't turn on the calculation by address.** The screen says what is missing: Starter plan or higher, an active payments account, a complete address, or at least one state. **My quote is not saved and says the ZIP is missing.** The client needs a state and a five-digit ZIP on their profile. **A line came out at 0%.** The client is in a state where you did not check that you collect, or is exempt. The document says so in its notes. **I reached my plan's quota.** Upgrade your plan, or turn the automatic calculation off and enter the rate by hand until next month. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Clients and statements](/en/docs/gestion/clientes) - [Payment methods](/en/docs/pagos/metodos) - [Connect account (KYC)](/en/docs/pagos/onboarding) - [Your Cord subscription](/en/docs/cuenta/suscripcion) --- # Invoicing in France URL: https://docs.cordhq.app/en/docs/pagos/paises/francia Last updated: 2026-10-13 Invoice in French with TVA per line item and the reform's mentions (transaction category, client SIREN, VAT on debits option, delivery address), Factur-X, issuing through an approved platform with statuses 200 to 213, e-reporting, and collection by card or SEPA. ## What it is In France Cord issues an invoice in **French** (with your client's language alongside if they have another), with each line item's TVA and **the mentions the e-invoicing reform requires**, downloadable as **Factur-X** (the PDF with the XML inside), which is also what the email carries by default. The reform also requires invoices between businesses established in France to travel through an **approved platform** (PA) and sales to consumers and with other countries to be **reported** (e-reporting). Cord has built issuing through a platform: it issues, reports, and communicates your payments from the invoices you already issue. It is being activated. | | In France | |---|---| | Default currency | EUR | | Tax | TVA | | Tax ID | SIREN / N° TVA (SIREN, SIRET, and TVA validated) | | Document | Invoice with Factur-X; transmitted through an approved platform once activated | | Authority | Approved platform and the tax administration (DGFiP) | | PDF language | French; with a client in another language, French with the client's alongside | | Online payments | Card, SEPA transfer with a reference, and SEPA Direct Debit (EUR) with Cord Payments | Issuing through an approved platform is built and being activated: meanwhile, Settings says **Coming soon** and your invoices already carry the reform's mentions. European e-invoicing is also new. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. ## Requirements - **Plan:** any to invoice with Factur-X (Free: 10 invoices per month). **Starter or higher** to register with the platform. - Your **SIREN** (or your TVA number, which contains it) in **Settings › Tax profile**. - Your **reception platform**: since September 1, 2026 every business established in France must be able to receive e-invoices, and Cord **only issues**. - **Permissions:** **Settings** for the tax profile and registration; **Quotes** to issue. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, your **SIREN / N° TVA**, address, and invoice prefix. If you apply the franchise, turn on **VAT small-business exemption (art. 293 B du CGI)**. 2. Under **E-invoicing in France**, choose your **VAT regime**, the **nature** of hand-typed line items (goods or services), and, if you have it, the **option to pay VAT on debits**. 3. In the catalog, choose each product's **type**: a product is a supply of goods; a service, subscription, or license is a supply of services. 4. On each French business client, enter their **SIREN** (or SIRET). 5. When issuing through the platform is active, click **Register with the platform** and follow the mandate step. ## Taxes - **TVA 20%** (default), **10%**, **5.5%**, and **2.1%**, per line item. - **Exonéré de TVA** for exempt transactions; on the exempt profile you can choose its e-invoice classification. - **Franchise (art. 293 B du CGI):** with the option on, your tax-free invoices carry the legal notice that explains it. ## The reform's mentions Every French invoice from Cord carries them, whether or not the platform is active: - **Transaction category:** supply of goods, supply of services, or mixed, according to each product's type or, for hand-typed line items, your profile's default nature. Without it, the invoice is written as before the reform and cannot be transmitted. - **Option for debits:** if you have it, the invoice prints "Option pour le paiement de la taxe d'après les débits" (services only). - **Client SIREN:** a SIRET travels as the identifier and its SIREN as the legal registration. - **Delivery address:** in the invoice editor (France only), when goods are delivered somewhere other than the client's address. It is not declared for a supply of services. - **Business-to-business conditions:** late payment penalties, the flat collection cost indemnity, and early payment discount conditions (art. L441-9 and L441-10 of the Commercial Code). ## Issuing through an approved platform ### What Cord does | Transaction | What Cord does | Payments | |---|---|---| | Between businesses established in France, client with SIREN | Transmits the Factur-X through the platform | If TVA is due on payment, reports each services payment as status 212 "Encaissée" | | With a business established outside France | Reports the invoice (e-reporting), one by one | Reports its payments | | To consumers | Reports the summary of each closed day, by currency and category | Reports what was collected that day | Only payments for **services** are reported, without the option for debits. A refund is reported as a negative amount with its reason. ### Register 1. In **Settings › Tax profile › E-invoicing in France**, check your SIREN, regime, email, and address: Cord creates your registration with that data. 2. If you want, enter the **legal representative** (first name, last name, and position) and click **Register with the platform**. 3. Click **Verify identity and sign the mandate with Iopole**, the approved platform Cord issues through, and complete the identity verification and the mandate there. 4. Come back to Cord and click **Refresh status**. When registration is complete, the section says **Registration complete: Cord issues and reports for you**. An invoice issued before registration is complete is not transmitted; the invoice detail says so. ### E-reporting deadlines | VAT regime | Transactions | Payments | |---|---|---| | Standard regime, monthly | By ten-day periods: 1–10, on the 20th; 11–20, on the last day of the month; 21–end, on the 10th of the next month | Month, on the 10th of the next month | | Standard regime, quarterly | Month, on the 10th of the next month | Month, on the 10th of the next month | | Simplified | Month, on the last day of the next month | Same | | Franchise | Two months, on the last day of the next month | Same | Cord sends each day as soon as it closes; Settings counts what is queued, unconfirmed, or past its deadline. ### Invoice statuses Each invoice's **E-invoicing platform** panel says how the reform treats it (transmitted or reported), how its submission is going, and each status the platform reported, with its date and reason: | Code | Status | |---|---| | 200 | Submitted to the platform | | 201 | Issued by the platform | | 202 | Received by the client's platform | | 203 | Made available to the client | | 204 | Acknowledged by the client | | 205 / 206 | Approved by the client (fully or partially) | | 207 | Disputed by the client | | 208 / 209 | Suspended: the client asks for supporting documents / Completed | | 210 | Refused by the client | | 211 / 212 | Payment sent / Payment received | | 213 | Rejected by a platform | | 501 | File not accepted by the platform | **A rejected invoice (210 or 213) is not corrected:** cancel it with a credit note (it is not transmitted: it is an accounting cancellation) and issue a new one with the right data. Nothing is corrected automatically. ## Client and product data - **Client:** SIREN or SIRET (validated with its check digit), their VAT number if they are in another EU country, and their electronic address if they have one. - **Product:** its **type** (product, service, subscription, or license) decides the transaction category. - **Invoice:** the delivery address when applicable. ## Get paid online - **Card** with Cord Payments. - **SEPA transfer with a reference** in EUR, which you turn on with **Automatic SEPA transfer** in **Settings › Payments › Payment methods**: your client transfers to an IBAN of their own (the account holder is typed exactly as shown), with a reference per payment, and Cord reconciles it on its own. It's offered on the invoice link and the quote's payment page if the document has a linked client. This feature is new: see [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). - **SEPA Direct Debit** in EUR, which you turn on in **Settings › Payments › Payment methods**. This feature is new. - Your payouts arrive at your **IBAN**. See [Payouts](/en/docs/pagos/depositos). ## Plan limits | Plan | Invoices per month | Issuing through the platform | |---|---|---| | Free | 10 | Not included | | Starter, Pro, Scale, Developer | Unlimited | Included once activated | ## What Cord does not cover yet - **Receiving** invoices from your suppliers: you need your reception platform. - **Correcting a report** (e-reporting) already sent: not possible from Cord. - **Voiding with the platform** an invoice already transmitted: it is corrected with a transmitted credit note. - Invoices with withholdings, self-billing, multi-vendor, down payments, and the margin scheme: not issued through the platform. ## Common problems **The invoice says the transaction category is missing.** Choose the product's type or the default nature of hand-typed line items in **Settings › Tax profile**. **My invoice says "Not transmitted by Cord".** It was issued before your registration with the platform was complete. **The platform rejected an invoice.** Cancel it with a credit note and issue a new one with the right data. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [European e-invoicing](/en/docs/pagos/factura-electronica) - [Germany](/en/docs/pagos/paises/alemania) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Products and pricing](/en/docs/cotizacion/productos) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in Mexico URL: https://docs.cordhq.app/en/docs/pagos/paises/mexico Last updated: 2026-10-14 CFDI 4.0 stamped with your CSD: PUE or PPD with payment complement, global invoice, replacement with reason 01, SAT keys per line item, CFDI to foreign clients, taxes and withholdings, cancellation, and collection by card, SPEI, or Mercado Pago. ## What it is In Mexico Cord issues **CFDI 4.0** stamped with the SAT through an authorized certification provider, **under your RFC and with your Digital Seal Certificate (CSD)**. You upload the CSD once and from then on every invoice, credit note, and payment complement is stamped in your name. On the Free plan, and when you choose the commercial option, Cord issues a **pro forma** with the `PRO` series, which does not replace a CFDI. | | In Mexico | |---|---| | Default currency | MXN (you can invoice in another currency with an exchange rate) | | Tax | IVA, with IVA and ISR withholdings | | Tax ID | RFC, validated with its check digit | | Document | CFDI 4.0 income, expense (credit note), and payment (complement) | | Authority | SAT, through an authorized certification provider | | PDF language | Your client's or, if they have none, your account's; the stamped CFDI PDF, in Spanish | | Online payments | Card (also in interest-free installments) and SPEI with Cord Payments, and Mercado Pago | ## Requirements - **Plan:** Starter or higher to stamp. On Free you issue pro formas (10 per month). - A **valid CSD** for your RFC: the `.cer` and `.key` files and the key password. You obtain it from the SAT; Cord does not issue it. - **Complete tax details** in **Settings › Tax details**: RFC, legal name, tax regime, and issuing zip code. - **Permissions:** **Settings** to upload tax details and the CSD; **Quotes** to create and issue invoices; **Collections** to record payments, void, replace, and issue credit notes. ## Set up your account 1. Open **Settings › Tax details** and complete **Tax identification**: RFC, legal name exactly as on your certificate, tax regime, issuing zip code, and default CFDI use. 2. Under **Digital Seal Certificate (CSD)**, upload your `.cer` and `.key`, type the key password, and click **Upload CSD and connect**. The password is only used to decrypt the key: Cord does not store it. 3. Review your catalog in **Settings › Taxes**: Cord seeds it with IVA 16%, IVA 8% for the border region, Exento, and the most common withholdings. 4. Classify your products in **Products**, section **E-invoicing (SAT, Mexico)**, with their product or service key and their unit key. 5. Complete each client's tax details on their profile: RFC, tax regime, CFDI use, and tax zip code. ## Taxes and withholdings | Seeded profile | Rate | How it is calculated | |---|---|---| | IVA 16% | 16% | Transferred on each line item's base. It is the default. | | IVA 8% región fronteriza | 8% | Border region incentive, valid until December 31, 2026: check that it still applies before using it in 2027. | | Exento | 0% | Exempt line item: it transfers no IVA. | | Retención IVA 10.6667% | 10.6667% | Two thirds of the 16% IVA, only on the **taxed** amount: an exempt line item is not part of the base. | | Retención ISR 1.25% | 1.25% | On the subtotal (RESICO). | | Retención IVA 4% (autotransporte) | 4% | Road freight transport, on the taxed amount. | | Retención IVA 6% (servicios de personal) | 6% | Staffing services, on the taxed amount. | Cord sends the SAT the taxes of **each line item** as you captured them, not a single rate. Withholdings marked as default are subtracted from the total. If you invoice in another currency, the CFDI declares the exchange rate frozen when the quote was made. ## Recipient details Cord takes the client's tax details from their profile and does not make them up: | Data | If missing | |---|---| | RFC | Stamped with the generic RFC XAXX010101000, in the client's name, with regime 616 and your business's zip code. | | Tax regime | 601 (General de Ley Personas Morales) if the client has an RFC. | | CFDI use | Your account's, or G03 (General expenses). | | Tax zip code | There is no substitute: the SAT may reject the stamping. | The defaults may not match your client's tax certificate. Complete them before issuing so the CFDI is useful to your client. ### Foreign clients If the country on the profile is not Mexico, the CFDI is issued to a **foreign resident**: generic RFC XEXX010101000, their tax residence (the profile's country), use **S01**, and, if you captured it, their tax ID (EIN, NIF, VAT) as the tax registration number. You decide each line item's rate with your accountant; services exports usually go at 0%. SAT keys per line item, CFDI to foreign clients, the global invoice, and CFDI replacement are new. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. ## SAT keys for each line item - Each product carries its **product or service key** (c_ClaveProdServ, 8 digits) and its **unit key** (c_ClaveUnidad). The product key is searched by description in the SAT catalog; the unit key, if left empty, is derived from the product's unit (hour → HUR, month → MON, kg → KGM). - In the invoice and quote editors, **each line item can carry its own keys**, which take precedence over the product's. Duplicating a document keeps them. - A line item with no keys of its own and no classified product is stamped with the generic **01010101** and **H87**, and the editor tells you how many are left that way before you issue. - A key with an invalid format is rejected when saving, naming the line item. ## Payment method: PUE, PPD, and payment complement Cord decides the method when stamping, using the invoice's actual payments: - **PUE (single payment)** when the invoice is already fully paid at issuance, with the payment form of the charge (credit card 04, debit card 28, transfer 03, cash 01, check 02). You can set the form by hand in the editor; it only applies to a PUE. - **PPD (installment or deferred payment)** with form 99 when the invoice is issued before it is paid. - For each payment you record on a PPD CFDI, Cord automatically stamps a **payment complement (CFDI type P)** related to the invoice. You see it in the invoice's activity. - A CFDI to "público en general" (generic RFC) is always stamped PUE: it does not accept a complement. If the payment is in another currency, the complement needs the official exchange rate of the payment date, and if the payment predates the invoice it is an advance, which the SAT documents with another procedure. In both cases Cord does not stamp it and the invoice's activity says why: issue it with your accountant. If a complement could not be stamped for another reason (for example, your plan's quota), contact us to retry it. Each payment complement counts as one tax document of your monthly quota. ## Invoice status On the invoice detail you see the **tax folio (UUID)** the SAT assigned, each line item's keys, taxes by rate, the amount paid, and the balance. The activity records issuance, sending, when the client opened it, and each payment. The PDF and XML are downloaded from the invoice and from its public link. ## Global invoice to the general public Sales that were paid without the client asking for an invoice are documented in **Invoices › Global invoice**: 1. Choose the **periodicity** (daily, weekly, fortnightly, monthly, or bimonthly; bimonthly only with regime 621), the **month**, and the **year**. For short periodicities, also choose the range of days. 2. Review the list: Cord shows the quotes **paid** in the period that have no invoice of their own or another global invoice, and says why it excludes the rest (another currency, withholdings, foreign client, or a rate other than 0, 8, or 16%). 3. Adjust the payment form if needed (by default, the one of the largest sale) and issue. The global invoice is stamped to PUBLICO EN GENERAL (XAXX010101000, regime 616, use S01, method PUE), with one line item per sale and per rate: key 01010101, unit ACT, and the sale's number as the identification number. A sale included in a valid global invoice cannot be invoiced separately: if the client asks for their invoice, cancel the global invoice with reason 04 and issue it again without that sale. ## Cancel, replace, and credit **Cancel.** When you void a CFDI, Cord asks for the **SAT reason**: | Reason | When | |---|---| | 02 | Document issued with errors, without a relation. | | 03 | The transaction did not take place. | | 04 | Nominative transaction related in a global invoice (global invoice only). | | 01 | Document with errors with a relation: used with **Replace CFDI**. | A cancellation request does not void the CFDI until the SAT confirms it. Meanwhile the invoice says it is in progress and you can click **Check cancellation status**. An invoice with payments applied is not voided: it is corrected with a credit note. **Replace CFDI (reason 01).** From the invoice, **Replace CFDI** creates a draft with the original's data so you can correct what is needed. When you issue it, Cord relates it to the original (relation 04), moves the original's payments to it, and requests cancellation of the original with reason 01 and the replacement's UUID. An invoice with valid credit notes or issued payment complements cannot be replaced: the SAT does not allow canceling a CFDI with valid related documents. **Credit note.** It is an expense CFDI related to the original UUID (relation 01), with use G02 when the client has an RFC. It keeps the original line items, rates, and withholdings; it can be full or partial. **Refund.** Refunding an invoice's online payment from Cord doesn't cancel or change the CFDI or its payment complement: document the return with a credit note. While there is refunded money without a note that covers it, the invoice detail reminds you. See [Refunding an invoice payment](/en/docs/pagos/reembolsos#refunding-an-invoice-payment). ## Get paid online - **Card** with Cord Payments, on the quote link and on the invoice link. - **Interest-free installments (MSI)** with a Mexican credit card, if you turn them on: your customer picks the term when paying in MXN and you receive the full amount in your payout; each term has an additional cost deducted from that payment. They don't apply to automatic payments. See [Interest-free installments](https://cordhq.app/en/support/msi-meses-sin-intereses). - **Automatic SPEI** for **MXN** payments on the quote and on the invoice link: each quote payment and each invoice has its own CLABE and reconciles by itself. A PPD invoice paid by SPEI gets its payment complement with form 03. On invoices it's a new feature: see [SPEI on the invoice link](/en/docs/pagos/metodos#spei-on-the-invoice-link). - **Mercado Pago**, as an alternative on the same page. - The Cord Payments fee applies to MXN payments; each month Cord issues you its own CFDI for that fee. See [Fees](/en/docs/pagos/condiciones). - Your payouts arrive at your **CLABE** account, validated with its check digit. See [Payouts](/en/docs/pagos/depositos). In **Settings › Payments › Payment methods**, a business in Mexico sees card, **Interest-free installments (MSI)** (which depends on card), and **Automatic SPEI transfer**, each with its MXN fee, and under **Other processors**, Mercado Pago. Bank debit isn't offered in MXN. On the link of an invoice in MXN, when your client chooses SPEI they see that invoice's own CLABE and the payment reference: ## Plan limits | Plan | Pro formas per month | CFDI included per month | |---|---|---| | Free | 10 | No stamping included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | Each income CFDI, credit note, payment complement, and global invoice counts once. From Starter, additional ones are billed as overage. See [Your Cord subscription](/en/docs/cuenta/suscripcion). ## What Cord does not cover yet - **Foreign Trade complement.** The definitive export of goods (key A1) requires it; Cord stamps the export as "Not applicable" and does not issue that complement. - **IEPS** and the taxed zero rate as a classification of its own: Cord does not infer them from a percentage. - **Payment complement in another currency and advances**: documented outside Cord, as explained above. - **Automatic cancellation response from the recipient**: checking the cancellation status is manual, with **Check cancellation status**. ## Common problems **My invoice came out as a pro forma.** Check your plan (Starter or higher), that your CSD is uploaded and valid, and that you did not choose the commercial option when issuing. **My client says their CFDI is not usable.** Check the tax regime, tax zip code, and CFDI use on their profile; if they were missing, Cord used defaults. Correct them and replace the CFDI with reason 01. **The editor says some line items have a generic key.** Assign the key on the product or on the line item before issuing. **I can't replace an invoice.** It has valid credit notes or issued payment complements. Cancel those documents first or contact us. **The cancellation is still in progress.** In some cases the SAT waits for the recipient's acceptance. Click **Check cancellation status** to see the status. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Digital Seal Certificate](/en/docs/cuenta/csd) - [Approval and invoicing](/en/docs/cotizacion/timbrado) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Tax invoicing](/en/docs/pagos/facturacion) - [Payment methods](/en/docs/pagos/metodos) - [Mercado Pago](/en/docs/pagos/mercado-pago) --- # Invoicing in Peru URL: https://docs.cordhq.app/en/docs/pagos/paises/peru Last updated: 2026-10-13 Electronic invoice and credit note sent directly to SUNAT (taxpayer's SEE) with CDR, QR code, and hash value: F series, exempt or non-taxable IGV, MYPE rate, reported IGV withholding, payment method, what is not covered (boleta), and collection with Mercado Pago. ## What it is In Peru each invoice is sent to **SUNAT**, which accepts it with a **receipt record (CDR)**. Cord sends it **directly** as your issuing system (taxpayer's SEE), without an OSE or PSE: it signs it with **your** digital certificate, sends it with your secondary SOL user, and prints the QR code and the hash value (valor resumen) on the PDF. Electronic invoicing with SUNAT is built and being activated: Cord turns it on country by country. Meanwhile, Settings › Tax profile says **Coming soon** and your invoices are issued as commercial invoices without tax validity. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. | | In Peru | |---|---| | Default currency | PEN | | Tax | IGV 18%; exempt (exonerado) and non-taxable (inafecto); MYPE rate | | Tax ID | RUC, validated with its prefix and check digit | | Document | Commercial invoice today; electronic invoice (01) and credit note (07) once activated | | Authority | SUNAT | | PDF language | Your client's or, if they have none, your account's; SUNAT data and legends, in Spanish | | Online payments | Mercado Pago | ## Requirements - **Plan:** Starter or higher to issue with SUNAT. On Free, commercial invoice (10 per month). - In **SUNAT Operaciones en Línea**: enroll as an electronic issuer from your own systems (taxpayer's SEE), **register your digital certificate**, create a **secondary SOL user** with the profile for sending receipts, and reserve an **F series** for Cord. - A **digital certificate** in your RUC's name (`.p12`/`.pfx`, or certificate and key). Its cost, if any, you pay directly to whoever issues it. - **Permissions:** **Settings** for the tax profile; **Quotes** to issue; **Collections** for the credit note. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name and your **RUC** under **Invoice identity**. 2. Under **Electronic invoicing with SUNAT**, choose your **invoice series** (for example F001) and, if you already issued in it from another system, the **last number**, so Cord continues after it. Do the same for credit notes. 3. Choose **what you sell**, whether your line items without IGV are **exempt (exonerado)** or **non-taxable (inafecto)**, and your establishment code. 4. Check what applies: the **MYPE** regime for restaurants and hotels, SPOT detractions, perception agent, or that your clients do not withhold IGV from you. List the **RUC of your clients that are withholding agents**. 5. Save your **secondary SOL user** (without the RUC) and its password. Cord tests them with a query that has no effects. 6. Upload your **digital certificate**. ## Taxes - **IGV 18%** (default). An invoice carries a single IGV rate. - **Exonerado** and **Inafecto** are different things: exonerado is SUNAT's term for an exempted transaction; inafecto, one outside the scope of the tax. Cord declares your 0% line items according to what you indicate in Settings; it never guesses. - **MYPE regime** for restaurants, hotels, and tourist lodging (Laws 31556 and 32219): only if you declare it in Settings, with the rate published for the year: **10.5% in 2026** and **15% in 2027**. Without a published rate for the year, it is not accepted. - The catalog has no "IGV withholding": the withholding is applied by your client, not by you (see below). ## IGV withholding The IGV withholding is applied by **the client** that SUNAT designated as a **withholding agent**, when paying you. You **report** it on the invoice: - List in Settings the RUC of your clients that are withholding agents (or mark yourself as excluded if no one withholds from you). - On a **taxed, credit sale above S/ 700** to one of those clients, the invoice reports the **3% withholding** of the total, and the **net amount pending** deducts it. - In another currency, Cord needs the document's frozen exchange rate to soles; without it, it is not sent. - The invoice total does not change: the withholding is reported, not subtracted. ## Payment method Each invoice declares its payment method: **cash (contado)**, or **credit (crédito)** with the net amount pending and the installment with its due date (from the invoice's due date), minus what has already been collected. The amount in words ("SON: …") is also printed. ## Status before SUNAT | Status | What it means | |---|---| | Accepted by SUNAT | With its receipt record and its hash value; if there were observations, they are listed. | | Waiting for SUNAT to confirm | Cord checks the status before doing anything: it never resends in production. | | SUNAT did not accept the invoice | Rejected, with the reason; the number was used and the next attempt takes another one. | | Test service (beta) | Without tax validity. | The PDF prints the RUC, the series and number, the buyer, the transactions by tax treatment, the IGV, the total, the payment method, the withholding if applicable, the hash value, the printed representation legend, and the QR code. The accepted XML is downloaded from the invoice and from its public link. ## Void or correct A cancellation notice (comunicación de baja) only applies to invoices not delivered to the client, and Cord delivers the invoice when issuing it. That is why an accepted invoice **is offset with a credit note**: type **01 (voiding of the transaction)** if it credits the full amount, or **09 (decrease in value)** if it credits part of it. The credit note shares the invoice series with its own numbering. ## Clients abroad A client outside Peru is an **export**: it is reported with their tax ID, as an export of goods or of services (with the country of use). ## Get paid online Cord Payments does not open accounts in Peru: online collection is with **[Mercado Pago](/en/docs/pagos/mercado-pago)**, on the quote link and the invoice link. You can also record a transfer by hand. ## Plan limits | Plan | Commercial invoices per month | SUNAT documents included per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | ## What Cord does not cover yet - **Sales receipt (boleta)** and its daily summary: a Peruvian client without a RUC is rejected before sending, with a message that says so. - **Cancellation notice**, **debit note**, **SPOT detractions**, and **perceptions**: checking them in Settings leaves the rail inactive, so nothing is issued halfway. - Advance payments, free transactions, ISC, ICBPER, IVAP, multiple installments per invoice, and dispatch guides. ## Common problems **Settings says Coming soon.** Electronic invoicing with SUNAT is being activated. **My client has no RUC and the invoice is not issued.** A client without a RUC gets a boleta, which Cord does not issue yet. **The invoice says the exchange rate is missing.** It is in another currency and has no frozen exchange rate to soles: without it, the IGV withholding cannot be reported and the invoice is not sent. **SUNAT rejects the certificate.** It must mention your RUC and, in production, be registered in SUNAT Operaciones en Línea. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Mercado Pago](/en/docs/pagos/mercado-pago) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Clients and statements](/en/docs/gestion/clientes) - [Payment methods](/en/docs/pagos/metodos) --- # Invoicing in the United Kingdom URL: https://docs.cordhq.app/en/docs/pagos/paises/reino-unido Last updated: 2026-10-13 VAT invoices with VAT per line, validated VAT number and card payments; Bacs Direct Debit and bank transfer in beta. What changes with e-invoicing in 2029. ## What it is In the United Kingdom Cord issues a **VAT invoice** with a sequential number, each line item's VAT, your **VAT registration number** if you are registered, and your client's details. Today the United Kingdom has no authority that authorizes or registers invoices, so Cord's document **is** your invoice: there is no registration with HMRC to make from Cord. | | In the United Kingdom | |---|---| | Default currency | GBP | | Tax | VAT | | Tax ID | VAT reg. no., validated (HMRC modulus 97); also the Company Number | | Document | VAT invoice and credit note (**Commercial invoice** in the editor) | | Authority | Not applicable to the invoice | | PDF language | Your client's or, if they have none, your account's | | Online payments | Card with Cord Payments; bank transfer with a reference and Bacs Direct Debit in GBP (new) | ## Requirements - **Plan:** any (Free: 10 invoices per month). - Your **VAT registration number** if you are registered: it is what the law requires on the invoice, not your UTR. - **Permissions:** **Settings** for the tax profile and taxes; **Quotes** to issue; **Collections** to void and credit. ## Set up your account 1. In **Settings › Tax profile**, complete your legal name, your **VAT reg. no.** (with or without the GB prefix; XI for Northern Ireland), address, city, postal code, and invoice prefix. 2. Review your catalog in **Settings › Taxes**. 3. Activate your payments account in **Settings › Payments › Account** to get paid by card and, if you want, turn on **Automatic bank transfer** and **Bacs Direct Debit** in **Settings › Payments › Payment methods**. ## Taxes - **VAT 20%** (standard, default) and **VAT 5%** (reduced). - **Zero-rated** and **Exempt** are two different profiles on purpose: in the United Kingdom they are different regimes (the first lets you recover input VAT; the second does not), and your return treats them differently. - Each line item carries its own rate; the document prints one row per rate. ## Tax ID and vocabulary - The tax ID label is **VAT reg. no.** Cord validates the number with HMRC modulus 97 (including the variant for new numbers) and accepts government department numbers. It also accepts the Companies House **Company Number**, which is what payments onboarding asks a company for. - The tax is called **VAT** throughout the app, the PDF, and your client's link. ## Client and product data - **Client:** their country and, if a registered business, their VAT number, validated with the same rule. - **Product:** its default rate from the catalog. ## Void or correct An invoice is **voided** from its detail if it has no payments applied; with payments, it is corrected with a full or partial **credit note**. ## Get paid online - **Card** with Cord Payments, on the quote link and the invoice link. - **Bank transfer with a reference** in GBP, on the invoice link and the quote's payment page: your client transfers by Faster Payments, Bacs, or CHAPS to a sort code and account number of their own, with a reference per payment, and Cord reconciles it on its own. It needs a client linked to the document. New feature: see [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). - **Bacs Direct Debit** in GBP, on the invoice link, in the client portal, and in automatic payments: 4 business days to confirm (7 with a new mandate), and your client's bank statement shows the payment processor as the collector. New feature: see [Bank debit](/en/docs/pagos/domiciliacion). - Outside MXN, Cord charges no platform fee. See [Fees](/en/docs/pagos/condiciones). - Your payouts arrive at your account with a **sort code** and an eight-digit account number. See [Payouts](/en/docs/pagos/depositos). In **Settings › Payments › Payment methods**, each method shows its status. While the payment processor turns on the transfer, the row says **In review** and your clients don't see it yet; the **Your client will see** line at the top only counts what's already **Active**. On the link of an invoice in GBP, your client chooses **Bank transfer** and sees a sort code and account number of their own, with that payment's reference highlighted: On the quote's payment page, each part of the payment (deposit, balance, or installment) has its own reference, and your client can send the instructions to their email with **Email these to me**: ## Plan limits | Plan | Invoices per month | |---|---| | Free | 10 | | Starter, Pro, Scale, Developer | Unlimited | ## What is coming: mandatory e-invoicing The UK government confirmed that **e-invoicing between businesses** will be mandatory for VAT invoices from **April 2029**, with the Peppol network as the exchange framework. The technical specifications have not been published yet. Today Cord does not generate structured e-invoices (Peppol) for businesses in the United Kingdom: the European formats it generates are for issuers established in the European Union. Your Cord VAT invoice remains valid until the obligation takes effect. ## What Cord does not cover yet - **Peppol e-invoicing** for issuers in the United Kingdom. - **Making Tax Digital**: Cord does not file your VAT return; export your invoices to your accounting software or connect [QuickBooks Online](/en/docs/automatizacion/integraciones/quickbooks) or [Xero](/en/docs/automatizacion/integraciones/xero). ## Common problems **Cord rejects my VAT number.** The check digits do not match. Check the number on your VAT registration certificate. **Should I enter my UTR or my VAT number?** Your VAT registration number. Whatever you enter in **VAT reg. no.** is printed on the invoice, and the UTR should never go on an invoice. **My client needs the invoice in an electronic format.** Today Cord does not generate it for the United Kingdom; send them the PDF. ## Related - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Payment methods](/en/docs/pagos/metodos) - [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia) - [Bank debit](/en/docs/pagos/domiciliacion) - [QuickBooks Online](/en/docs/automatizacion/integraciones/quickbooks) - [Xero](/en/docs/automatizacion/integraciones/xero) --- # Invoicing by country URL: https://docs.cordhq.app/en/docs/pagos/paises/resumen Last updated: 2026-10-13 Which document Cord issues in each of the 12 countries it offers, which taxes your account starts with, which authority registers it, how you get paid online, and what is available today, being activated, or coming soon. ## What it is Cord offers twelve countries: **Mexico, the United States, Canada, Brazil, Spain, the United Kingdom, Germany, France, Colombia, Argentina, Chile, and Peru**. The country you choose when you create your account decides five things at once: - **The taxes your catalog starts with**, under their local name (IVA, VAT, GST, Sales tax, TVA, USt., IGV) and with their standard rates, ready to edit in **Settings › Taxes**. - **The tax ID** requested from the business and its clients (RFC, EIN, NIF, CNPJ, RUT…), validated with its check digit before it is saved. - **Which document Cord issues**: a tax document registered with the country's authority when Cord has that rail, or a commercial invoice with a sequential number when it does not. - **The form of the PDF**: the country's time zone and the legal notices it requires, in the language of its law. The rest of the PDF appears in your client's language or, if they have none, your account's; in France, French always comes first (see [Invoice language](/en/docs/pagos/facturacion#invoice-language)). - **How you get paid online**: Cord Payments (card; SPEI in Mexico; bank transfer with a reference in Spain, Germany, France, the United Kingdom, and the United States; SEPA, Bacs, ACH, or Canadian pre-authorized debit, depending on the country) or Mercado Pago where Cord Payments does not reach. Each country has its own page with every detail: taxes, the data you capture, document types, how the status before the authority looks, how to void or correct, and what Cord does not cover yet. The rails that register invoices with a tax authority are turned on country by country: Verifactu in Spain is already on, in beta; the approved platform in France, ARCA, NFS-e, NF-e, SUNAT, the SII, and the DIAN follow their own schedule. While one is **being activated**, its section in Settings says **Coming soon** and your invoices are still issued as commercial documents. This feature is new and may not be enabled on your account yet. If you don't see it, contact us. ## The 12 countries at a glance | Country | Taxes your account starts with | Document Cord issues | Authority or rail | Online payments | Status | |---|---|---|---|---|---| | [Mexico](/en/docs/pagos/paises/mexico) | IVA 16%, IVA 8% border region, exempt, IVA and ISR withholdings | CFDI 4.0 from Starter; pro forma on Free | SAT, stamped with your CSD | Card, Mercado Pago; SPEI in MXN on quotes and invoices (on invoices, being enabled) | Available | | [United States](/en/docs/pagos/paises/estados-unidos) | Your state's sales tax and exempt | Commercial invoice | No invoice authority; sales tax is recorded for your filing | Card; ACH debit and ACH or wire transfer (USD) new | Available; sales tax by address new | | [Canada](/en/docs/pagos/paises/canada) | GST, HST, and your province's combined rate (GST + QST, PST, or RST) | Commercial invoice | Not applicable | Card; pre-authorized debit (CAD) new | Available | | [Brazil](/en/docs/pagos/paises/brasil) | No national rate: Isento only | Standard invoice; NFS-e for services and NF-e for goods | National NFS-e system and your state's SEFAZ | Mercado Pago | NFS-e and NF-e being activated | | [Spain](/en/docs/pagos/paises/espana) | IVA 21, 10, and 4%, exemptions with a reason, IRPF; IGIC in the Canary Islands | Pro forma; invoice registered with Verifactu | AEAT | Card; SEPA debit and SEPA transfer (EUR) new | Verifactu in beta; e-invoicing between businesses coming soon | | [United Kingdom](/en/docs/pagos/paises/reino-unido) | VAT 20 and 5%, zero-rated, exempt | Commercial invoice | Not applicable | Card; Bacs debit and bank transfer (GBP) new | Available | | [Germany](/en/docs/pagos/paises/alemania) | USt. 19 and 7%, steuerfrei | Commercial invoice with downloadable XRechnung, ZUGFeRD, and Peppol | Not applicable: Cord generates the files, it does not transmit them | Card; SEPA debit and SEPA transfer (EUR) new | Available | | [France](/en/docs/pagos/paises/francia) | TVA 20, 10, 5.5, and 2.1%, exonéré | Commercial invoice with Factur-X and the reform's mentions | Approved platform (PA) | Card; SEPA debit and SEPA transfer (EUR) new | Issuing through the platform being activated | | [Colombia](/en/docs/pagos/paises/colombia) | IVA 19 and 5%, exempt, ReteIVA, ReteFuente | Commercial invoice; validated e-invoice | DIAN | Mercado Pago | Being activated | | [Argentina](/en/docs/pagos/paises/argentina) | IVA 21, 10.5, and 27%, exempt | Commercial invoice; type A, B, or C invoice with CAE | ARCA | Mercado Pago | Being activated | | [Chile](/en/docs/pagos/paises/chile) | IVA 19% calculated per document, exempt | Commercial invoice; DTE 33, 34, 56, and 61 | SII | Mercado Pago | Being activated | | [Peru](/en/docs/pagos/paises/peru) | IGV 18%, exonerado, inafecto | Commercial invoice; electronic invoice and credit note | SUNAT | Mercado Pago | Being activated | **How to read the status:** - **Available:** works today for every account in the country, on the plan shown. - **New:** built and tested against simulated services, but just released; it may not be enabled on your account yet. - **Being activated:** the rail is built and tested against the authority's specifications, and Cord turns it on country by country. Meanwhile, the Settings section says **Coming soon**, shows no fields, and your invoices are issued as commercial invoices. - **Coming soon:** Cord already built it, but it depends on something external (the authority publishing its service, or Cord completing a filing). ## Which document is issued The document type is decided **when you issue** and stays saved: an issued document keeps its type even if you later change your plan or configuration. | Situation | Document | |---|---| | Free plan, any country | Commercial invoice (pro forma in Mexico and Spain) | | Starter or higher in Mexico | **CFDI 4.0**, with your CSD uploaded. You can choose pro forma. | | Starter or higher in Spain, with Verifactu active and a certificate | **Invoice registered with Verifactu**. Without that, pro forma. | | Starter or higher in a country whose authority rail is ready (AR, BR, CL, CO, PE) | **Electronic document authorized** by the authority. If you choose the commercial option, a pro forma is issued. | | Any other case | Commercial invoice with a sequential number | - **Commercial invoice:** sequential number per organization, taxes and withholdings per line, the tax details of both parties, and an immutable copy. Its PDF says it is a commercial document not filed with any authority. - **Pro forma:** a commercial document that says explicitly that it does not replace a tax invoice. It is for getting paid, not for deducting. - **Tax document:** the one the authority authorizes or registers (CFDI, Verifactu record, ARCA CAE, NFS-e, NF-e, SUNAT CDR, DTE accepted by the SII, DIAN CUFE). Its legal number replaces the internal number. A document issued in an authority's test environment (homologation, beta, certification, or enablement) says **no tax validity**, carries a number with a test prefix, cannot be paid online, and does not use your tax document quota. ## Taxes per line, in the country's language In every country, tax travels **with each line item**, not with the document: you can mix a taxed service with an exempt product, or two different rates, on the same invoice. Each document prints one row per rate. - When the account is created, Cord seeds the country's standard rates (and the territory's when the tax changes: Canadian province, Canary Islands, Ceuta and Melilla, US state). They are an editable starting point: the business decides. - Brazil starts without a national rate on purpose: there is none to suggest. - Rounding also belongs to the country: Chile calculates IVA **once per document**, as the SII requires; the rest round per line. - Withholdings are subtracted from the total and calculated on their own base: the subtotal, the IVA (Colombia's ReteIVA), or only the taxed amount (Mexico's IVA withholding). ## Validated tax ID Cord validates the tax ID of the business and its clients with each country's rule before saving it: on the organization, on the client profile, in client imports, in the API, in the MCP server, and when a client is created from a quote. | Country | Tax ID | What is checked | |---|---|---| | Mexico | RFC | Shape, date, and SAT check digit; accepts the generic XAXX010101000 and XEXX010101000 | | United States | EIN / Tax ID | Nine digits and a prefix assigned by the IRS; for an individual, SSN or ITIN | | Canada | BN / GST/HST no. | Nine digits with a check digit, alone or with its program account (RT0001); QST number | | Brazil | CNPJ / CPF | Check digits; accepts the alphanumeric CNPJ | | Spain | NIF / CIF | NIF, NIE, and CIF with their control letter or digit, with or without the ES prefix | | United Kingdom | VAT reg. no. | HMRC modulus 97; also the Company Number | | Germany | Steuernummer / USt-IdNr. | USt-IdNr. with its check digit; Steuernummer by its shape | | France | SIREN / N° TVA | SIREN and SIRET with their check digit; the TVA key calculated from the SIREN | | Colombia | NIT | Verification digit when written with a hyphen | | Argentina | CUIT | Prefix and check digit | | Chile | RUT | Check digit, including K | | Peru | RUC | Prefix and check digit | Whatever cannot be proven wrong is accepted: a false rejection would leave you unable to invoice. ## Series per issuer Outside Mexico, numbering belongs to the **issuer**, not to the Cord account. If two Cord organizations have the same tax ID, they cannot number with the same series: when you save your tax details, Cord asks you to choose another one (for example, by adding a 2 to the prefix). That way two invoices of your business never repeat a number. In Spain the series also carries the fiscal year and numbering starts over every year. ## Online payments by country | Method | Countries | Currency | |---|---|---| | Card with Cord Payments | MX, US, CA, ES, GB, DE, FR | The invoice's, if the processor supports it | | Automatic SPEI | MX | MXN only | | Automatic SEPA transfer | ES, DE, FR | EUR only | | Automatic bank transfer (Faster Payments, Bacs, or CHAPS) | GB | GBP only | | Automatic ACH and wire (domestic wire) | US | USD only | | SEPA Direct Debit | ES, DE, FR | EUR only | | Bacs Direct Debit | GB | GBP only | | ACH bank debit | US | USD only | | Pre-authorized debit (Canada) | CA | CAD only | | Mercado Pago | MX, BR, CO, AR, CL, PE | Whatever Mercado Pago supports on your account | | Manual transfer | All 12 | Any, recorded by hand | In Brazil, Colombia, Argentina, Chile, and Peru, Cord Payments does not open accounts: online collection is with [Mercado Pago](/en/docs/pagos/mercado-pago), and **Settings › Payments › Account** says so before you start onboarding. - **Bank transfer with a reference** (SEPA, UK, ACH, or wire): each client has one fixed account to pay you and each payment carries its own reference, which Cord uses to reconcile it. It's offered on the invoice link and on the quote's payment page, only if the document has a linked client. Canada, Brazil, Colombia, Argentina, Chile, and Peru have no automatic bank transfer. See [Bank transfer with a reference](/en/docs/pagos/transferencia-referencia). - **Bank debit** (SEPA, Bacs, ACH, or pre-authorized debit): it's offered on the invoice link, in the client portal, and as a saved method for automatic payments, only on invoices in its currency. See [Bank debit](/en/docs/pagos/domiciliacion). - Both are turned on in **Settings › Payments › Payment methods** and are only offered once the payment processor activates the method on your account. SPEI in Mexico stays the same. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. ## Plan limits | Plan | Commercial invoices and pro formas per month | Tax documents included per month | |---|---|---| | Free | 10 | No tax issuance included | | Starter | Unlimited | 30 | | Pro | Unlimited | 200 | | Scale | Unlimited | 500 | | Developer | Unlimited | 1,000 | - Every document the authority authorizes or registers counts as a tax document, in any country: a CFDI (also each payment complement), a Verifactu record, an ARCA document, an NFS-e, an NF-e, a SUNAT invoice, a DTE, or a DIAN invoice. - Drafts and test documents do not count. - From Starter, additional tax documents are billed as overage on your subscription. See [Your Cord subscription](/en/docs/cuenta/suscripcion). - In the United States, sales tax calculated by address has its own monthly quota. See [United States](/en/docs/pagos/paises/estados-unidos). ## Common problems **My country says Coming soon in Settings.** Your country's rail is being activated. Your invoices are issued as commercial invoices and you can collect them normally; when the rail is activated for your account, the section will show its fields. **My invoice came out as a pro forma.** In Mexico and Spain, an invoice without tax issuance is a pro forma. Check your plan (Starter or higher) and that your certificate is uploaded and valid. **Cord rejects my client's tax ID.** The check digit does not match the country's rule. Check the number on your client's certificate; the message says which data to review. **My country doesn't have the rate I need.** Add it in **Settings › Taxes** with **+ New tax**. The seeded rates are a starting point, not a closed list. ## Related - [Mexico](/en/docs/pagos/paises/mexico) · [United States](/en/docs/pagos/paises/estados-unidos) · [Canada](/en/docs/pagos/paises/canada) · [Brazil](/en/docs/pagos/paises/brasil) - [Spain](/en/docs/pagos/paises/espana) · [United Kingdom](/en/docs/pagos/paises/reino-unido) · [Germany](/en/docs/pagos/paises/alemania) · [France](/en/docs/pagos/paises/francia) - [Colombia](/en/docs/pagos/paises/colombia) · [Argentina](/en/docs/pagos/paises/argentina) · [Chile](/en/docs/pagos/paises/chile) · [Peru](/en/docs/pagos/paises/peru) - [Tax invoicing](/en/docs/pagos/facturacion) - [European e-invoicing](/en/docs/pagos/factura-electronica) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Payment methods](/en/docs/pagos/metodos) - [Your Cord subscription](/en/docs/cuenta/suscripcion) --- # Client portal: invoices and payments URL: https://docs.cordhq.app/en/docs/pagos/portal-facturas Last updated: 2026-10-13 One link per client with all their invoices, the balance per currency, paying several invoices in a single charge, and automatic payments. How to create, share, regenerate, or disable it, and what your client sees. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. ## What it is The **client portal** is a private page, one per client, where that client sees **every invoice you've issued them**, what they owe in each currency, and what they've already paid. From there they download each invoice, **pay several in a single charge**, and can turn on [automatic payments](/en/docs/pagos/cobro-automatico) so the next ones are charged on their due date by themselves. They don't need an account or a password: the link is their access. You create and manage it from the client's profile. Its appearance comes from **Settings › Brand appearance › Client portal**: the layout, top announcement and welcome message you set there also show here. The comments setting on that tab only applies to each quote link. See [Client portal (quote link)](/en/docs/cuenta/portal-cliente). ## Requirements | | Details | |---|---| | **Plan** | All plans. | | **Permission** | **Clients** to create, send, regenerate, or disable the link, and to turn off a client's automatic payments. | | **Invoices** | Invoices **issued** to that client. Quotes don't appear in the portal. | | **Online payment** | Your [Cord Payments](/en/docs/pagos/onboarding) account active, with **Card** (or bank debit) turned on in **Settings › Payments › Payment methods**. Available in Mexico, the United States, Canada, Spain, the United Kingdom, Germany, and France. In Brazil, Colombia, Argentina, Chile, and Peru the portal shows the invoices and the balance, and tells your client to contact you to pay. | ## Create and share the link 1. Open **Clients** and go to the client's profile. 2. In the right-hand column, under **Client portal**, click **Create portal link**. 3. Share the link: - **Copy** copies it so you can paste it into an email, WhatsApp, or your system. - **Send by email** sends your client the "Your invoices with [your business]" email with the **Open my portal** button, with your branding and your reply-to address. It only appears if the client has an email on their profile. - **Open** shows you the portal in another tab, just as your client sees it. The link stays the same until you generate another one: you can copy it or send it again whenever you want. ## What your client sees | Element | Details | |---|---| | **Top announcement** | A strip in your brand color, if you wrote one in **Client portal**. | | **Header** | Your logo (or your initial in your brand color) in the header style you chose, **Your invoices**, the client's name and your welcome message, if you wrote one. | | **Balance due per currency** | One card per currency with the balance, how many invoices are to pay, and how much is **overdue**. Currencies are **never added together**: a balance in MXN and another in USD are two cards. With no balance, it says "You have no balance due." | | **Automatic payments** | If you allow it in **Settings › Payments › Payment methods**, the card to turn it on, the method it's on with, or the reason it stopped. See [Automatic payments](/en/docs/pagos/cobro-automatico). | | **To pay** | Each open invoice with its number, its due date (or the issue date if it has none), the balance and, if there were partial payments, "of [total]". Overdue ones carry **Overdue**; one with a pending bank debit, **Payment processing**. Each with **View** (its link) and **PDF**. | | **Paid** | The last 24 paid invoices, collapsed, with their total and their links. | | **Footer** | Your contact email, the notice "This link is personal: it gives access to your invoices and payments with [your business]. Don't share it.", the Cord brand mark, unless you've hidden it, and the **Platform Privacy Notice** link, which opens Cord's privacy notice in the portal's language. | The portal speaks that client's document language (the one in their record or, if they have none, your account's) and uses that language's date and amount format. Each invoice they open from there keeps the language it was issued in. The automatic payment authorization is shown in the portal's language and Cord records which one your client accepted it in; in Canada, the pre-authorized debit clause is in French if that's their language and in English otherwise. See [Document language](/en/docs/gestion/clientes#document-language). ### Which invoices appear - Invoices **issued** to that client, open or paid, in all their currencies. - Drafts, voided invoices, and credit notes don't appear. - In Mexico, a replaced CFDI doesn't appear (its replacement does), and neither does the global invoice, because it doesn't belong to any client. - A test document appears, but can't be paid online. ## Pay several invoices at once 1. Your client checks the invoices they want to pay. They can only choose **one currency at a time**: once they check an invoice in MXN, the ones in other currencies are disabled. 2. A bar appears at the bottom with the summary, for example "2 invoices · $101,256.40", and the **Pay selected** button. 3. In the payment sheet they see the total. If you allow automatic payments, they can check **Save this method for automatic payments**, together with the authorization. 4. They click **Continue**, enter their card or bank account details, and click **Pay [amount]**. 5. Back on the portal they see "We're confirming your payment". A card takes a few seconds; a bank debit, a few days. In Canada, if you turned on pre-authorized debit, the payment sheet asks **Paying from your bank account?** before **Continue**, with **Yes, as a business** and **Yes, as an individual**. The answer is recorded in the debit authorization and adds that option to the form; to pay by card they don't need to answer, unless the debit is the only method. The same question appears when turning on [automatic payments](/en/docs/pagos/cobro-automatico) from the portal. How it's charged and allocated: - **Each invoice is paid at its real balance.** The browser only chooses which invoices; Cord reads each one's amount from your account at the moment the charge is created. If a balance changed (for example, because you recorded another payment), your client reads that the balance of an invoice changed or already has a payment in progress, and to refresh the page. - **One charge, several invoices.** The client sees a single charge on their statement. When the payment is confirmed, each invoice records its share in its payment history and its balance goes down; the one that reaches zero becomes **Paid**. - **Methods:** card and, if you turned on [bank debit](/en/docs/pagos/domiciliacion), SEPA debit on invoices in EUR (businesses in Spain, Germany, and France), ACH on invoices in USD (United States), Bacs on invoices in GBP (United Kingdom), or pre-authorized debit on invoices in CAD (Canada). In MXN only card is offered. - **Fee:** where Cord charges a fee (today, charges in MXN), **one** fee is charged for the whole charge, not one per invoice. See [Fees](/en/docs/pagos/condiciones). - **Payment processing.** While a bank debit is being confirmed, those invoices show **Payment processing** and lose their checkbox: they can't be paid again or voided. - **Account to verify.** If your client authorizes the debit with an account that is verified with a small deposit (in Canada, for example), the sheet hides the pay button and tells them that within 1 to 2 business days they'll receive that deposit and an email with instructions, with the **Verify my account** link. Those invoices also stay in **Payment processing** until they confirm the account or the verification expires. See [Bank debit](/en/docs/pagos/domiciliacion#canadian-pre-authorized-debit). - **Never twice.** If an invoice already has a payment in progress from its own link (a debit the bank is still confirming or that is waiting for the account to be verified), the portal doesn't charge it again: it tells your client to wait for the confirmation and, if the account still needs verifying, shows them the **Verify my account** link. A payment made from the portal is refunded from the detail page of any of the invoices it paid: just that invoice's share, or the whole payment. If the refund is issued outside Cord, Cord allocates it among the invoices it paid: see [Refunds](/en/docs/pagos/reembolsos#refunding-a-charge-that-paid-several-invoices). ## Generate a new link or disable it From the **Client portal** block on the profile: | Action | What happens | |---|---| | **Generate new link** | The previous link stops working right away and Cord creates another. Use it if the link was shared too widely; then share the new one with your client. | | **Disable link** | Your client can't open their portal until you generate another link. Automatic payments don't change: if they're still on, the notice for a failed charge sends your client a new portal link. If you don't want them back in, turn off automatic payments too. | Both actions ask for confirmation and are recorded in your account's audit log. If automatic payments stay on and a charge fails, the email Cord sends the client includes the button to their portal, and to do so it generates a new link if you had disabled it. To make sure there's no link at all, turn off automatic payments too. ## Privacy and security - **The link is a credential.** It's generated at random (32 bytes) and can't be guessed. Whoever has it sees the invoices and can pay them: share it only with your client. - **It isn't indexed or tracked.** The page doesn't show up in search engines, doesn't pass its address to other sites, and carries no analytics. Cord doesn't record when your client opens it either. - **It lives on cordhq.app.** Even if you have a [custom domain](/en/docs/cuenta/dominio-propio), the portal isn't served from your domain: your domain only serves quote and invoice links, never a page with saved payment methods. - **Payment details don't go through Cord.** The card or bank account is entered in the payment processor's form; Cord only keeps the type, the brand, and the last four digits. ## Limits - Up to 50 invoices in a single payment, all in the same currency. - The minimum per charge is the processor's: 0.50 in the currency (for example, 0.50 USD or 0.50 EUR), or 50 units in zero-decimal currencies. - The portal doesn't offer Mercado Pago, SPEI, or bank transfer: online payment is with Cord Payments. To pay by transfer, your client uses **View** and pays from that invoice's link: by SPEI to that invoice's CLABE (in MXN, if you have SPEI turned on) or by [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) (in EUR, GBP, or USD, if you have it active). - Part of an invoice can't be paid from the portal; for a partial payment, your client uses **View** and pays from that invoice's link. - Quotes don't appear in the portal. ## Troubleshooting **My client doesn't see payment buttons.** Your Cord Payments account isn't active, **Card** is off in **Settings › Payments › Payment methods**, your country doesn't have Cord Payments, or the account is a test one ("Test portal: online payment is disabled."). **An invoice doesn't appear.** Check that it was issued to that client. A draft, a voided invoice, or a credit note isn't listed. **An invoice can't be checked.** Your client already checked invoices in another currency, the invoice has a payment in progress, or there's no method available in that currency. **The link says the page doesn't exist.** You generated a new link or disabled the portal. Share the current link from the client's profile. **Send by email doesn't appear.** The client has no email on their profile. ## Related - [Automatic payments](/en/docs/pagos/cobro-automatico) - [Payment methods](/en/docs/pagos/metodos) - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Clients and statements](/en/docs/gestion/clientes) - [Refunds](/en/docs/pagos/reembolsos) - [Client portal (quote link)](/en/docs/cuenta/portal-cliente) --- # Automatic payment reminders URL: https://docs.cordhq.app/en/docs/pagos/recordatorios Last updated: 2026-10-15 Which payment reminders Cord sends on its own: the invoice ladder before and after the due date and how to choose its stages, turn them off, or pause a customer, the notice for quotes coming due, what your customer receives, and how duplicate emails are prevented. ## What they are Automatic reminders are emails Cord sends to your customer when a document is about to fall due or is already overdue. They work on every plan and come turned on: they run once a day for every open invoice and every approved quote that meets the conditions on this page. You choose the invoice schedule in **Settings › Invoicing › Reminders**. If you never change it, Cord uses the usual ladder. They're different from two other collection tools: - **[AI collections](/en/docs/pagos/cobranza-ia)** (Pro, Scale, and Developer) writes personalized emails for overdue accounts and can propose an installment plan to your customer, which only they can accept. - **The WhatsApp reminder** in [receivables](/en/docs/pagos/cartera-cobranza) is one you prepare and send yourself, whenever you want. ## Requirements | Requirement | Detail | |---|---| | Plan | All plans. | | Permission | None for them to go out: Cord sends them on its own. To change the schedule or turn them off, the **Settings** permission; to pause a customer, the **Collections** permission. | | Customer | Must have an email on file. No email, no reminder. | | Invoice | Issued (not a draft), open, with a due date and an outstanding balance. | | Quote | Approved or invoiced, with a balance, not a recurring retainer, and whose balance isn't already carried by an open invoice (in that case the invoice is reminded). | | Account | Doesn't apply to test accounts or the demo account. | ## Invoices: the reminder ladder Every open invoice goes through a ladder of stages, counted in days from its due date. The **default** ladder has six: | Stage | When | What your customer receives | |---|---|---| | 7 days before | One week before the due date | **Invoice [number] is coming due** | | 1 day before | The day before the due date | **Invoice [number] is coming due** | | 3 days after | Three days overdue | **Past due: invoice [number]** | | 7 days after | One week overdue | **Past due: invoice [number]** | | 14 days after | Two weeks overdue | **Past due: invoice [number]** | | 30 days after | One month overdue | **Past due: invoice [number]** | After the last stage of your schedule, Cord stops sending automatic reminders for that invoice. Days are counted on **your business's calendar day**, using the time zone in **Settings › General**: a stage doesn't go out a day early or a day late because your customer or the server is in another time zone. ## Choose the schedule This feature is new and may not be enabled on your account yet. If you do not see it, write to us. 1. Open **Settings › Invoicing › Reminders**. 2. In **Invoice schedule**, select the moments when you want your customer to get a reminder: before the due date, on the due date, or after. 3. Check the **Your client receives** line: it spells out the full schedule as it will go out. 4. Click **Save changes**. You can choose from: | Moment | Options | |---|---| | Before the due date | 14, 7, 3, or 1 day before | | On the due date | **Due today** | | After the due date | 1, 3, 7, 14, 30, 60, or 90 days after | Up to **8 reminders** per invoice, and at least one. **Restore the default schedule** brings back the usual ladder. ### What happens to invoices already in progress The change applies from the next daily run, including invoices that already received reminders: - **A stage that already went out is never repeated**, even if it stays in your schedule. - **A stage that falls before one already sent is skipped.** If the 7-days-before notice already went out and you add 14 days before, that invoice doesn't get a late notice; new invoices do. - **A new later stage does go out** when the invoice reaches it. For example, if you add 60 days after, an invoice that already went through the 30-day stage gets the 60-day one when it's 60 days overdue. ### Turn reminders off The **Send automatic reminders** switch stops the emails to your customers: invoice reminders and quote notices. Everything that doesn't go to the customer keeps working: your **Overdue payment** alert for quotes (if it's on in [Notifications](/en/docs/gestion/notificaciones)) and the **An invoice becomes overdue** event. [AI collections](/en/docs/pagos/cobranza-ia) has its own switch. If you turn them back on, each invoice gets only the most recent stage it already reached, not the ones skipped while reminders were off. ## Pause a customer If a customer asked you not to write to them, pause their reminders from their record: 1. Open **Clients** and go to the customer. 2. In **Automatic reminders**, click **Pause reminders** and confirm. The pause is the same **Never email** list used by [AI collections](/en/docs/pagos/cobranza-ia): a paused customer gets no automatic reminders and no emails from the agent. The other way around, a customer, quote, or invoice you add to **Never email** from the agent doesn't get reminders either. Paused customers appear in **Settings › Invoicing › Reminders › Paused clients**, with a **Resume** button. Your customer can also ask for it themselves: every automatic reminder and every [AI collections](/en/docs/pagos/cobranza-ia) email carries the link **Don't contact me through this channel again** at the bottom. If they click it, they're excluded from your business's email collections right away, with no automatic reminders and no emails from the agent, and Cord lets you know. In **Paused clients** and on their record they appear as **Customer request**, without the **Resume** button: an opt-out your customer asked for can't be resumed from Cord. The opt-out only applies to your business: if your customer also buys from another business that uses Cord, that business can still email them. ## What your customer receives - **Subject:** the matching notice followed by your business name: **Invoice [number] is coming due** before the due date, **Invoice [number] is due today** on the due date, and **Past due: invoice [number]** after. - **Language:** the invoice's, which the invoice took when issued: the one your client had in their record or, if they had none, your account's. Changing the record later doesn't change that invoice's reminders. See [Document language](/en/docs/gestion/clientes#document-language). - **Body:** the invoice number, the due date, and the **outstanding balance with its currency**. The balance already deducts partial payments and credit notes, so you never remind your customer about money they've already paid. - **Pay invoice button:** opens the invoice link, where they can pay the full balance or pay part of it. See [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas). - **Your signature, sender, and reply-to:** from Starter, the reminder carries the signature, display name, and reply-to address from **Settings › Notifications › Email**. The introduction from that screen doesn't: it's written for the email you send the document with, and the reminder keeps its due-date message. - **Branding:** the email uses your logo and color. If you connected your [business Gmail](/en/docs/automatizacion/integraciones/gmail), it goes out from your Gmail account; otherwise it goes out from Cord with your business name. - **Opt-out:** at the bottom, the link **Don't contact me through this channel again**. Email apps that support it also offer one-click unsubscribe. Each reminder sent appears on the **invoice timeline** (for example, a due-date notice 7 days before, a due-date notice on the due date, or a collection reminder 3 days overdue) and in the audit log. If your customer opted out, the stage that was due isn't sent and appears once on the invoice timeline as **Reminder not sent at the client's request**, with the stage in the detail. A quote notice skipped for that reason is recorded in the audit log. ### One stage, one email Cord records the stage **before** sending the email, and each stage can be recorded only once per invoice. In practice: - **No duplicates.** Even if the daily process runs twice on the same day, your customer receives a single email per stage. - **A failed send is retried.** The stage is released and tried again the next day. - **No bursts.** If an invoice enters the ladder late (for example, you issued it already 20 days overdue), Cord sends only the most recent stage that applies, not every earlier one at once. - **The same money isn't reminded twice.** If the invoice comes from a quote that received its own reminder that same day, the invoice waits until the next day. ### The "An invoice becomes overdue" event The day after an invoice with a balance falls due, Cord emits the **An invoice becomes overdue** event (`invoice.overdue`) once. It reaches your [webhooks](/en/docs/desarrolladores/herramientas/webhooks) and can trigger a [workflow](/en/docs/automatizacion/workflows/disparadores), for example to alert your team in Slack or create a follow-up task. It goes out even if you turned reminders off or paused the customer: it's for you, not for them. ## Quotes: due-date notice Approved quotes with an outstanding balance get a simpler notice: **two emails, one three days before the due date and another on the day it's due**. These two moments are fixed; they follow the reminders switch and the per-customer pause. The due date is the approval day plus the payment term's days: | Term | Due | |---|---| | Due on receipt | On the approval date | | Net 7, 15, 30, 45, 60, or 90 | That many calendar days after approval | The email, with your logo and color, shows the quote number, the quote's **balance** with its currency (the total minus what was already collected as a deposit or installments), and the due date, with a **View and pay [quote number]** button that opens the quote link. The subject is **Payment reminder — [quote number]**; it goes out in the quote's language (the one it took when sent) and, from Starter, with your signature. See [Credit terms](/en/docs/pagos/credito). With **Due on receipt** terms, the due date matches the approval, so only the due-day notice goes out, and it may arrive the same day your customer approves. ## When no reminder is sent - You turned automatic reminders off, or the customer is paused. - Your customer asked not to receive email collections through the link **Don't contact me through this channel again**. - The customer has no email on file. - The invoice is already paid, voided, marked uncollectible, or still a draft. - The invoice has no due date or its balance is zero. - The invoice has gone through every stage of your schedule, or is more than 120 days overdue. - The stage that would apply falls before one that already went out (see **What happens to invoices already in progress**, above). - The quote is fully paid, isn't approved, or is a [recurring retainer](/en/docs/pagos/igualas): retainers charge themselves every month and are never treated as overdue receivables. - The account is a test account or the demo account. ## Limits - One invoice reminder per stage, up to 8 stages, chosen from the menu on this page. - Automatic reminders don't count toward the [AI collections](/en/docs/pagos/cobranza-ia) cap of 2 collection messages every 7 days, and that cap doesn't stop them. - The reminder text can't be edited; from Starter it carries your signature. If you need a different message or channel, create a [workflow](/en/docs/automatizacion/workflows) with the **An invoice becomes overdue** trigger and a [wait](/en/docs/automatizacion/workflows/esperas). - Quote notices have two fixed moments and no ladder after the due date. To chase overdue quotes, use [receivables](/en/docs/pagos/cartera-cobranza) or [AI collections](/en/docs/pagos/cobranza-ia). - Reminders don't attach the PDF; the customer downloads it from the invoice link. ## Common problems **My customer says they didn't get the reminder.** Check that their record has an email, that they aren't paused, and that reminders are on. Then look for the event on the invoice timeline. If it isn't there, the send failed and is retried the next day. **They got a reminder for an invoice they already paid by transfer.** The reminder goes out while the invoice has a balance. Record the payment on the invoice as soon as you verify it. **I added a stage and an invoice didn't get it.** If that invoice had already received a later stage, the new one falls behind and isn't sent, so no late notice goes out. New invoices do get it. **I don't want a customer to get reminders.** Pause their reminders from their record in **Clients** (see [Pause a customer](#pause-a-customer)). ## Related - [Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas) - [Receivables and operating collections](/en/docs/pagos/cartera-cobranza) - [AI collections](/en/docs/pagos/cobranza-ia) - [Credit terms](/en/docs/pagos/credito) - [Notifications](/en/docs/gestion/notificaciones) --- # Refunds URL: https://docs.cordhq.app/en/docs/pagos/reembolsos Last updated: 2026-10-11 How to give money back to a customer from Revenue › Payments or from an invoice's detail page: full or partial refunds, each method's limits, what happens to the fee, the CFDI and the allocation of a charge that paid several invoices. ## Where to refund It depends on how the money came in: | The payment came in through… | Refund it from… | |---|---| | A **quote** link (full payment, deposit, balance or installments) or a [retainer](/en/docs/pagos/igualas) | **Revenue › Payments** (`/app/cobros`), with the **Refund** button in "Recent payments". | | An **invoice** link, the [client portal](/en/docs/pagos/portal-facturas) or [automatic payments](/en/docs/pagos/cobro-automatico) | The **invoice detail page**, with the **Refund** button next to the payment. See [Refunding an invoice payment](#refunding-an-invoice-payment). | | A quote link, collected with **Mercado Pago** | Your Mercado Pago account; Cord reads it and records it on its own (see [Mercado Pago](/en/docs/pagos/mercado-pago)). | | A **manually recorded** payment (transfer, cash, check) | Outside Cord: Cord did not move that money, so there is no button. You handle the refund directly with your customer. | In **Revenue › Payments**, every row in "Recent payments" that corresponds to a payment **reconciled through Cord Payments** has the **Refund** button. Once a refund is confirmed, Cord reflects it in the balance of each invoice that money paid (see [Effect on a linked invoice](#effect-on-a-linked-invoice)). Refunding requires the **Refunds** permission. This permission is **not granted automatically** to team administrators — the account owner has to explicitly grant it to each member who needs to issue refunds, from Settings › Team. This is intentional: moving money out of the account is a more sensitive action than administering it. ## How it works In Revenue › Payments (an invoice's detail page works the same way, with what is explained [below](#refunding-an-invoice-payment)): 1. Click **Refund** on the payment's row. 2. A dialog opens with the amount available to refund (it may be less than the total, if you already issued a partial refund before) and an optional internal reason field. 3. Enter the amount — the full total or just a portion. 4. Tick the box confirming you understand that the refund returns the stated amount to the customer but **does not automatically refund Cord's platform fee**. You can't confirm without it. 5. Since this moves money, Cord asks you to **re-confirm your identity** (your password or your 2FA code) before executing the refund, even if your session was already active. It's the same "re-authentication" mechanism that protects other sensitive account actions. 6. The refund is logged in your organization's audit trail, with the amount, the reason (if given), and who authorized it. You can refund the same payment **more than once**, as long as the accumulated total doesn't exceed what was originally charged — the dialog always shows you how much is still available. ## Refunding an invoice payment This feature is new and may not be enabled on your account yet. If you don't see it, write to us. On an invoice's detail page, the **Payments** section lists each payment. An online payment —by card, bank debit (SEPA, ACH, Bacs or Canadian pre-authorized debit), bank transfer (SPEI or with a reference) or Mercado Pago— that came in through the invoice link, the client portal or automatic payments has the **Refund** button. Under each payment you see what has already been refunded and what is in progress. 1. Click **Refund** next to the payment. 2. Cord checks the payment and tells you what can be returned **before** you confirm: the available amount, whether it accepts a partial amount and, if it can't be refunded, why. 3. Enter the amount (or confirm the total), add an internal reason if you want, and check the box confirming that Cord's platform fee is not refunded automatically. 4. Confirm. Cord asks you to confirm your identity again if you haven't in the last 10 minutes, just like in Payments. 5. The refund is recorded in the audit log and in the invoice's activity. ### What each method allows | Method | Refund | Window and timing | |---|---|---| | Card | Full or partial | The money goes back to the client's card within their bank's timeframes. | | SEPA debit (EUR) | Full or partial | Up to 180 days after the charge. It takes 3 to 4 business days to process and up to 5 to reach the client's account. | | ACH debit (USD) | **Full only** | Up to 180 days after the charge. It takes up to 3 business days and reaches the client as a credit that doesn't say "refund": let them know. | | Bacs debit (GBP) | Full or partial | Up to 180 days after the charge. It takes 3 to 4 business days. Your client can dispute the debit with their bank at any time, even after the refund: let them know you're returning it so they don't receive it twice. | | Pre-authorized debit (CAD) | Full or partial | Up to 180 days after the charge. It takes about 3 business days, can't be cancelled and reaches the client as a credit that doesn't say "refund": let them know. | | SPEI transfer (MXN) or [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) (EUR, GBP or USD) | Full or partial | Up to 180 days after the charge. It goes back to your client's bank account: they receive an email to provide it and, until they do, the refund is **on hold** without reopening the balance. If they don't respond within 45 days, the refund isn't completed and the money stays as a balance in their favor in your payments account: write to us to return it. To request it, the invoice needs the client's email. | | Mercado Pago | Full or partial | It leaves your connected Mercado Pago account and goes back to the method the client paid with. | - A **bank debit in progress** doesn't appear among the invoice's payments yet, and it can't be refunded until it's confirmed. The invoice detail page says so. - An invoice's **bank transfer** payment (SPEI or with a reference) is returned by the processor to the account your client provides, not by a transfer of yours. This differs from a transfer collected on a quote (see [Card vs. bank transfer](#card-vs-bank-transfer-two-different-flows)). - A payment that **came in through the quote** (the quote was already paid, fully or partially, when it was invoiced) is refunded from its payment in Revenue › Payments, or from your Mercado Pago account if Mercado Pago collected it. The invoice reflects it on its own. - A **manually recorded** payment has no button: Cord did not move that money and can't return it. - If the provider has a refund of that payment that Cord hasn't recorded yet (for example, one issued outside Cord a few minutes ago), Cord waits to record it before letting you request another. ### What happens on the invoice - A **confirmed** refund reopens that amount: a paid invoice goes back to open with that balance, and one with an outstanding balance increases it. One **in progress** (bank debits, a transfer waiting for the client's account, Mercado Pago under review) doesn't touch the balance until it's confirmed. - On a **voided** invoice that received a late payment, refunding it lowers the "Amount to return to client". - The invoice's activity records each refund once: "Refund of …" when it's confirmed, "Refund of … requested" while it's in progress, and "The refund of … did not go through" if it fails. The provider's notice that arrives later doesn't count it twice. - With Cord Payments, the refund also triggers the `refund.succeeded` and `refund.failed` events of your [webhooks](/en/docs/desarrolladores/herramientas/webhooks), like any other refund. - The refund **doesn't change the document**: the invoiced amount stays the same. If what you return will no longer be charged, also issue a credit note (see [Effect on a linked invoice](#effect-on-a-linked-invoice)). ### Mexico: the CFDI remains valid Refunding the payment doesn't cancel or change the stamped CFDI: before the SAT, the invoice remains valid for its original amount, and if that payment had a payment complement, the complement isn't canceled either. To document the return, issue a **credit note** from **More actions › Credit note**: in Mexico it is a CFDI de egreso (type E) with use G02 "Returns, discounts or rebates" and relationship 01 to the invoice's UUID. Cord doesn't issue it on its own, because not every refund is a return of the sale: refunding a duplicate charge, for example, doesn't change what was invoiced. Decide the amount with your accountant. While there is refunded money without a credit note covering it, the invoice detail page reminds you. ## Card vs. bank transfer: two different flows ### Card The refund is processed **automatically** as soon as you confirm it — no manual step required on your part. The money returns to the customer's original card on whatever timeline their bank handles. ### Bank transfer (SPEI or with a reference) In Revenue › Payments, refunding a transfer collected on a **quote** —SPEI in Mexico or [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) in EUR, GBP or USD— requires a manual transfer by the business. Requesting it in the dashboard does not itself return the money (an **invoice**'s transfer is returned to the account your client provides: see [What each method allows](#what-each-method-allows)): 1. Gets recorded in Cord as "pending, manual refund". 2. Cord automatically creates in [Tasks](/en/docs/gestion/tareas) a task titled "Send the [amount] SPEI refund" (or "Send the [amount] bank transfer refund" for a bank transfer with a reference), in your account's language: high priority, linked to the quote, and assigned to whoever requested the refund. It emits **A task is created** (`task.created`) like any task. 3. You make the transfer yourself through your normal bank account, and mark the task as completed. Completing the task closes your to-do, but **doesn't record the refund as paid**: in Cord it stays "pending, manual" and **A refund succeeds** (`refund.succeeded`) isn't emitted. The amount stays set aside, so it can't be refunded again. Keep the transfer receipt on your side. ## What happens to your money - The refunded amount is deducted from your net revenue across all of the [Payments](/en/docs/pagos/dashboard) reports — it never stays "hidden" in the total collected figure. - **The platform fee Cord charged on the original payment is not refunded automatically**, and the payment processor's fees are governed by its own terms. It's a processing cost that already occurred when the card was charged or the transfer was received — refunding the customer doesn't reverse that cost. See the details in [Fees and advantages](/en/docs/pagos/condiciones). - If the refunded payment was part of a quote with an [upfront deposit and balance](/en/docs/pagos/anticipos), the refund only affects the specific payment you chose — not the rest of that quote's slices. A refund **does not revert the quote's status** — it stays marked as paid. If you also need to cancel the quote itself (for example, because the entire order was called off), do that from the quote's detail page separately. ## Effect on a linked invoice Cord distinguishes a requested refund from a confirmed one. Only confirmed refunds count toward money returned on the invoice; a repeated event doesn't subtract it again. A refund can arrive before the payment record and await that link. A confirmed refund **reopens** that amount in the invoice balance: the invoice is no longer paid for that amount. If the refund is for something that won't be collected anymore (a returned product, a service that wasn't delivered), also issue a **credit note** for that amount: a credit note reduces the document amount while a refund returns money, and they're separate actions. Review [balance calculation](/en/docs/pagos/facturas-emitidas). ## Refunding a charge that paid several invoices This feature is new and may not be enabled on your account yet. If you don't see it, write to us. From the [client portal](/en/docs/pagos/portal-facturas) and with [automatic payments](/en/docs/pagos/cobro-automatico), a single charge can pay several invoices. **If you refund from Cord**, you do it from the detail page of one of those invoices and choose: - **This invoice only:** up to what the charge applied to that invoice, minus what has already been returned to it. The refund goes to that invoice, not to the last one. - **The whole payment:** returns everything left of the charge and reopens each invoice for what it paid. An **ACH** charge only allows **The whole payment**: returning a single invoice's share would be a partial refund. **If the refund is issued outside Cord** (or you choose The whole payment), Cord allocates the refund among the invoices the charge paid: 1. **From the last one to the first.** The refund is assigned starting with the last invoice the charge was applied to, and works backwards. 2. **Up to what each invoice received.** Each invoice is assigned at most what it received from that charge, minus what other refunds of the same charge already assigned to it. 3. **All or nothing.** If the refund doesn't fit entirely in what the charge applied (for example, because the refund notice arrived before the payment notice), it isn't split halfway: it waits and is allocated as soon as the payment is recorded. | Example | F-0231 | F-0236 | Charge total | |---|---:|---:|---:| | Payment applied (in this order) | 48,940.00 MXN | 52,316.40 MXN | 101,256.40 MXN | | Refund of 60,000.00 MXN | −7,683.60 MXN | −52,316.40 MXN | −60,000.00 MXN | | Balance that reopens | 7,683.60 MXN | 52,316.40 MXN | | - A charge that paid **a single** invoice assigns the whole refund to that invoice. - Refunds of charges from before October 2026 have no allocation: they only count in the balance if their charge paid a single invoice. - An **ACH** bank debit only supports **full** refunds. --- # Cord Payments Overview URL: https://docs.cordhq.app/en/docs/pagos/resumen Last updated: 2026-10-11 Collect by card from the quote, the invoice or the portal; in beta, bank transfer with a reference and direct debit. SPEI in Mexico, Mercado Pago in LatAm. **Cord Payments** is the system you use to accept card payments, transfers that reconcile on their own (SPEI in Mexico and bank transfer with a reference in EUR, GBP, and USD), bank debit (SEPA, ACH, Bacs, or Canadian pre-authorized debit), or manual-transfer payments directly from a quote, an invoice, or your client's invoice portal. The money lands in your own payments account and from there it is paid out to your bank account at the [frequency you choose](/en/docs/pagos/depositos) in **Settings › Payments › Payouts**: daily, weekly, monthly, or manual. On payments in Mexican pesos (MXN), Cord charges a per-transaction fee that you see and accept before you start collecting. On payments in any other currency, Cord applies no platform fee today. See the [full fee schedule](/en/docs/pagos/condiciones). In Mexico, Brazil, Colombia, Argentina, Chile, and Peru you can also collect with [Mercado Pago](/en/docs/pagos/mercado-pago), using your own Mercado Pago account. Start now Use Cord to accept online payments from the same quote link, automatically reconcile the payments that go through Cord, and — in Mexico, once your Digital Seal Certificate (CSD) is uploaded — stamp the CFDI for your sales. Find your use case → ## Goodbye manual reconciliations In many businesses, receiving a payment means: asking the client to email the transfer receipt, sales forwarding it to finance, and finance searching for the exact deposit in the bank portal the next day to cross-reference it against the quote. **Cord Payments eliminates this process for online payments.** Every online payment —by card, SPEI, bank transfer with a reference, or bank debit— is tied to its quote or its invoice and changes its status as soon as it is confirmed, with no receipts to cross-check by hand. ### What you will learn in this section: **Activate and collect** 1. **[Accepting a payment](/en/docs/pagos/aceptar):** What your customer sees when paying from the quote or invoice link. 2. **[Connect your account](/en/docs/pagos/onboarding):** Verifying your business, documents by country, phone capture, and account statuses. 3. **[Cord Payments fees](/en/docs/pagos/condiciones):** How much Cord charges by method and currency, and how the fee is activated. 4. **[Payment methods](/en/docs/pagos/metodos):** Card, SPEI, bank transfer with a reference, bank debit, Mercado Pago, and manual transfer by country and currency, and how each one is confirmed. 5. **[Mercado Pago](/en/docs/pagos/mercado-pago):** The second online payment rail, with your own account. **Payment models** 6. **[Upfront and balance](/en/docs/pagos/anticipos):** How to charge a percentage today and the rest later. 7. **[Installment payment plans](/en/docs/pagos/cuotas):** An overdue balance split into monthly installments from the same link. 8. **[Monthly retainers](/en/docs/pagos/igualas):** An automatic monthly card charge. 9. **[Credit terms](/en/docs/pagos/credito):** Due on receipt and Net 7 to Net 90, and when payment is enabled. **Tracking the money** 10. **[Payments dashboard](/en/docs/pagos/dashboard):** Balance, payouts, fees, disputes, and recent payments. 11. **[Payouts to your bank](/en/docs/pagos/depositos):** Frequency, statuses, history, payout account by country, and paused payouts. 12. **[Refunds](/en/docs/pagos/reembolsos)** and **[disputes and chargebacks](/en/docs/pagos/disputas):** What to do when something doesn't go as expected. **Invoicing** 13. **[Tax invoicing by country](/en/docs/pagos/facturacion):** CFDI 4.0 in Mexico (PUE or PPD, payment complement, global invoice, and replacement), invoices registered with Verifactu in Spain (beta), standard invoices with sales tax, VAT, or GST/HST in other markets (authorized by the tax authority in Argentina, Brazil, Chile, Colombia, and Peru when issuing is active), and quotas per plan. 14. **[Create, issue, and collect invoices](/en/docs/pagos/facturas-emitidas):** The full life of an invoice and its balance. 15. **[Recurring invoices](/en/docs/pagos/facturas-recurrentes):** Repeat an invoice every month without re-entering it. 16. **[E-invoicing](/en/docs/pagos/factura-electronica):** Factur-X, XRechnung, Peppol BIS, and Facturae for every invoice of an EU business, and issuing through an approved platform in France. The detail of each of the 12 countries —taxes, tax ID, document, authority, status, and online payments— lives in **[Invoicing by country](/en/docs/pagos/paises/resumen)**, with one page per country. **Collections and treasury** 17. **[Automatic payment reminders](/en/docs/pagos/recordatorios):** The email ladder before and after the due date. 18. **[Invoice portal](/en/docs/pagos/portal-facturas):** One link per client with all their invoices, their balance per currency, and paying several at once. 19. **[Automatic payments](/en/docs/pagos/cobro-automatico):** Your client saves a method and Cord charges each invoice on its due date, with retries and notices. 20. **[Receivables and operating collections](/en/docs/pagos/cartera-cobranza)** and **[AI collections](/en/docs/pagos/cobranza-ia):** How to follow up on what you're owed. 21. **[Treasury and FX Lock](/en/docs/pagos/tesoreria-fx):** Cash-flow forecast and locked exchange rates. ## Direct charges to your own account Cord Payments uses **direct charges**: when your customer pays, the payment is recorded in your own payments account, in your business's name — it never passes through a Cord account. From there, the money is paid out to your bank account at the payout frequency you choose. Cord isn't a middleman for the money — it's the software layer that orchestrates the transaction, verifies your identity, and calculates the fee — in Mexico, it also issues the CFDI for that fee (see [Fiscal invoicing by country](/en/docs/pagos/facturacion)). This also means you're the merchant of record for every payment — not Cord. You're responsible to your customer for the goods or services sold, and to the bank for any chargeback. See [Fees and advantages](/en/docs/pagos/condiciones) for the details. ## What's new See [what's new in payments and invoicing](/en/docs/pagos/mejoras-confiabilidad): changes to invoice payments, credit notes, downloads from the invoice link, and plans. --- # Treasury and FX Lock URL: https://docs.cordhq.app/en/docs/pagos/tesoreria-fx Last updated: 2026-10-11 Where to see your cash-flow forecast, the status of late interest, and 30-day FX coverage. ## Where each thing lives This document covers three distinct financial tools in Cord that sometimes get confused with each other because they all touch "money", but they live in different parts of the app: - **Cash-flow forecasting** 90 days out is the **Cash flow · 90 days** report in **Reports** (`/app/informes`), not in Revenue › Payments. It requires the Pro plan or higher. It's an analytics report, separate from the [Cord Payments dashboard](/en/docs/pagos/dashboard) that shows what you've already collected. - **Late-payment interest** appears in **Settings › Approvals** (currently suspended; see below). - **FX Lock** is a property of each individual quote in the editor, not a separate panel. ## 90-Day Cash Flow In **Reports › Cash flow · 90 days** (Pro plan or higher), the report cross-references the credit terms of your open quotes with each client's **real payment behavior history**. If a client has Net 30 terms but historically pays 15 days late on average, the forecast adjusts the expected incoming capital based on that real behavior — it doesn't assume everything gets paid exactly on the due date — giving you a more realistic view of your 90-day liquidity. ## Late-Payment Interest Automatic application is suspended while the country-by-country legal review is completed. Settings displays any historical rate as inactive, and the monthly process creates no new charges. Cord keeps previously recorded charges so balances and audit history remain traceable. ## Currency coverage (FX Lock) Selling in another currency shouldn't be a gamble. When you quote in a currency other than the one your books use, Cord locks the exchange rate and carries it all the way through to the invoice. ### Which currency applies where Cord keeps two currencies apart, end to end: - **The selling currency** is the one you enter prices in. It's what your client sees on the link, what the email says, and what their card is charged in. - **Your accounting currency** is your business's own (Settings › General). It's the one your books are kept in. If they're the same — the normal case — there's nothing to set up. If you pick a different selling currency in step 3 of the editor (**Terms**, the **Which currency are you quoting in?** field), the currency coverage panel appears right there. On an invoice, the field is called **Invoice currency**. ### 30-day FX Lock When you save a quote in another currency, Cord takes that day's exchange rate and **locks it for 30 days**: - **Protection cushion:** you add a margin on top of the day's rate to absorb volatility during the credit window. In the editor you choose **Light** (+1%), **Normal** (+2%, the default), or **Cautious** (+5%). - **Certainty on both sides:** your client knows exactly what they pay in their currency, and you know the rate your books will see even if the market moves between approval and payment. - **The invoice states it:** the document is issued in the selling currency and prints the exchange rate applied plus the total converted to your accounting currency. In Mexico that's the TipoCambio the SAT requires on a CFDI that isn't in pesos. ### No exchange rate, no quote The exchange rate comes from a dated market source. If it can't be retrieved at that moment — the source is down, or that currency pair isn't available — Cord **won't save the quote**, and tells you why. That may look strict, and it's deliberate: a made-up exchange rate isn't visible when you save, it's visible weeks later on an invoice with the wrong amount. If it happens, try again in a moment or quote in your business's own currency. ### Online payments and currencies Card payments work in the quote's currency. The transfer that reconciles on its own only exists in the currency of your business's country rail: SPEI in pesos in Mexico and, as a new feature, [bank transfer with a reference](/en/docs/pagos/transferencia-referencia) in EUR (Spain, Germany, and France), GBP (United Kingdom), and USD (United States). If you quote in another currency, your client pays by card. --- # Bank transfer with a reference URL: https://docs.cordhq.app/en/docs/pagos/transferencia-referencia Last updated: 2026-10-11 Get paid by SEPA, UK, or ACH and wire transfer with automatic reconciliation: one fixed account per client, a reference on each payment, where it's offered, what happens if your client transfers less or more, and how refunds work. This feature is new and may not be enabled on your account yet. If you don't see it, write to us. ## What it is It's the automatic reconciliation Cord already does with [SPEI in Mexico](/en/docs/pagos/metodos#automatic-spei), brought to businesses in Spain, Germany, France, the United Kingdom, and the United States. Your client gets the details of a bank account to pay you and a **reference** for each payment. When the transfer arrives, Cord identifies it, records the payment on the document, and recalculates the balance, without anyone looking for the deposit in the bank. The money goes into your [payments account](/en/docs/pagos/onboarding) and from there to your bank on your [payout schedule](/en/docs/pagos/depositos), just like a card payment. ## Rails by country Cord offers the rail that matches your business's country, only in its currency: | Your business's country | Rail | Currency | Details your client receives | |---|---|---|---| | Spain, Germany, and France | SEPA transfer | EUR only | Account holder, IBAN, and BIC | | United Kingdom | Faster Payments, Bacs, or CHAPS | GBP only | Account holder, sort code, and account number | | United States | ACH or domestic wire | USD only | Account holder (or beneficiary), routing number (ABA), and account number | | Mexico | SPEI | MXN only | One CLABE per invoice. See [Automatic SPEI](/en/docs/pagos/metodos#automatic-spei) | - **Spain gets a French IBAN.** The payment processor doesn't issue Spanish IBANs, so businesses in Spain get an IBAN from France. It's a SEPA account like any other: your client transfers in euros from their bank just as they would to a Spanish account. Businesses in Germany get a German IBAN and businesses in France, a French one. - **In the United States, never an international wire.** Your client can pay by ACH or domestic wire. The details don't include SWIFT, because an international wire can't be refunded. - **Canada, Brazil, Colombia, Argentina, Chile, and Peru** don't have this rail. In Canada your client can pay with [pre-authorized debit](/en/docs/pagos/domiciliacion). ## One fixed account per client, one reference per payment Outside Mexico, the account belongs **to your client**: the same one for every invoice and quote they pay you, on every visit. What changes is the **reference**, which is unique to each payment. - **Cord reconciles by the reference first.** That's why the instructions show it at the top, highlighted, with the note to put it in the transfer's reference field. - **If a transfer arrives without a reference**, it's applied to that same client's open payment with the exact amount. If it doesn't match any, it stays as a balance in your client's favor (see [If they transfer less or more](#if-they-transfer-less-or-more)). - **There are never two open transfer payments for the same invoice.** If your client opens the transfer again, they see the same payment with the same reference. In Mexico each invoice has its own CLABE: money sent to that CLABE can only pay that invoice. See [SPEI on the invoice link](/en/docs/pagos/metodos#spei-on-the-invoice-link). ## Requirements - **Country and currency:** a business in Spain, Germany, France, the United Kingdom, or the United States, and a document in the rail's currency (EUR, GBP, or USD). If the document is in another currency, the transfer isn't offered. - **An active payments account** and the method activated on your account by the payment processor. - **A client linked to the document.** The account belongs to the client, so without a client there's no one to assign it to. In the preview of an invoice without a client, the link tells you; your client doesn't see the option. - **Payment settings permission** to turn it on. ## Turn it on 1. Open **Settings › Payments › Payment methods** with the **Payment settings** permission. Your payments account has to be active; before that, the Cord Payments methods appear locked. 2. Under **Online payments**, turn on your country's transfer: **Automatic SEPA transfer** (Spain, Germany, and France), **Automatic bank transfer** (United Kingdom), or **Automatic ACH and wire** (United States). 3. Cord requests the method from the payment processor for your account. While it's under review, it isn't offered to any client yet. 4. Once the processor activates it, it appears on your invoice links and on your quotes' payment page in the rail's currency, as long as the document has a linked client. Turning it off stops offering it on new payments. Each method shows its status next to its name: **In review** while the processor turns it on, **Active** once it's offered, and **Unavailable: check your verification** if your payments account is missing a requirement. The **Your client will see** line at the top only counts what's **Active**. ## What your client sees ### On the invoice link If you also accept cards, your client chooses between **Card** and **Bank transfer** under **Payment method**; if you only have the transfer, they go straight to **Pay [amount] by bank transfer**. Choosing it shows the **Bank transfer instructions**: - The **reference**, highlighted with **Copy**, with the note to put it in the transfer's reference field. - The outstanding **amount** for that payment, with its currency. - The rail's account details, each with **Copy**. - The **Print or save PDF** button. With **Pay another amount**, your client transfers only part of the balance: that payment carries its own reference and the rest stays as the invoice balance. Cord caps the partial payment at the real balance. ### The account holder, exactly as shown (EUR) For SEPA transfers, the instructions show the **account holder** with the note to enter it exactly as shown. If the name doesn't match, the bank may hold the transfer. ### On the quote's payment page With card and transfer turned on, your client chooses **Card** or **Bank transfer** on the payment page. Each part of the charge (deposit, balance, or installment) is a payment with its own reference. From the instructions they can also press **Email these to me**, which sends them to the client email on file for the quote (up to three emails every ten minutes per link). ## How it's confirmed When the transfer for the full amount of the payment arrives, Cord records it on the invoice without you doing anything, recalculates the balance, and, if it reaches zero, marks it **Paid**. On the quote, the charge becomes paid and the quote changes status. In the invoice detail the payment shows as **Wire transfer**, and in Revenue › Payments, as **Bank transfer**. Confirmation depends on the bank's notice and **isn't always instant**. If your client already transferred, they should refresh the link before trying a card. ## If they transfer less or more - **Less.** What arrived is held for that payment but isn't recorded yet: the invoice history notes the incomplete transfer with what arrived and what's missing, and your client sees the outstanding amount when they open the transfer again. The payment is recorded when the rest arrives, to the same account and with the same reference. If they try to pay by card in the meantime, Cord asks them to finish the transfer. - **More, or with no open payment.** Only the requested payment is recorded; the difference stays **in your client's favor** and isn't your business's money. If your client has another transfer payment waiting for funds in that currency, it's applied there; otherwise, the history of their oldest open invoice says so. If they have none, Cord's team gets an alert: write to us to arrange the return. - **If nobody applies it**, the processor tries to return it to your client after 75 days. ## Refunds A transfer payment that came in through the **invoice link** is refunded from the invoice detail, fully or partially, up to 180 days after the charge. Your client receives an email to provide the bank account the money goes back to, so the invoice needs their email; until they provide it, the refund stays **pending** and doesn't reopen the balance. If they don't respond within 45 days, the refund isn't completed and the money stays as a balance in their favor in your payments account: write to us to return it. A transfer payment on a **quote** is returned outside Cord: when you request the refund in Revenue › Payments, Cord creates the task **Send the [amount] bank transfer refund** and you make the transfer from your bank. See [Refunds](/en/docs/pagos/reembolsos). ## Fee Outside MXN, Cord charges no platform fee on the transfer. The payment processor applies its own terms. See [Cord Payments fees](/en/docs/pagos/condiciones). ## Limits - Only in the rail's currency: EUR in Spain, Germany, and France; GBP in the United Kingdom; USD in the United States. - Only on the invoice link and the quote's payment page. Not in the [client portal](/en/docs/pagos/portal-facturas), [automatic payments](/en/docs/pagos/cobro-automatico), or [retainers](/en/docs/pagos/igualas): from the portal, your client opens each invoice and pays it from its link. - Needs a client linked to the document. - On the quote, it only exists on the payment page with a method selector. If your account still uses the previous payment page, the transfer outside Mexico only appears on invoices: write to us. - No international wire or SWIFT. ## Common problems **My client doesn't see the transfer.** The document isn't in the rail's currency, it has no linked client, the method is turned off in **Settings › Payments › Payment methods**, or the processor hasn't activated it on your account yet. **My client transferred without the reference.** If the amount exactly matches one of their open payments, it's applied there. If not, it stays as a balance in their favor and is applied to their next transfer payment in that currency. **My client's bank held the transfer (EUR).** Check with them that the account holder was entered exactly as shown in the instructions. **My client paid two invoices with a single transfer.** Each payment has its reference. Whatever doesn't belong to a payment stays in their favor; ask them to make one transfer per invoice with its reference. ## Related - [Payment methods](/en/docs/pagos/metodos) - [Bank debit](/en/docs/pagos/domiciliacion) - [Accept a payment](/en/docs/pagos/aceptar) - [Refunds](/en/docs/pagos/reembolsos) - [Invoicing by country](/en/docs/pagos/paises/resumen) - [Cord Payments fees](/en/docs/pagos/condiciones) --- # All products and features URL: https://docs.cordhq.app/en/docs/productos Last updated: 2026-10-11 The complete Cord catalog: quotes, signature, chat, payments, invoices, AI collections, reports, workflows, integrations, API, portal and branding, team and SSO, with the minimum plan for each capability. Each card shows the **minimum plan** where the capability is available. Higher plans include everything in the lower ones. When a feature depends on the country, the card says so. Full caps and allowances are in [Your Cord subscription](/en/docs/cuenta/suscripcion). Quote Quotes Build proposals with line items, live margins, validity and terms. Free includes 5 active quotes and 5 sends per month. Minimum plan: Free. Quote with AI Paste text or upload a photo or PDF and the AI builds the line items from your catalog for you to review. 3 builds per month on Free; 20, 50 and 500 on Starter, Professional and Scale. Minimum plan: Free. Products, discounts and taxes Catalog or free-form lines, discounts and the tax of each line, named after your country's tax. Minimum plan: Free. Discounts and coupons A discount on the subtotal by percentage or amount, and coupons with a code, validity dates, currency, and usage cap for quotes, invoices, and the API. Minimum plan: Free. Catalog, kits and volume pricing Products and services with cost and margin, a suggested tax per product, one-click kits, quantity tiers and CSV import. Free allows 50 products; Starter, 500. Minimum plan: Free. Currencies and locked exchange rate Quote in another currency and lock the exchange rate when quoting to protect your margin. Minimum plan: Free. Preview and sending Share the link by email, WhatsApp or by copying it, and check how your client will see it. Minimum plan: Free. Follow-up and internal approvals Quote list and board. Live presence and client attention from Professional; internal approvals by discount, amount or margin from Scale. Minimum plan: Free. Negotiate and close Chat and counteroffer Your client comments on each line or the whole proposal and sends counteroffers from the same link. Minimum plan: Free. Approval with evidence The client approves with their name and Cord keeps the approved version, date, time and IP as technical evidence. Supports partial approval by line. Minimum plan: Free. Client portal Announcement, welcome, comments and layout of the link your client sees. Removing Cord branding from Starter. Minimum plan: Free. Get paid Cord Payments Card payments inside the link, paid out to your account. Mexico, the United States, Canada, Spain, the United Kingdom, Germany and France. Minimum plan: Free. Mercado Pago Online payments in Brazil, Colombia, Argentina, Chile and Peru, and an alternative in Mexico. Minimum plan: Free. Payment methods Card, bank transfer with instructions, transfer with automatic reconciliation (SPEI in Mexico; with a reference in EUR, GBP, and USD), and SEPA, ACH, Bacs, or pre-authorized bank debit on invoices. Minimum plan: Free. Fees Which fee applies to each payment by method and currency, and which payments carry none. Minimum plan: Free. Upfront and balance Charge a percentage on approval and the rest later, from the same link. Minimum plan: Free. Monthly retainers Turn a quote into an automatic monthly card charge. In countries with Cord Payments. Minimum plan: Free. Credit terms Due on receipt or Net terms of 7, 15, 30, 45, 60, and 90 days, with a per-client credit limit as an exposure signal. Minimum plan: Free. Invoice portal One link per client with all their invoices, their balance in each currency, and paying several in a single charge. Minimum plan: Free. Automatic payments Your client saves a card or their bank account and Cord charges each invoice on its due date, with retries and notices. In the countries with Cord Payments. Minimum plan: Free. Payments dashboard Charges, payouts and balances of your account in one place. Minimum plan: Free. Refunds Full or partial refunds of online payments, with their own permission. Minimum plan: Free. Disputes and chargebacks When a client disputes a card charge: evidence, response and deadline. Minimum plan: Free. Invoice Invoices and credit notes Invoices with number, PDF, payment link, partial payments and credit notes. 10 commercial invoices per month on Free and unlimited from Starter. Minimum plan: Free. CFDI 4.0 (Mexico) Stamping with your own CSD, SAT keys per product and CFDI to customers abroad. 30, 200 and 500 tax invoices per month on Starter, Professional and Scale. Minimum plan: Starter. Invoicing by country Which document Cord issues in each market: CFDI 4.0 with payment complement in Mexico, and authorized invoices in Argentina, Brazil, Chile, Colombia, and Peru when issuing is active. In Spain, the invoice is registered with the AEAT through Verifactu (beta) from Starter, with your electronic certificate. US sales tax by address from Starter. Minimum plan: Free. From quote to invoice Issue the invoice for an approved quote without retyping data. Minimum plan: Free; tax invoices from Starter. Recurring invoices Repeat an invoice every month with its data frozen; each issuance is its own document. Minimum plan: Professional. Collections and AI Receivables and collections Receivables from quotes and invoices, aging, promises and reminders. Minimum plan: Professional. Autonomous collections with AI An agent that follows up on overdue balances, with your approval or automatically. Minimum plan: Professional. Treasury and FX Lock Cash-flow forecast and currency coverage for what you quote in other currencies. 90-day cash flow from Professional. Minimum plan: Free. Management and reports Home KPIs with change against the previous period, pipeline and pending follow-ups, with customizable widgets and a widget library. Minimum plan: Free. Clients and statements Directory with terms, credit, tax details and statement. Free allows 50 clients; Starter, 500. Minimum plan: Free. Tasks Team to-dos with an assignee, priority, due date, and an email every morning with what's due today and overdue. Minimum plan: Free. Notifications Alerts by email, Slack or Microsoft Teams depending on the event. Minimum plan: Free. Reports 15 reports: sales, clients, products, payments, taxes, finance, repeat purchase, and team members, with comparison and CSV export. Forecast from Starter; Finance, 90-day cash flow, and Collections from Professional. Minimum plan: Free. Custom reports Group and measure your way, save the report for the team, and get it every Monday or every 1st with the CSV attached. Minimum plan: Free. Automate Cord Workflows "When this happens, do this": alerts, tasks, messages to the client and more. 1 active workflow on Free, 5 on Starter, no cap from Professional. Minimum plan: Free. Integrations HubSpot, Shopify, Google Sheets, Excel, Gmail, QuickBooks Online, Xero, Slack, Microsoft Teams, WhatsApp Business, Make, Zapier and n8n. Minimum plan: Free. Developers REST API Quotes, clients, products, invoices and collections through the API. 100 requests per month on Free; 1,000, 5,000, 10,000 and 50,000 on paid plans. Minimum plan: Free. Webhooks Signed events with durable delivery. Manual redelivery from Professional. Minimum plan: Free. MCP server Connect AI assistants to your account. Agent governance from Scale. Minimum plan: Free. CLI Sign in, integrate your project and listen to webhooks from the terminal. Minimum plan: Free. Cord Elements The embeddable quote builder for your site, with React, Web Components and your own appearance. Minimum plan: Free. OAuth for apps External apps connect with OAuth 2.0 instead of asking you for an API key. Minimum plan: Free. Cord Workbench API keys, webhooks, events, logs and the health of your integration. Minimum plan: Free. Account, brand and team Set up with AI Your brand, taxes, catalog and templates proposed from your website and price list. Minimum plan: Free. Branding Logo, colors and typography on the portal, quotes, PDF and emails. Minimum plan: Free. Custom domain Your links from a subdomain of your company. Minimum plan: Professional. Team, roles and security Required 2FA, sessions and allowed domains on every plan; invitations, roles and audit log from Professional. Minimum plan: Free. Enterprise SSO SAML 2.0 sign-in with your identity provider and the option to require it. Minimum plan: Scale. --- # Get Started URL: https://docs.cordhq.app/en/docs Last updated: 2026-10-10 Official Cord documentation to create quotes, close deals, collect payments, invoice, automate follow-up and integrate your systems in the 12 available markets. Cord is a quote-to-cash platform: it covers the sales cycle from proposal to payment. You build a quote —by hand, from a kit or with AI— and your client receives it in a link where they discuss it, counteroffer, approve with technical evidence and pay online. Then Cord issues the invoice, tracks receivables, follows up on overdue balances and shows you how your business is doing. All with your brand, in each sale's currency and with per-person permissions. Cord is available in 12 countries: Mexico, the United States, Canada, Brazil, Spain, the United Kingdom, Germany, France, Colombia, Argentina, Chile and Peru. In Mexico, the United States, Canada, Spain, the United Kingdom, Germany and France you collect online with Cord Payments; in Brazil, Colombia, Argentina, Chile and Peru, with [Mercado Pago](/en/docs/pagos/mercado-pago), which also works in Mexico. Every account invoices with its country's tax: sales tax in the United States, VAT in the United Kingdom, GST/HST and QST in Canada. In Mexico, Cord stamps CFDI 4.0 with your CSD; in Germany and France the invoice also goes out as XRechnung or Factur-X. See what changes in each market in [Invoicing by country](/en/docs/pagos/facturacion). Create an account Sign up with email or Google, choose your country, and Cord sets up your currency, taxes and payment methods. You start on the Free plan, with no card required. Follow the Create your account guide or go straight to the developer reference. Create a free account → ## First steps This is the actual order in which Cord guides you. Each step links to its full guide. 1. **Sign up and verify your email.** With email and password, Cord sends you a verification link; with Google you go straight in. [Create your account](/en/docs/cuenta/crear-cuenta). 2. **Set up your workspace.** A four-step wizard asks for your company name, country, role, industry and what you will use Cord for. The country sets your currency, time zone and the taxes your account starts with. 3. **Set up with AI (optional).** Give Cord your website or price list and review the proposed brand, catalog and taxes. [Set up with AI](/en/docs/cuenta/configurar-con-ia). 4. **Prepare your business.** Your [brand](/en/docs/cuenta/marca), your tax details (in Mexico, your [CSD](/en/docs/cuenta/csd)) and the message of your PDF and [portal](/en/docs/cuenta/portal-cliente). 5. **Build your catalog.** Products, kits and clients, one by one or by CSV. [Import your catalog](/en/docs/cuenta/catalogo). 6. **Create and send your first quote.** [Create a quote](/en/docs/cotizacion/resumen) and [send it](/en/docs/cotizacion/envio). 7. **Turn on online payments.** Connect [Cord Payments](/en/docs/pagos/onboarding) or [Mercado Pago](/en/docs/pagos/mercado-pago), depending on your country. 8. **Collect and invoice.** [Accept a payment](/en/docs/pagos/aceptar) and issue the [invoice](/en/docs/pagos/facturas-emitidas). 9. **Automate your follow-up.** Publish your [first workflow](/en/docs/automatizacion/workflows/primer-workflow). 10. **Invite your team.** From the Professional plan. [Team, permissions and security](/en/docs/cuenta/equipo-seguridad). ## Explore the documentation The documentation has five sections, one per tab at the top. Get started Your account, setup, the app and Settings maps, and your subscription. Quote and close Quotes with AI, products and discounts, sending, chat, approval and sales management. Get paid and invoice Cord Payments, Mercado Pago, deposits, retainers, credit, invoices and collections. Automate Workflows that take the next step on their own and integrations with your other tools. Developers REST API, webhooks, CLI, MCP server, OAuth and Cord Elements. All products The complete catalog of what Cord does, with the minimum plan for each feature. ### Get started - [Create your account](/en/docs/cuenta/crear-cuenta) and [configure it](/en/docs/cuenta/configuracion) - [Set up with AI](/en/docs/cuenta/configurar-con-ia) - [Complete app map](/en/docs/operacion/mapa-de-la-app) and [Settings map](/en/docs/cuenta/mapa-de-ajustes) - [Team, permissions and security](/en/docs/cuenta/equipo-seguridad) - [Your Cord subscription](/en/docs/cuenta/suscripcion) ### Quote and close - [Create a quote](/en/docs/cotizacion/resumen) and [generate it with AI](/en/docs/cotizacion/ia) - [Products and pricing](/en/docs/cotizacion/productos) and [advanced options](/en/docs/cotizacion/opciones) - [Preview and sending](/en/docs/cotizacion/envio) - [Chat and negotiation](/en/docs/interaccion/chat) and [approval and evidence](/en/docs/interaccion/firma) - [Quote management](/en/docs/gestion/cotizaciones), [clients](/en/docs/gestion/clientes), [tasks](/en/docs/gestion/tareas) and [reports](/en/docs/gestion/informes) ### Get paid and invoice - [Payments overview](/en/docs/pagos/resumen) and [how to accept a payment](/en/docs/pagos/aceptar) - [Connect your account (KYC)](/en/docs/pagos/onboarding), [methods](/en/docs/pagos/metodos) and [fees](/en/docs/pagos/condiciones) - [Upfront and balance](/en/docs/pagos/anticipos), [retainers](/en/docs/pagos/igualas) and [credit](/en/docs/pagos/credito) - [Invoices](/en/docs/pagos/facturas-emitidas), [recurring invoices](/en/docs/pagos/facturas-recurrentes) and [invoicing by country](/en/docs/pagos/facturacion) - [Receivables and follow-up](/en/docs/pagos/cartera-cobranza) and [AI collections](/en/docs/pagos/cobranza-ia) ### Automate - [Cord Workflows](/en/docs/automatizacion/workflows) and [your first workflow](/en/docs/automatizacion/workflows/primer-workflow) - [Ready-made ideas](/en/docs/automatizacion/workflows/ideas) - [Integrations](/en/docs/automatizacion/integraciones): HubSpot, Shopify, QuickBooks Online, Xero, Slack, Make, Zapier and more ### Developers - [Developer overview](/en/docs/desarrolladores/empezar/resumen) and [your API key](/en/docs/desarrolladores/empezar/apikey) - [API reference](/en/docs/desarrolladores/referencia) - [Webhooks](/en/docs/desarrolladores/herramientas/webhooks), [CLI](/en/docs/desarrolladores/herramientas/cli) and [MCP server](/en/docs/desarrolladores/herramientas/mcp) - [Cord Elements](/en/docs/desarrolladores/herramientas/elements/resumen) More resources What's new What changed in payments, invoices, security and plans, and how it helps your operations. Service status Cord's current availability and ongoing incidents. llms.txt An index of Cord designed for AI assistants and tools that read the documentation. Support site Answers to common questions, quick guides and contact with the team. Developer resources Set up an API key and explore the API, webhooks, MCP and Cord Elements. Cord roadmap Which features are available, in development or planned. Integrations Connect Cord with your CRM, store, accounting, spreadsheets and messaging.