Back to Quality Control Checklist

Integration and API Spec

The reference during the build: every tool connection, auth scope, field mapping, and error-handling rule.

4 pagesPDF · Technical
FS-DOC-05Technical

Integration and API Spec

Quality Control Checklist Automation

[YourCompany.com] · Operations Department · Prepared by FullSpec · [Today's Date]

This document is the authoritative integration reference for the Quality Control Checklist automation. It covers every tool connected to the workflow, the exact authentication methods and scopes required, field mappings between tools at each agent handoff, orchestration layout, credential storage, and the error handling and retry behaviour required at every integration point. The FullSpec team uses this specification to configure, connect, and validate all integrations from scratch. No integration decision should be made that contradicts the definitions here without updating this document first.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent
Google Forms
Inspector-facing checklist submission and form trigger
OAuth 2.0 (Google Workspace)
Free (personal) or Google Workspace Starter
Agent 1 (QC Review Agent)
Airtable
Central QC log, corrective action records, linked views
Personal Access Token (PAT)
Airtable Plus ($20/month)
Agent 1 (QC Review Agent), Agent 2 (Reporting Agent)
Slack
Real-time failure alerts and corrective action assignment messages
OAuth 2.0 (Slack App)
Slack Pro ($8/month) or Free with limitations
Agent 1 (QC Review Agent)
Gmail
Weekly QC summary report distribution to management list
OAuth 2.0 (Google Workspace)
Free (personal) or Google Workspace Starter
Agent 2 (Reporting Agent)
Automation platform
Workflow orchestration, scheduling, credential store, and retry logic
Internal platform credential store (per-tool OAuth or token)
Paid tier supporting webhooks and scheduled triggers ($37/month)
Both agents
Before you connect anything: every integration must be tested against a sandbox or test environment before production credentials are entered. Use a Google Forms test form, an Airtable sandbox base, a Slack test workspace or private channel, and a Gmail test account. Validate each connection end-to-end in isolation before wiring agents together. Do not use live inspection data or the production Airtable base during connection testing.
Integration and API SpecPage 1 of 4
FS-DOC-05Technical

02Per-tool integration detail

Google Forms

Acts as the entry point for all inspection data. The automation platform listens for new form submissions via the Google Forms trigger (polling the linked Google Sheet responses tab or via Apps Script webhook relay). Each submission must carry a batch or unit identifier, inspector name, timestamp, and one response row per checklist item.

Auth method
OAuth 2.0. Authenticate as the Google account that owns the form. Grant the automation platform access to the linked Google Sheets spreadsheet where responses are stored.
Required scopes
https://www.googleapis.com/auth/forms.body.readonly, https://www.googleapis.com/auth/spreadsheets.readonly, https://www.googleapis.com/auth/drive.readonly
Trigger setup
Google Forms does not natively push webhooks. Responses are written to a linked Google Sheet. The automation platform polls the linked sheet at a 2-minute interval for new rows, or an Apps Script onFormSubmit trigger posts a HTTP POST to the automation platform inbound webhook URL. The Apps Script approach is preferred for latency under 30 seconds. Store the inbound webhook URL in the credential store, not in the script.
Required configuration
Form must include fixed field IDs for: batch_id, inspector_name, inspection_type, inspection_date, and one column per checklist item with a pass/fail/na value. Field order must be locked before build. The linked Google Sheet ID must be stored in the credential store.
Rate limits
Google Sheets API: 300 read requests per minute per project, 60 requests per minute per user. At 120 inspections per month (approximately 4 per day), polling at 2-minute intervals produces well under 100 reads per day. No throttling required at current volume.
Constraints
Form structure must not change after build without updating the field mapping config. Adding checklist items requires a schema update and re-test. Offline submissions (cached on device) will arrive as a batch when connectivity resumes; the automation must handle duplicate-check logic on batch_id plus inspection_date.
// Output to QC Review Agent
form_response {
  batch_id: string,
  inspector_name: string,
  inspection_type: string,
  inspection_date: ISO8601 string,
  checklist_items: [ { item_id: string, label: string, result: 'pass'|'fail'|'na' } ],
  raw_row_index: integer
}
Airtable

Serves as the central data store for inspection records and corrective actions. Two tables are required: QC_Log (one record per inspection submission) and Corrective_Actions (linked to QC_Log via a linked record field). Both agents read from and write to this base. The Reporting Agent queries QC_Log with date filters; the QC Review Agent creates records in both tables.

Auth method
Personal Access Token (PAT). Generate a PAT from the Airtable account settings with read and write scopes. Store the token in the credential store under the key AIRTABLE_PAT. Do not use the legacy API key.
Required scopes
data.records:read, data.records:write, schema.bases:read
Webhook/trigger setup
Airtable webhooks (Airtable Automations or external webhook subscriptions via the REST API) are used by neither agent as a trigger in this build. The QC Review Agent is triggered by Google Forms; the Reporting Agent by a schedule. Airtable is write and read target only.
Required configuration
Base ID stored in credential store as AIRTABLE_BASE_ID. Table IDs for QC_Log and Corrective_Actions stored as AIRTABLE_TABLE_QC_LOG and AIRTABLE_TABLE_CORRECTIVE_ACTIONS. QC_Log schema: fields inspection_id (autonumber), batch_id (text), inspector_name (text), inspection_type (text), inspection_date (date), failed_items (long text JSON array), severity (single select: Critical, Major, Minor, Pass), status (single select: Open, In Progress, Closed), linked_ca_id (linked record to Corrective_Actions). Corrective_Actions schema: ca_id (autonumber), linked_inspection (linked record), defect_description (long text), severity (single select), assignee (collaborator), due_date (date), status (single select: Open, In Progress, Resolved), slack_message_ts (text).
Rate limits
Airtable REST API: 5 requests per second per base. At 120 inspections per month, peak write load is approximately 2 records per inspection event (QC_Log + Corrective_Actions if failure). Maximum concurrent load is well under 1 request per second. No throttling required. Add a 250ms delay between sequential writes within a single agent run to avoid 429 responses.
Constraints
Linked record fields require the record ID of the parent record, not a text value. The QC Review Agent must capture the returned record ID from the QC_Log write before creating the Corrective_Actions record. Field names are case-sensitive in the REST API; use exact names as defined in the schema above.
// Input from QC Review Agent (write to QC_Log)
POST /v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_QC_LOG}
fields: { batch_id, inspector_name, inspection_type, inspection_date,
          failed_items (JSON string), severity, status: 'Open' }

