ROKIConnect

QuickBooks

QuickBooks Online (Intuit) — API Accounting v3, OAuth 2.0

3 a 5 horas de trabajo real del dueño y el contador. Se reparte así: crear la cuenta de desarrollador de Intuit y la app, 1 hora. Revisar y ajustar la configuración de QuickBooks (numeración de facturas, permisos de usuario, cuenta de depósito), 1 a 2 horas con el contador presente. El clic de autorización OAuth, 10 minutos. Conseguir o redactar las URLs de política de privacidad y contrato de usuario final, 1 a 2 horas (más si hay que escribirlas de cero). Pruebas de aceptación con cobros reales chicos al final, 1 hora.del comercio
35 a 55 horas de quien programa, y esto es un piso, no un promedio optimista. Desglose: flujo OAuth completo con almacén cifrado de tokens y renovación automática con rotación, 10 a 14 horas (es lo más largo y lo que más se subestima). Receptor de webhook con validación de firma, protección contra reenvíos y respuesta rápida, 6 a 8 horas. Traducción DocNumber a Id interno más creación del Payment con LinkedTxn, 6 a 8 horas. Control de duplicados e idempotencia, 4 a 6 horas. Tarea de respaldo que consulta GET /payments/{id}, 3 a 4 horas. Bitácora, alertas y panel mínimo para ver qué pasó, 4 a 6 horas. Infraestructura (VPS, dominio, TLS, despliegue), 3 a 5 horas. Pruebas end to end en sandbox, 4 a 6 horas. Si la empresa necesita multimoneda, sumale 8 a 12 horas más.de programacion
Entre 38 y 60 horas de trabajo efectivo. Pero en el calendario son de 4 a 8 semanas hasta el primer cobro real registrado.en total

La diferencia entre 60 horas de trabajo y 8 semanas de calendario no es pereza de nadie: es la revisión de Intuit. Según la documentación de Intuit, la revisión técnica lleva en promedio unos 20 días desde que se inicia, y ese plazo depende de su agenda, de cuántos problemas encuentren y de qué tan rápido los corrijas. Si te rechazan el cuestionario de evaluación, el reloj arranca de nuevo. Vos podés tener todo funcionando perfecto en sandbox en dos semanas y seguir esperando un mes más para tocar datos reales. Dos consejos que ahorran semanas: primero, mandá el cuestionario de evaluación apenas tengas el conector andando en sandbox, no al final. Es la tarea de mayor demora y puede correr en paralelo mientras terminás lo demás. Segundo, no le prometas al dueño una fecha de salida hasta que Intuit apruebe. Prometé una fecha para "listo y probado en sandbox", que esa sí depende de vos. Y sumale, aparte de todo esto, entre 1 y 3 horas por mes de mantenimiento permanente: revisar que la renovación de tokens no se haya caído, renovar el certificado TLS, y conciliar los cobros que hayan quedado colgados.

Quien lo hace

El dueño solo NO puede. Hace falta el socio implementador, sí o sí.

Repartilo así:

Dicho sin vueltas: si no hay alguien que pueda mantener un servidor andando, esta integración no se sostiene. No la empieces.

Que tiene que existir antes de empezar

1
Suscripción activa de QuickBooks Online y confirmar en qué región/edición está la empresa

Donde: Ícono de engranaje (arriba a la derecha) > "Account and settings" (en interfaz en español, "Cuenta y configuración") > pestaña "Billing & subscription" / "Facturación y suscripción"

Sin suscripción viva no hay compañía y por lo tanto no hay realmId, que es el identificador con el que la API sabe a qué empresa escribir. Además necesitás ver la edición regional: QuickBooks Online no se comercializa oficialmente en Honduras, y la moneda base de la compañía se fija al crearla y NO se puede cambiar después. Averiguá esto ANTES de prometer nada, no después.

2
Un usuario con rol de administrador de la compañía

Donde: Ícono de engranaje > "Manage users" / "Administrar usuarios"

