In connector mode the QuickBooks owner connects once to your app, for an agreed time. After that, reports are pulled when the owner clicks in your app. FinShare doesn't ask them again for each pull: your app's API call is the approval.
Because that moves the per-pull approval into your app, connector mode is turned on per account by FinShare. On an account without it, the connector endpoints return 403 connectors_not_enabled. To ask about it, email support@finshare.io.
Vetting Vault uses connector mode: the person providing the data connects QuickBooks once per deal, then answers each document request from QuickBooks with a click.
Your responsibility
Only call the pull endpoint when the person who connected QuickBooks takes an action in your app. Don't pull on a timer, on another user's click, or in bulk. FinShare records who your app said clicked, in the audit log, with every pull.
How it works
- Create a connector.
POST /v1/connectorsreturns a request ofkind: "connector"and aconsent_url. It has no reports of its own. - The owner connects. They see "Connect your QuickBooks to <your app>", connect at Intuit, confirm the company, choose how long to stay connected, and click Connect <Company>. Nothing is pulled.
- You get
request.approvedwithdata.kind: "connector". The connection is live. - The owner clicks in your app. You call
POST /v1/connectors/:id/pullswith the reports. FinShare pulls them at once. - Reports arrive by webhook, the same as any request:
report.readyandround.delivered, carrying the pull'sexternal_ref.
Create a connector
curl https://app.finshare.io/v1/connectors \
-H "Authorization: Bearer fl_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: deal-4471-connector" \
-d '{
"access_days": 180,
"requester": { "name": "Dana Reyes", "email": "dana@harborpartners.example", "org": "Harbor Partners" },
"owner": { "name": "Sam Ortiz", "email": "sam@ortizplumbing.example" },
"message": "Ortiz Plumbing data room",
"external_ref": "deal-4471",
"return_url": "https://app.yourproduct.com/deals/4471"
}'| Field | Default | Notes |
|---|---|---|
access_days | 180 | How long the connection may stay live, up to your account's maximum. The owner may choose less. |
requester | name required; email and org optional, as for requests. | |
owner | Optional prefill. | |
message | What the connection is for, shown to the owner. A deal name works well. | |
external_ref | Your id for the connector. | |
return_url | As in Embedding. | |
link_expires_in_days | 14 | 1 to 60. |
What the owner agrees to
The connect page shows different promises from a standard request:
- Connecting shares nothing by itself. Reports are pulled only when you choose to send them, one request at a time.
- We only read reports. We never change anything in your QuickBooks.
- Intuit's sign-in screen describes general access to your accounting data. That is the only permission Intuit offers apps. FinShare uses it only to pull the reports you send.
- You can disconnect at any time: in the app you connected from, from the link we email you, or inside QuickBooks.
- When the connection ends, we revoke our QuickBooks access. Reports already delivered stay with the requester.
Make sure your UI keeps the first promise: the owner should see which reports a click will send before they click.
Pull reports
curl https://app.finshare.io/v1/connectors/req_Zt6Hb3Nq8Wm2Kc5Rx9Lv/pulls \
-H "Authorization: Bearer fl_live_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: filereq-9120-click-1" \
-d '{
"items": [
{ "report_type": "profit_and_loss", "period": { "kind": "trailing_months", "months": 12 }, "options": { "summarize_by": "month" } },
{ "report_type": "ar_aging_detail", "period": { "kind": "as_of" } }
],
"period_end": "2026-09-30",
"external_ref": "filereq-9120",
"actor": { "name": "Sam Ortiz", "email": "sam@ortizplumbing.example" }
}'items: 1 to 25 report items, the same format as requests.period_end: defaults to the last completed month end. Can't be in the future.external_ref: your id for this pull. It's on every webhook about the pull.actor: the person who clicked. Required. Your app vouches that this is the person who connected.
Returns 201 with a request for the pull. Its connector_request_id is the connector's id. It's active immediately, with one round already approved.
Pulls can't be refreshed or rolled forward. For updated numbers, make a new pull.
Status, links and disconnecting
| Call | On the connector | On a pull |
|---|---|---|
GET /v1/requests/:id | Connection status, approval summary | Rounds and reports |
POST /v1/requests/:id/consent_link | A fresh connect link while still awaiting the owner | |
POST /v1/requests/:id/cancel | Disconnects: ends every pull under it and revokes the QuickBooks token, unless another live approval needs that company | Ends access for that pull |
If the connection lapses
If Intuit stops accepting the connection, you get connection.needs_reconnect and the owner is emailed a reconnect link. Pull calls return 409 needs_reconnect until they reconnect. You get connection.reconnected when they do.
What the owner can see
The owner's manage page shows the connector as "Connected to <your app>", with every report delivered under any pull, and a Disconnect from <your app> button. If they disconnect, you get grant.revoked for the connector and for each open pull.