// Input from QC Review Agent (write to Corrective_Actions)
POST /v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_CORRECTIVE_ACTIONS}
fields: { linked_inspection: [record_id], defect_description,
          severity, assignee (collaborator user_id), due_date, status: 'Open' }

// Input from Reporting Agent (read QC_Log with filter)
GET /v0/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_QC_LOG}
  ?filterByFormula=AND(IS_AFTER({inspection_date}, '{7_days_ago}'),
                       IS_BEFORE({inspection_date}, '{today}'))
  &fields[]=batch_id,inspection_type,severity,status,inspector_name,inspection_date
Slack

Used by the QC Review Agent to send two distinct message types: a channel alert to the operations manager channel when a critical or major failure is detected, and a direct message to the assignee when a corrective action is created and assigned. The Slack app must be installed in the workspace with the required bot scopes before build.

Auth method
OAuth 2.0 via a custom Slack app. Create the app at api.slack.com/apps, install it to the workspace, and store the Bot User OAuth Token in the credential store as SLACK_BOT_TOKEN.
Required scopes
chat:write, chat:write.public, users:read, users:read.email, channels:read, im:write
Webhook/trigger setup
No inbound webhook is used by this integration. The automation platform posts outbound messages to Slack using the chat.postMessage API method. Store the operations manager channel ID as SLACK_OPS_CHANNEL_ID in the credential store. Do not hardcode channel names; use channel IDs which are stable.
Required configuration
SLACK_BOT_TOKEN in credential store. SLACK_OPS_CHANNEL_ID in credential store. Corrective action assignee Slack user IDs mapped to failure categories in a config lookup table stored in the credential store or orchestration platform config (not hardcoded in the workflow). The Airtable Corrective_Actions table must store the slack_message_ts of the alert message to allow threaded follow-up if needed.
Rate limits
Slack Web API: Tier 3 rate limit for chat.postMessage is 1 request per second (burst up to 100 per minute). At 120 inspections per month, maximum alert volume is 120 messages per month, well under any rate ceiling. No throttling required.
Constraints
Block Kit message payloads must not exceed 3000 characters. The alert message must include: batch_id, failed checklist items, severity label, Airtable corrective action deep link, and assigned owner. Deep links to Airtable records use the format https://airtable.com/{AIRTABLE_BASE_ID}/{AIRTABLE_TABLE_CORRECTIVE_ACTIONS}/{record_id} and must be constructed dynamically from the returned record ID.
// Output: channel alert (chat.postMessage)
POST https://slack.com/api/chat.postMessage
Authorization: Bearer {SLACK_BOT_TOKEN}
body: {
  channel: SLACK_OPS_CHANNEL_ID,
  text: 'QC Failure Alert: {batch_id}',
  blocks: [ header, section(failed_items, severity),
            section(assignee, due_date), actions(link_to_ca) ]
}

