SOURCE_ID: import_from_google_sheets NAME: Import Google Sheets CATEGORY: CRM Import rows from a Google Sheets spreadsheet tab into Floqer — either as a one-time backfill or as an ongoing source that picks up newly added rows. Imported rows become available to your Floqer workflows for enrichment, scoring, outreach, and the like. 1. ENDPOINTS Source identifier (used in every endpoint path): `import_from_google_sheets`. POST /api/v1/sources/import_from_google_sheets/preview Scope: sources:read Returns a sample page of rows from the chosen sheet tab, without creating anything. Use this to validate the spreadsheet / tab selection and inspect column shape before committing. POST /api/v1/sources/import_from_google_sheets Scope: sources:write Creates the source, imports existing rows immediately (when `import_existing_data`), and — for an active source — picks up newly added rows going forward. Returns `source_instance_id` (the new source's UUID). POST /api/v1/sources/import_from_google_sheets/options/ Scope: sources:read Resolves dynamic option values for a field. Two `field_name` values matter: `spreadsheet_id` and `sheet_name` (see §5). GET /api/v1/sources//data Scope: sources:read Paginated rows imported into the created source. `` is the UUID returned by Create. Query: `page_no` (default 1), `page_size` (default 20, max 200). Source-agnostic; see concepts.txt §10. POST /api/v1/sources//sync Scope: sources:write Connects the created source to a workflow and (by default) backfills it with the source's current rows. `` here is the UUID returned by Create. Body: { workflow_id, field_mapping, push_existing?, run? } — `field_mapping` keys are `input.` references on the target workflow, values are the source fields to pull. This step is source-agnostic; see concepts.txt §10 for the full shape. PATCH /api/v1/sources//status Scope: sources:write Pause or resume an active source by UUID. Body: {"status": "active" | "paused"}. Source-agnostic. Every endpoint for this source first verifies the API-key user has an active Google Sheets connection. Missing connection → 424. 2. PULL MODE (ONE-TIME VS ONGOING) `pull_mode` is required on the create endpoint (not on preview). Values: "static" One-time import. The source imports the sheet's current rows once (when `import_existing_data`) and stops — it does not watch for new rows. "active" Ongoing source. Imports the current rows initially (when `import_existing_data`) AND picks up newly added rows as they appear, until `expiration_date`. 3. BODY SHAPE (PREVIEW + CREATE) Field names are snake_case. Unknown top-level keys are rejected with 400 — the body is strict. Preview accepts: spreadsheet_id required: the Google Spreadsheet ID sheet_name required: the tab name within the spreadsheet import_existing_data boolean; optional trigger_column string; optional Create accepts all the preview fields plus: name required: display name for the new source pull_mode required: "static" | "active" expiration_date ISO date (YYYY-MM-DD); optional (active source only) 4. FIELD CATALOGUE spreadsheet_id (string) — required The Google Spreadsheet ID. Resolve it with the `spreadsheet_id` dynamic-options call (§5). sheet_name (string) — required The tab name within the spreadsheet (not a numeric sheet id). Resolve it with the `sheet_name` dynamic-options call, passing the chosen `spreadsheet_id` as context (§5). import_existing_data (boolean) — optional When true, the rows already present in the sheet are imported. Leave it on to backfill; turn it off when you only care about rows added going forward (active source). trigger_column (string) — optional The column used to detect newly added rows for an active source. A new row is picked up when this column is populated. name (string) — required on create only Human-readable display name for the source. pull_mode (string) — required on create only "static" (one-time) or "active" (ongoing, watches for new rows). See §2. expiration_date (string) — optional, active only ISO date (YYYY-MM-DD) after which an active source stops watching for new rows. 5. DYNAMIC OPTIONS Two dynamic-options field names are available for this source. Both are POSTs to /api/v1/sources/import_from_google_sheets/options/ with body `{ "context"?: {...} }`. spreadsheet_id Context: none. Returns: {value: , label: , extras}. Use the returned `value` directly as `spreadsheet_id`. sheet_name Context: { "spreadsheet_id": "" } — REQUIRED. Returns: {value: , label: , extras}. Use the returned `value` directly as `sheet_name`. Connection check: each call verifies the API-key user has an active Google Sheets connection first. Missing connection → 424. 6. HOW TO CONFIGURE END-TO-END Typical flow for an AI agent building a Google Sheets import source: Step 1 — Resolve the spreadsheet POST /api/v1/sources/import_from_google_sheets/options/spreadsheet_id Body: {} Pick the spreadsheet's `value` as `spreadsheet_id`. Step 2 — Resolve the tab POST /api/v1/sources/import_from_google_sheets/options/sheet_name Body: {"context": {"spreadsheet_id": ""}} Pick the tab's `value` as `sheet_name`. Step 3 — Preview before committing POST /api/v1/sources/import_from_google_sheets/preview Body: { "spreadsheet_id": "", "sheet_name": "Sheet1", "import_existing_data": true } Check the returned `data[]` row shape (one key per sheet column). Iterate until you're happy — preview never creates anything. Step 4 — Create the source POST /api/v1/sources/import_from_google_sheets Body: + the create-only fields: "name": "", "pull_mode": "static" | "active", "expiration_date": "2027-01-01" // optional, active only Response: { "status": 201, "data": { "source_instance_id": "", "name", "created_at" }} Step 4b — (Optional) Poll imported rows while the import runs GET /api/v1/sources//data?page_no=1&page_size=20 ( = UUID from Step 4) Row keys match the sheet's column headers. `total_count` grows until the import finishes. Step 5 — Sync the source into a workflow (so its rows flow downstream) POST /api/v1/sources//sync ( = UUID from Step 4 ) First build `field_mapping`: a. GET /api/v1/workflows → pick the destination workflow_id. b. GET /api/v1/workflows//sheets//inputs → each input has a `reference` like `{{input.email}}`. c. Map each workflow input (reference WITHOUT braces) to a source field — the source fields are the sheet's column headers. Body: { "workflow_id": "", "field_mapping": { "input.email": "Email", "input.name": "Name" }, "push_existing": true, "run": "all" } See concepts.txt §10 for the full sync semantics (source-agnostic). The initial import runs asynchronously — the create call returns as soon as the source is created and the import has started, not when rows have finished arriving. 7. KEY NOTES - Google Sheets connection is mandatory. If the API-key user has no active Google Sheets connection, every endpoint (preview, create, options) returns 424 ("User is not connected to 'googleSheets'."). Surface this as a "connect Google Sheets first" CTA. - `sheet_name` is the tab NAME (e.g. "Sheet1"), not a numeric sheet id. Use the `sheet_name` dynamic-options call to get exact names. - An active source watches for newly added rows. `trigger_column` controls which column's presence marks a row as new. - `import_existing_data` controls whether the rows already in the sheet are backfilled on create. - Credits are consumed when the source is created. If credit consumption fails (e.g. insufficient balance), the source is still created but its import can't start; the API returns 402 so you can top up and retry. - Use PATCH /status to pause an active source and resume it later without recreating it. 8. WHERE IT FITS UPSTREAM (in Google Sheets) Rows live in a spreadsheet tab in the user's Google account. Column headers become the field names on imported rows. THIS SOURCE Creates a Google Sheets import source. On creation it imports the sheet's current rows (when `import_existing_data`); an active source also picks up newly added rows until `expiration_date`. DOWNSTREAM (in Floqer) Imported rows become available to your Floqer workflows — wire the source into a workflow to enrich, score, or run outreach on each row. 9. WHEN TO USE - One-time backfill of a spreadsheet into a Floqer workflow: `pull_mode: static`, `import_existing_data: true`. - Watch a spreadsheet for new rows and run a workflow on each one as it's added: `pull_mode: active`, `trigger_column: ""`. When you instead want to push data OUT of Floqer INTO a sheet, use the Google Sheets action templates (e.g. `google_sheet_add_data`, `google_sheet_upsert_row`) inside a workflow — see the action catalog in action-catalog.txt. Last updated: 2026-06-02. Reference: https://floqer.com/docs/reference