Solo un administrador puede autorizar una aplicación de terceros. Un usuario con rol limitado va a ver la pantalla de conexión y va a fallar sin un mensaje claro de por qué. No pierdas media hora con eso.

3
Numeración de factura controlada por vos (custom transaction numbers)

Donde: Ícono de engranaje > "Account and settings" > "Sales" / "Ventas" > sección "Sales form content" > "Custom transaction numbers", en ON

El external_reference de ROKI ("FAC-001") tiene que coincidir con el DocNumber de la factura en QuickBooks. Si QuickBooks numera solo y vos no controlás ese campo, no hay forma de casar el cobro con la factura y toda la integración pierde sentido.

4
Definida la cuenta contable donde cae el cobro

Donde: Ícono de engranaje > "Chart of accounts" / "Plan de cuentas"

En el objeto Payment esto es DepositToAccountRef. Si no lo mandás, QuickBooks deposita el cobro en "Undeposited Funds" ("Fondos no depositados") y alguien tiene que armar el depósito a mano, cobro por cobro. Que el contador elija y lo deje por escrito antes de programar.

5
El cliente ya creado como "Customer" en QuickBooks

Donde: Menú lateral "Sales" / "Ventas" > "Customers" / "Clientes"

El objeto Payment exige CustomerRef. No podés registrar un pago contra un cliente que no existe. Si vendés a consumidor final ocasional, definí un cliente genérico y usá siempre ese.

6
Multimoneda, SOLO si la moneda base de la compañía no es la moneda en que cobra ROKI

Donde: Ícono de engranaje > "Account and settings" > "Advanced" / "Avanzado" > sección "Currency" / "Moneda" > "Multicurrency"

ROKI manda montos en lempiras en unidades decimales. Si la compañía tiene otra moneda base, necesitás CurrencyRef y ExchangeRate en cada Payment. Ojo: activar multimoneda en QuickBooks Online es IRREVERSIBLE. No lo prendas para probar.

7
Cuenta de desarrollador de Intuit, creada con un correo del comercio

Donde: https://developer.intuit.com > "Sign up" / "Sign in"

Es la cuenta dueña de la aplicación y de las llaves de producción. Si la crea el consultor con su correo personal, el día que se va el comercio pierde el control de su propia integración. Usá algo tipo sistemas@tucomercio.com con la contraseña en poder del dueño.

8
Un servidor conector propio (VPS) con HTTPS público

Donde: Fuera de QuickBooks: es infraestructura del comercio o del implementador

Es el requisito que la gente descubre tarde y duele. Necesitás: puerto 443/TCP abierto de entrada desde internet, certificado TLS válido emitido por una autoridad certificadora pública (autofirmado NO sirve, ni para Intuit ni como destino del webhook de ROKI), un nombre de dominio propio, y salida a internet por 443 hacia quickbooks.api.intuit.com, oauth.platform.intuit.com y aura.roki.systems. El almacén donde guardás los tokens debe ser cifrado y con permisos de archivo restringidos al usuario del servicio (nada de 0644 ni de dejarlos en un repositorio).