// Output: DM to assignee (chat.postMessage)
POST https://slack.com/api/chat.postMessage
body: {
  channel: {assignee_slack_user_id},
  text: 'You have been assigned a corrective action for {batch_id}.',
  blocks: [ section(defect_description, due_date, ca_link) ]
}
Gmail

Used exclusively by the Reporting Agent to send the weekly QC summary email every Monday at 07:00. The email is sent from a designated operations sender address to a management distribution list. The message is constructed from an HTML template with placeholder substitution performed by the automation platform before sending.

Auth method
OAuth 2.0. Authenticate as the designated sender Google account (e.g. ops-reports@[YourCompany.com]). Store the refresh token in the credential store as GMAIL_REFRESH_TOKEN and client credentials as GMAIL_CLIENT_ID and GMAIL_CLIENT_SECRET.
Required scopes
https://www.googleapis.com/auth/gmail.send
Webhook/trigger setup
No inbound webhook. The Reporting Agent is triggered by a time-based schedule (cron: 0 7 * * 1, Monday at 07:00 in the operations team local timezone). The automation platform schedule node fires the agent; Gmail is a write-only output at the end of the workflow.
Required configuration
GMAIL_SENDER_ADDRESS in credential store. GMAIL_RECIPIENT_LIST (comma-separated management email addresses) in credential store. HTML email template stored in the orchestration platform config with placeholders: {{week_label}}, {{total_inspections}}, {{pass_count}}, {{fail_count}}, {{pass_rate_pct}}, {{top_failure_categories}}, {{open_corrective_actions_count}}, {{open_ca_list}}.
Rate limits
Gmail API send quota: 250 quota units per second per user; each send costs 100 units. The Reporting Agent sends one email per week (52 emails per year). No rate limit risk whatsoever. No throttling required.
Constraints
The OAuth token must be refreshed using the stored refresh token before each send. Access tokens expire after 1 hour; the orchestration layer must handle token refresh automatically. If the Airtable query returns zero records for the week (e.g. holiday period), the agent must still send the email with zero counts rather than suppressing it, to confirm the automation ran.
// Output: weekly summary email (Gmail API)
POST https://gmail.googleapis.com/gmail/v1/users/me/messages/send
Authorization: Bearer {access_token}
body (RFC 2822 encoded, base64url):
  From: ops-reports@[YourCompany.com]
  To: {GMAIL_RECIPIENT_LIST}
  Subject: Weekly QC Summary - w/c {week_label}
  Content-Type: text/html; charset=utf-8
  [rendered HTML from template with substituted placeholders]
Integration and API SpecPage 2 of 4
FS-DOC-05Technical

03Field mappings between tools

The tables below define the exact field mappings at each agent handoff in the workflow. All field names are shown in their exact form as they appear in the source and destination systems. Monospace names are used throughout. Any deviation from these names requires a corresponding update to the orchestration platform field mapping config.

Handoff 1: Google Forms to Airtable QC_Log (QC Review Agent, step 1)

Source tool
Source field
Destination tool
Destination field
Google Forms / Sheets
`Timestamp`
Airtable QC_Log
`inspection_date`
Google Forms / Sheets
`Inspector Name`
Airtable QC_Log
`inspector_name`
Google Forms / Sheets
`Batch or Unit ID`
Airtable QC_Log
`batch_id`
Google Forms / Sheets
`Inspection Type`
Airtable QC_Log
`inspection_type`
Google Forms / Sheets
`[All checklist item columns]` (JSON serialised array)
Airtable QC_Log
`failed_items`
Derived by agent logic
`severity_label` (computed from rules)
Airtable QC_Log
`severity`
Derived by agent logic
`'Open'` (hardcoded initial value)
Airtable QC_Log
`status`

Handoff 2: Airtable QC_Log to Airtable Corrective_Actions (QC Review Agent, step 2, on critical or major failure only)

Source tool
Source field
Destination tool
Destination field
Airtable QC_Log
`record_id` (returned from write)
Airtable Corrective_Actions
`linked_inspection` (linked record array)
Airtable QC_Log
`batch_id`
Airtable Corrective_Actions
`defect_description` (prefixed: 'Batch: {batch_id} -')
Airtable QC_Log
`severity`
Airtable Corrective_Actions
`severity`
Derived: failure category lookup
`assignee_user_id`
Airtable Corrective_Actions
`assignee` (collaborator field)
Derived: inspection_date + 2 business days
`due_date`
Airtable Corrective_Actions
`due_date`
Derived: Slack API response
`message_ts`
Airtable Corrective_Actions
`slack_message_ts`

Handoff 3: Airtable Corrective_Actions to Slack (QC Review Agent, step 3, channel alert)

Source tool
Source field
Destination tool
Destination field
Airtable QC_Log
`batch_id`
Slack Block Kit
`header.text`
Airtable QC_Log
`failed_items`
Slack Block Kit
`section.text` (formatted list)
Airtable QC_Log
`severity`
Slack Block Kit
`section.text` (severity badge)
Airtable Corrective_Actions
`ca_id`
Slack Block Kit
`actions.url` (Airtable deep link)
Airtable Corrective_Actions
`assignee`
Slack Block Kit
`section.text` (assignee display name)
Airtable Corrective_Actions
`due_date`
Slack Block Kit
`section.text` (formatted date)

Handoff 4: Airtable QC_Log to Gmail (Reporting Agent, weekly schedule)