Los pasos

  1. 1. Crear la cuenta de desarrollador y la aplicación en el portal de Intuit
    Entrá a https://developer.intuit.com y registrate. Después creás la app desde el panel de desarrollador y elegís la plataforma "QuickBooks Online and Payments". Advertencia honesta: Intuit rediseñó y renombró este portal varias veces en los últimos años, y sus páginas de documentación se arman con JavaScript, así que no siempre se puede verificar el rótulo exacto de cada botón. Los nombres que sí aparecen en la documentación y en el soporte oficial de Intuit son "My Hub", la sección "Keys & OAuth" bajo "Development" y bajo "Production" en la barra lateral, y la pantalla "Keys and credentials". Si en tu pantalla el botón se llama distinto, buscá la sección que muestre "Client ID" y "Client Secret": esa es. De entrada la app queda en modo desarrollo, con llaves de desarrollo. Eso es lo normal y con eso vas a trabajar las primeras semanas.
  2. 2. Pedir el alcance com.intuit.quickbooks.accounting y entender que no hay uno más chico
    Al configurar la app tenés que habilitar el origen de datos de contabilidad (Accounting). Ese es el alcance com.intuit.quickbooks.accounting, y es el único que necesitás para esta integración: es el que permite leer facturas y crear el objeto Payment. Acá va algo que tenés que decirle al dueño con todas las letras: ese alcance NO se puede achicar. Según la lista de alcances de Intuit, no existe un permiso de solo lectura, ni uno limitado a facturas, ni uno limitado a pagos. com.intuit.quickbooks.accounting da acceso de lectura y escritura a la contabilidad completa de la empresa: clientes, proveedores, asientos, cuentas, todo. El principio de "permiso mínimo" acá no se puede aplicar del lado de Intuit, porque Intuit no lo ofrece. El único control real es quién tiene el Client Secret y los tokens en tu servidor. El alcance com.intuit.quickbooks.payment es otro producto (la pasarela de cobro de Intuit) y no lo necesitás: quien cobra es ROKI.
  3. 3. Cargar la Redirect URI
    En la sección "Keys and credentials" de tu app, en "Redirect URIs", tocás "Add URI", pegás la dirección de tu conector y guardás con "Save". Si no guardás, no queda: es un error clásico. Ejemplo: https://conector.tucomercio.com/qbo/callback Tres reglas que Intuit no perdona: - Tiene que ser HTTPS. localhost con http no lo acepta en producción. - Tiene que coincidir carácter por carácter con la que mandás en la petición de autorización. Una barra de más al final y te tira "redirect_uri query parameter value is invalid". - Development y Production tienen listas SEPARADAS de Redirect URIs. Cargar la de desarrollo no te sirve para producción. Podés tener hasta 25 por app.
  4. 4. Crear la compañía sandbox y probar ahí primero
    Desde tu cuenta de desarrollador entrás a "My Hub" > "Sandboxes" y tocás "Add" (o "Add a sandbox company"), eligiendo por ejemplo QuickBooks Online Plus. La sandbox es una empresa de QuickBooks falsa, con datos de juguete, para que rompas cosas sin miedo. Ahí probás con las llaves de desarrollo y contra la URL base de sandbox. Direcciones base (confirmadas en la documentación de Intuit): - Sandbox: https://sandbox-quickbooks.api.intuit.com - Producción: https://quickbooks.api.intuit.com La diferencia entre sandbox y producción es exactamente eso: distinta URL base, distinto par de Client ID/Client Secret, distinta lista de Redirect URIs, y datos que no son reales. El flujo de OAuth es idéntico y usa los MISMOS endpoints de autorización y token en los dos casos. Lo que la sandbox NO te prueba: la sandbox es una compañía estadounidense en dólares. Si tu empresa real opera en otra moneda, todo el camino de conversión sigue sin probar. Tenelo presente.
  5. 5. El flujo de OAuth 2.0: el clic del dueño y de dónde sale el realmId
    Esta es la parte central y la que más se malentiende. Nadie escribe un usuario y contraseña de QuickBooks en tu sistema. Lo que pasa es esto: PASO A — tu conector manda al administrador de QuickBooks a esta dirección (endpoint confirmado en el documento de descubrimiento OpenID de Intuit, https://developer.api.intuit.com/.well-known/openid_configuration): https://appcenter.intuit.com/connect/oauth2?client_id=TU_CLIENT_ID&response_type=code&scope=com.intuit.quickbooks.accounting&redirect_uri=https://conector.tucomercio.com/qbo/callback&state=un_valor_aleatorio PASO B — el dueño ve una pantalla de Intuit, elige la empresa y aprieta el botón de conectar. Ese es el único momento en que interviene una persona. PASO C — Intuit lo devuelve a tu Redirect URI con tres cosas en la dirección: ?code=AB11...&state=un_valor_aleatorio&realmId=9130350000000000 Ese realmId es el identificador de la empresa. Es lo que hace que todo funcione y lo tenés que guardar junto con los tokens. Va dentro de cada llamada a la API: /v3/company/{realmId}/... . No es un dato secreto, pero sin él no podés escribir en ninguna parte. Y es POR EMPRESA: si el mismo consultor conecta cinco comercios, son cinco realmId con cinco juegos de tokens. No lo dejes fijo en el código. PASO D — tu conector canjea ese code por tokens contra el endpoint de token (también confirmado en el documento de descubrimiento): POST https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer Authorization: Basic <client_id:client_secret en base64> Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=AB11...&redirect_uri=https://conector.tucomercio.com/qbo/callback Y recibís access_token, refresh_token y sus vencimientos. Para revocar la conexión el endpoint es https://developer.api.intuit.com/v2/oauth2/tokens/revoke.
  6. 6. Guardar y renovar los tokens: acá se rompen la mayoría de las integraciones
    Leé esto dos veces, porque es la causa número uno de que una integración con QuickBooks "deje de andar sola" a los pocos meses. - El access token dura 1 hora. Nada más. - El refresh token dura hasta 100 días. - PERO el refresh token ROTA: cada vez que renovás, Intuit puede devolverte un refresh token nuevo, y en la práctica lo hace alrededor de una vez por día. Cuando devuelve uno nuevo, el anterior queda muerto. Regla operativa: guardá SIEMPRE el último refresh token que te devolvieron, pisando el anterior, en la misma transacción. Si tu sistema se queda con uno viejo, la próxima renovación te da invalid_grant, la conexión se cae, y la única salida es que el dueño vuelva a hacer el clic de autorización a mano. Y el otro escenario feo: si el comercio se toma vacaciones y el conector no llama a la API durante más de 100 días, el refresh token vence y la conexión se cae igual. Un conector sano renueva por su cuenta aunque no haya ventas. Agregale al conector una alerta: si falla la renovación, que le avise a alguien por correo o WhatsApp el mismo día. Si no, se enteran cuando ya hay treinta cobros sin registrar.
  7. 7. Crear el cobro en ROKI y mandarle el enlace al cliente
    Cuando en QuickBooks se emite una factura que se va a cobrar por ROKI, tu conector llama a ROKI: POST https://aura.roki.systems/api/connect/v1/payments Authorization: Bearer sk_live_... (usá sk_test_... mientras probás contra la sandbox) Content-Type: application/json { "amount": 1500.00, "external_reference": "FAC-001", "name": "Factura 001" } El amount va en unidades decimales, en lempiras. NUNCA en centavos: 1500.00 son mil quinientos lempiras, no quince lempiras. Esto conviene porque coincide con cómo QuickBooks maneja TotalAmt, que también es decimal. No hay conversión de centavos en ningún lado de esta integración, y está bien que así sea. El external_reference tiene que ser el DocNumber exacto de la factura en QuickBooks. Es el hilo que va a unir las dos puntas más adelante. ROKI responde 201 con { id, checkout_url, transaction_id: null }. Guardá el id de ROKI junto al Id interno de la factura de QuickBooks en una tabla tuya: la vas a necesitar. El checkout_url se lo mandás al cliente por correo o por WhatsApp, o lo ponés como enlace de pago. Ese enlace es lo que el cliente abre para pagar.
  8. 8. Recibir el webhook de ROKI en el conector (no en QuickBooks)
    Cuando el cliente paga, ROKI manda un aviso firmado a una URL pública HTTPS. Esa URL es la de TU conector, por ejemplo https://conector.tucomercio.com/roki/webhook. QuickBooks no participa de este paso: mirá el punto sobre webhooks más abajo. Validá la firma antes de creerle a nada. En la cabecera ROKI-Signature viene t=<unix>,v1=<hmac_sha256_hex>. Tomás el timestamp, le pegás un punto, le pegás el CUERPO CRUDO tal cual llegó (sin parsearlo, sin reordenarlo, sin reformatearlo), calculás HMAC-SHA256 con tu secreto y comparás. Compará con una función de tiempo constante, no con un == común. Y rechazá lo que tenga un timestamp de hace más de unos minutos, para que nadie te reenvíe un aviso viejo. Si el evento es payment.approved, el pago se acreditó y recién ahí seguís. Respondé rápido con 200 y hacé el trabajo pesado en segundo plano. Un webhook que tarda se reintenta, y un reintento mal manejado te duplica el cobro en la contabilidad.
  9. 9. Encontrar el Id interno de la factura (el paso que casi todos se saltean)
    Acá está la trampa técnica más costosa de toda la integración, y conviene entenderla aunque no programes. En QuickBooks, una factura tiene DOS números: - el DocNumber, que es "FAC-001", el número que ve el cliente y el que vos elegiste; - el Id, que es un número interno de QuickBooks tipo "249", que vos no elegís y que el cliente nunca ve. Para registrar el pago, QuickBooks exige el Id interno. No acepta el DocNumber. Y ROKI te devuelve el external_reference, que es el DocNumber. Entonces hay un paso de traducción obligatorio: GET https://quickbooks.api.intuit.com/v3/company/{realmId}/query?query=select Id, Balance, TotalAmt, CustomerRef from Invoice where DocNumber = 'FAC-001' Authorization: Bearer <access_token> Accept: application/json De ahí sacás el Id, el CustomerRef y el Balance pendiente. Atención con esto: el intérprete de consultas de QuickBooks a veces confunde valores con guiones y los toma como fechas. Un DocNumber tipo "FAC-001" está justo en la zona de riesgo. Probalo con tu formato real de numeración antes de dar la integración por lista. Si te da problemas, cambiá el formato de numeración (por ejemplo sin guiones) mientras estás a tiempo. Alternativa más segura si podés: guardá el Id interno de QuickBooks en tu propia tabla cuando creás el cobro en ROKI (paso 7), y así en este paso no consultás nada, solo leés tu tabla. Es más rápido y no depende del parser de Intuit.
  10. 10. Registrar el pago contra la factura: el objeto Payment con Line y LinkedTxn
    Ahora sí, el registro contable. En QuickBooks un pago es un objeto Payment que tiene un total y una lista de líneas, y cada línea dice a qué documento se aplica mediante LinkedTxn. Esa es toda la lógica: el LinkedTxn es la soga que ata el pago a la factura. POST https://quickbooks.api.intuit.com/v3/company/{realmId}/payment?minorversion=<fijá una versión y dejala fija> Authorization: Bearer <access_token> Content-Type: application/json Accept: application/json { "CustomerRef": { "value": "69" }, "TotalAmt": 1500.00, "TxnDate": "2026-08-16", "PaymentRefNum": "ROKI-9f3a2", "PrivateNote": "Cobro ROKI Connect, referencia FAC-001", "DepositToAccountRef": { "value": "35" }, "Line": [ { "Amount": 1500.00, "LinkedTxn": [ { "TxnId": "249", "TxnType": "Invoice" } ] } ] } Campo por campo, en castellano: - CustomerRef: el cliente. Obligatorio, y tiene que ser el MISMO cliente de la factura. - TotalAmt: el total cobrado, decimal. Los 1500.00 que vinieron de ROKI. - TxnDate: la fecha con la que entra el asiento. Usá la fecha de acreditación, no la de emisión. - PaymentRefNum: poné acá el identificador del pago de ROKI. Es tu rastro de auditoría cuando el contador pregunte de dónde salió esa plata. - PrivateNote: nota interna. Dejá escrito el external_reference. Cuesta nada y salva horas. - DepositToAccountRef: la cuenta que definió el contador. Si lo omitís, va a "Undeposited Funds" y alguien tiene que depositarlo a mano. - Line[].Amount: cuánto de este pago se aplica a ESA factura. - Line[].LinkedTxn[].TxnId: el Id INTERNO de la factura (el "249" del paso anterior, no "FAC-001"). - Line[].LinkedTxn[].TxnType: la palabra "Invoice". Si un solo pago cancela varias facturas, agregás más elementos al arreglo Line, uno por factura, y la suma de los Amount tiene que dar TotalAmt. Antes de mandar esto, verificá que no exista ya un Payment con ese mismo PaymentRefNum. Si el webhook llega dos veces y vos creás dos pagos, la factura queda pagada al doble y le dejás un problema al contador.
  11. 11. Confirmar que la factura quedó saldada
    No des por bueno un 200. Volvé a consultar la factura y mirá el campo Balance: GET https://quickbooks.api.intuit.com/v3/company/{realmId}/invoice/249 Si Balance quedó en 0, la factura está saldada. Si quedó en algo distinto de 0, hubo un pago parcial o algo salió mal, y eso tiene que quedar registrado en tu bitácora y, si podés, generar un aviso. La factura también te va a mostrar un arreglo LinkedTxn apuntando al Payment: es el mismo vínculo visto desde el otro lado. Sirve para auditar. Guardá en tu bitácora, para cada operación: el id de ROKI, el external_reference, el realmId, el Id de la factura, el Id del Payment creado, y la fecha. El día que haya una discusión de plata, esa tabla es toda tu defensa.
  12. 12. El respaldo cuando el webhook no llega
    Los webhooks se pierden. Se cae internet, se reinicia el servidor, vence un certificado. Asumilo desde el diseño, no como parche. Dejá una tarea programada que corra cada 15 o 30 minutos, tome todos los cobros que vos creaste en ROKI y que siguen sin registrar en QuickBooks, y consulte: GET https://aura.roki.systems/api/connect/v1/payments/{id} Authorization: Bearer sk_live_... Si el estado es aprobado y en QuickBooks no hay Payment, lo registrás con el mismo procedimiento del paso 10. La verificación de "¿ya existe este pago?" es lo que evita que el webhook y esta tarea creen el pago dos veces. Esto no es opcional. Sin este respaldo, tarde o temprano hay un cliente que pagó y una factura que en la contabilidad figura impaga.
  13. 13. Pasar a producción: llaves reales y la revisión de Intuit
    Cuando funciona todo en sandbox, pedís las llaves de producción en la sección "Production" > "Keys & OAuth" de tu app. Intuit no te las entrega por pedirlas. Antes exige, como mínimo: - Completar el perfil de la app. - Una URL de política de privacidad y una URL de contrato de usuario final (End User License Agreement). Tienen que ser direcciones que carguen de verdad. Si la app es solo para uso interno del comercio, el soporte de Intuit ha indicado que alcanza con una URL de reemplazo, pero si la vas a ofrecer a terceros necesitás documentos reales. - Cargar la Redirect URI de producción, que es una lista aparte de la de desarrollo. - Completar el cuestionario de evaluación de la app (app assessment questionnaire). Esto es obligatorio para TODA app que toque datos de producción, incluidas las privadas que nunca se publican en el App Store. Negarse a completarlo puede terminar en que Intuit te corte el acceso a producción. Qué te pregunta ese cuestionario, para que no te agarre desprevenido: dónde está hospedada la aplicación, cada cuánto hacés análisis de vulnerabilidades, si usás un sistema de monitoreo de seguridad (SIEM), cómo está la seguridad de red, si exigís autenticación de múltiples factores, cómo ciframos los datos en tránsito y en reposo, cómo manejás autenticación y autorización, y si tenés certificación ISO 27001 o auditoría SOC 2. Acá va la parte incómoda, y prefiero decírtela ahora: un consultor chico con un VPS compartido no tiene buenas respuestas para la mitad de esas preguntas. No es imposible pasar, pero no es un trámite. Preparalo con tiempo. Y los tiempos: según la documentación de Intuit, la revisión técnica lleva en promedio unos 20 días desde que se inicia, y ese plazo depende de la agenda de revisiones, de cuántos problemas encuentren y de qué tan rápido los corrijas. Si te rechazan, el reloj vuelve a empezar. Intuit además revisa las apps una vez por año, o más seguido si se le antoja: esto no es un permiso que se saca una vez y listo. No le pongas fecha de salida al dueño hasta que Intuit apruebe.

Como llega el webhook

QuickBooks Online NO puede recibir el webhook de ROKI. Ni con desarrollo a medida, ni pagando más. No existe.

Es importante entender por qué, porque la palabra "webhook" aparece en la documentación de Intuit y confunde a todo el mundo:

QuickBooks Online SÍ tiene webhooks, pero van en la dirección contraria. Son avisos que Intuit MANDA HACIA AFUERA, hacia una URL tuya, cuando algo cambia dentro de QuickBooks (se creó una factura, se modificó un cliente). Son de salida. QuickBooks no expone ninguna dirección donde un tercero como ROKI pueda golpear la puerta y decir "cobré 1500 lempiras". Como sistema en la nube y cerrado, QuickBooks solo acepta que le escriban por su API autenticada con OAuth, nunca por un aviso anónimo entrante.

Entonces, la alternativa, que además es la única arquitectura posible:

EL CONECTOR EN EL MEDIO. Hace falta un servicio propio, hospedado por el comercio o por el implementador, con una dirección pública HTTPS. Ese servicio:

  1. Recibe el webhook de ROKI en, por ejemplo, https://conector.tucomercio.com/roki/webhook
  2. Valida la firma ROKI-Signature (HMAC-SHA256 sobre timestamp + "." + cuerpo crudo)
  3. Responde 200 enseguida
  4. Traduce el external_reference "FAC-001" al Id interno de la factura en QuickBooks
  5. Llama a la API de QuickBooks con el access token vigente y crea el objeto Payment con su Line/LinkedTxn
  6. Registra todo en su bitácora

Lo que ese conector necesita, concreto: puerto 443/TCP abierto de entrada desde internet, certificado TLS emitido por una autoridad certificadora pública (autofirmado no sirve: ROKI no le va a entregar el aviso), un dominio propio, y salida por 443 hacia quickbooks.api.intuit.com y oauth.platform.intuit.com. Nada de puerto 80, nada de IP pelada, nada de túneles caseros tipo ngrok para producción.

Un detalle que juega a favor: como QuickBooks Online es un servicio en la nube, tu conector puede vivir en cualquier parte con internet. No tiene que estar en la oficina del comercio, no hay que abrir puertos en el router del negocio ni exponer la red interna. Podés poner el conector en un VPS y listo. Esta es la única ventaja real que QuickBooks Online tiene sobre un ERP instalado en la oficina, y no es poca.

Ahora, lo que nadie te dice: ese conector es software que hay que mantener andando para siempre. Renueva tokens todos los días, vence el certificado cada 90 días, se cae el VPS. Si nadie lo cuida, la integración muere en silencio y el comercio se entera cuando el contador cierra el mes. Definí quién lo opera ANTES de arrancar, y ponelo por escrito.

¿Y los webhooks propios de QuickBooks? Para esta integración no los necesitás. Solo servirían si quisieras que ROKI se entere cuando alguien emite una factura nueva en QuickBooks, para generar el cobro automáticamente. Es una mejora posterior, no parte de la puesta en marcha. La sección donde se configuran está dentro de la app en el portal de desarrollador, pero no pude confirmar el rótulo exacto de esa pestaña en la documentación oficial, así que no te lo voy a inventar.

Lo que se rompe

Lo que no pudimos confirmar

Cada nombre de menu y cada puerto de esta pagina se verifico contra la documentacion oficial de la plataforma. Estos 7 puntos no se pudieron confirmar, y se dejan senalados en vez de presentarlos como ciertos:

Fuentes