Source tool
Source field
Destination tool
Destination field
Derived: date range label
`week_label`
Gmail HTML template
`{{week_label}}`
Airtable QC_Log
`COUNT(record_id)` for period
Gmail HTML template
`{{total_inspections}}`
Airtable QC_Log
`COUNTIF(severity, 'Pass')`
Gmail HTML template
`{{pass_count}}`
Airtable QC_Log
`COUNTIF(severity, != 'Pass')`
Gmail HTML template
`{{fail_count}}`
Derived: pass_count / total_inspections * 100
`pass_rate_pct`
Gmail HTML template
`{{pass_rate_pct}}`
Airtable QC_Log
`inspection_type` grouped failure counts
Gmail HTML template
`{{top_failure_categories}}`
Airtable Corrective_Actions
`COUNT(status = 'Open' OR 'In Progress')`
Gmail HTML template
`{{open_corrective_actions_count}}`
Airtable Corrective_Actions
`ca_id, defect_description, assignee, due_date` (open records)
Gmail HTML template
`{{open_ca_list}}`
Integration and API SpecPage 3 of 4
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
Two separate workflows, one per agent. Workflow 1: QC Review Agent (event-driven, Google Forms trigger). Workflow 2: Reporting Agent (schedule-driven, Monday 07:00 cron). Both workflows share a single credential store within the automation platform. No cross-workflow calls are made at runtime; data sharing is exclusively via Airtable records.
Agent 1 trigger mechanism
Webhook (preferred): Apps Script onFormSubmit posts a HTTP POST to the automation platform inbound webhook URL. The platform must validate the request using a shared secret header (X-FullSpec-Secret) checked against the value stored in the credential store as FORMS_WEBHOOK_SECRET. Fallback: 2-minute polling of the linked Google Sheet responses tab if webhook relay is not available in the deployment environment.
Agent 1 webhook signature validation
The Apps Script relay sends a HMAC-SHA256 signature of the payload body using the FORMS_WEBHOOK_SECRET. The orchestration layer must verify the signature before processing. Requests failing signature validation must be dropped and logged to the platform error log with status 401.
Agent 2 trigger mechanism
Time-based schedule (poll): the automation platform cron node fires at 07:00 every Monday in the configured timezone (stored as REPORT_TIMEZONE in platform config). No external webhook is involved. The agent is self-contained and requires no inbound network exposure.
Credential store scope
All credentials are stored in the automation platform's encrypted credential store. No secrets appear in workflow node configurations, code blocks, or logs. Credential keys are referenced by name only in workflow nodes.
Shared config store
Non-secret configuration values (recipient list, channel ID, timezone, template content, failure category to assignee mapping) are stored in the platform's environment variable or config block, separate from the credential store, but also not hardcoded in nodes.

The full credential store contents required before any workflow can be activated are listed below. All values must be present and validated in the sandbox environment before switching to production credentials.

Credential store and config reference. All keys must be populated before workflow activation.
// Credential store contents (automation platform encrypted store)
// Key                          Type            Used by

GOOGLE_OAUTH_CLIENT_ID          OAuth client    Google Forms, Gmail
GOOGLE_OAUTH_CLIENT_SECRET      OAuth secret    Google Forms, Gmail
GOOGLE_FORMS_REFRESH_TOKEN      OAuth token     Google Forms (Sheets polling)
GMAIL_REFRESH_TOKEN             OAuth token     Gmail send
GMAIL_SENDER_ADDRESS            String          Gmail send (From address)
GMAIL_RECIPIENT_LIST            String          Gmail send (To, comma-separated)

AIRTABLE_PAT                    PAT token       All Airtable reads and writes
AIRTABLE_BASE_ID                String          All Airtable requests
AIRTABLE_TABLE_QC_LOG           String          QC Review Agent, Reporting Agent
AIRTABLE_TABLE_CORRECTIVE_ACTIONS String        QC Review Agent

SLACK_BOT_TOKEN                 OAuth token     Slack channel alert, Slack DM
SLACK_OPS_CHANNEL_ID            String          Slack channel alert

FORMS_WEBHOOK_SECRET            HMAC secret     Webhook signature validation

// Platform config (non-secret, environment variables)
REPORT_TIMEZONE                 String          'Australia/Sydney' (adjust per client)
SEVERITY_RULES_JSON             JSON string     QC Review Agent classification logic
ASSIGNEE_CATEGORY_MAP_JSON      JSON string     Failure category -> Airtable user ID map
CA_DUE_DATE_BUSINESS_DAYS       Integer         2 (days after inspection date)
AIRTABLE_BASE_URL               String          'https://airtable.com/{AIRTABLE_BASE_ID}'
GMAIL_EMAIL_TEMPLATE_HTML       String          Full HTML template with placeholders

05Error handling and retry logic

Every integration point in this automation has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors must be captured by the orchestration layer, logged with the triggering payload, and routed to the platform error log or a designated ops alert. The table below defines the required behaviour for each failure scenario.

Integration
Scenario
Required behaviour
Google Forms webhook
Inbound webhook signature validation fails
Drop the request immediately. Log payload hash and source IP to error log with status 401. Do not process. No retry. Alert the FullSpec ops log. Contact support@gofullspec.com if repeated.
Google Forms / Sheets polling
Sheets API returns 429 (rate limited)
Apply exponential backoff: wait 5s, retry, then 15s, then 60s. After 3 failed retries, log the error with the row index and send an alert to the platform error channel. Resume on the next poll cycle.
Google Forms / Sheets polling
Duplicate row detected (same batch_id and inspection_date already in Airtable)
Skip the record. Log the duplicate with the row index and batch_id. Do not create a second QC_Log record or Corrective_Action. No alert to Slack.
Airtable write (QC_Log)
POST returns 422 (field validation error, e.g. invalid severity value)
Halt the run for this submission. Log the full response body and the source form payload. Send a platform error alert with the batch_id. Do not proceed to Corrective_Actions or Slack. Require manual review and resubmission.
Airtable write (QC_Log)
POST returns 429 (rate limited, >5 req/sec)
Wait 250ms and retry once. If the second attempt fails, wait 2 seconds and retry a final time. If all three attempts fail, log the error, store the payload to a dead-letter queue in the platform, and alert the error channel. Do not proceed to downstream steps.
Airtable write (Corrective_Actions)
linked_inspection record ID is missing or invalid
Halt corrective action creation. Log the error with the batch_id and QC_Log write response. Raise a platform alert. The QC_Log record already exists; manual corrective action creation is the fallback. Do not send a Slack alert without a valid ca_id.
Slack chat.postMessage (channel alert)
API returns 404 (channel not found)
Log the error with the SLACK_OPS_CHANNEL_ID value. Send a fallback email to GMAIL_SENDER_ADDRESS notifying that the Slack alert failed and listing the batch_id and severity. Update SLACK_OPS_CHANNEL_ID in the credential store and retest immediately.
Slack chat.postMessage (channel alert or DM)
API returns 429 (rate limited)
Wait 1 second and retry up to 3 times with 1-second backoff between each attempt. If all retries fail, log the error with the batch_id and fall back to the Gmail fallback alert to GMAIL_SENDER_ADDRESS. Do not suppress the alert.
Slack DM (assignee notification)
User ID not found in ASSIGNEE_CATEGORY_MAP_JSON for the failure category
Send the DM to SLACK_OPS_CHANNEL_ID instead, flagging that the assignee lookup failed and manual reassignment is needed. Log the unmapped failure category so the config map can be updated.
Airtable read (Reporting Agent weekly query)
GET returns empty result set for the date range
Do not suppress the email. Render the template with zero values for all counts and include a note: 'No inspections recorded this week.' Send as normal. Log the empty result to the platform run log.
Gmail send (weekly report)
OAuth token refresh fails (expired or revoked refresh token)
Log the OAuth error with the token key name. Do not send the email. Send a platform alert to the error channel with the error detail. The FullSpec team must re-authorise the Gmail OAuth connection and reissue the refresh token. Contact support@gofullspec.com if this occurs.
Gmail send (weekly report)
send API returns 500 or 503 (transient Google error)
Retry after 2 minutes, then after 10 minutes, then after 30 minutes (3 total retries). If all retries fail, log the full error response and send a platform error alert. The weekly email is considered failed for that cycle. No automatic backfill; the FullSpec team must trigger a manual run.
Unhandled exceptions policy: any error scenario not covered by the table above must be caught by a global error handler in each workflow. The global handler must log the full error object, the triggering node name, and the input payload to the platform error log, and send a notification to support@gofullspec.com. No workflow may exit silently on an unexpected error. Silent failures are treated as a build defect requiring immediate remediation.
Integration and API SpecPage 4 of 4

More documents for this process

Every document generated for Quality Control Checklist.

Launch Plan
Operations · Owner
View
ROI and Business Case
Finance · Owner
View
Process Runbook / SOP
Operations · Owner
View
Developer Handover Pack
Technical · Developer
View
Test and QA Plan
Quality · Developer
View