FS-DOC-05Technical
Integration and API Spec
Training and Certification Tracking
[YourCompany.com] · HR Department · Prepared by FullSpec · [Today's Date]
This document is the definitive technical reference for every external service connection used in the Training and Certification Tracking automation. It covers authentication methods, required OAuth scopes, webhook configuration, field-level mappings between tools, credential store contents, and failure behaviour for every integration point. FullSpec uses this specification to configure, test, and maintain all integrations. Your team is responsible for provisioning API credentials and confirming BambooHR custom field names before the build begins.
01Tool inventory
Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Orchestration layer
Hosts both agent workflows, manages scheduling, credential store, and retry logic
Internal service account
N/A (platform subscription)
All
BambooHR
HRIS source of truth: employee records read for scan; certification fields written on renewal
API key (per-user or service account)
Essentials or higher (API access required)
Agent 1, Agent 2
Google Sheets
Certification tracking log: read for expiry data; written with reminder and completion entries
OAuth 2.0 (service account JSON key recommended)
Google Workspace (any tier) or free Google account
Agent 1, Agent 2
Gmail
Sends personalised tiered reminder emails to employees
OAuth 2.0 (delegated or service account with domain-wide delegation)
Google Workspace Business Starter or Gmail account with SMTP/API enabled
Agent 1
Slack
Sends manager notifications on expiry alerts and escalation events
OAuth 2.0 (Bot token via Slack App)
Free tier sufficient; paid required for message retention beyond 90 days
Agent 1
Typeform
Employee certificate submission form; webhook fires on each new response
OAuth 2.0 or Personal Access Token; webhook HMAC-SHA256 signature
Basic plan (webhooks available); Pro recommended for file upload size up to 10 MB
Agent 2
Google Drive
Certificate file storage; automation creates folders and uploads files on submission
OAuth 2.0 (same service account as Google Sheets if using service account)
Google Workspace (any tier) or free Google account with sufficient storage
Agent 2
Before you connect anything: provision sandbox or test credentials for every tool listed above and validate each connection end-to-end in a non-production environment before any production credentials are entered into the credential store. BambooHR test subdomains, Typeform test forms, a sandboxed Google Sheet, and a Slack test workspace should all be used during the build and QA phases.
02Per-tool integration detail
BambooHR
Used by both agents. Agent 1 (Certification Monitor Agent) reads employee records and certification custom fields daily. Agent 2 (Renewal Intake and Filing Agent) writes updated completion and expiry dates back to the employee profile on submission.
Auth method
API key passed as HTTP Basic Auth username; password field left blank. Key is generated per user or via a dedicated service account user in BambooHR Settings > API Keys.
Required scopes
BambooHR API keys are not scope-gated by OAuth; access is controlled by the permission level of the user account the key belongs to. The service account must have: read access to Employee Directory, read/write access to Custom Fields (certification type, completion date, expiry date), and read access to Job Information (for manager lookup). Do not use an admin account key in production.
Webhook / trigger setup
Not applicable for Agent 1 (poll-based). BambooHR webhooks are not used in this build; the orchestration layer polls the API on a daily schedule instead.
Required configuration
Three custom fields must exist on the BambooHR employee profile before the build begins: cert_type (text or dropdown), cert_completion_date (date), cert_expiry_date (date). Field IDs (numeric) must be retrieved from the BambooHR API at /api/gateway.php/{subdomain}/v1/meta/fields and stored in the credential store, not hardcoded. The BambooHR subdomain must also be stored in the credential store.
Rate limits
BambooHR enforces a limit of approximately 800 API requests per hour per API key. At a volume of 30 to 80 employee records scanned once daily, the daily scan will generate at most 160 requests (two calls per employee: one for directory, one for custom fields). No throttling logic is required at current volume, but exponential backoff must be implemented for 429 responses.
Constraints
The API does not support bulk field updates in a single request; each employee record requires an individual PATCH call. File attachments cannot be written to BambooHR via the standard v1 API; certificate files are stored in Google Drive only, with the Drive URL optionally written to a text custom field if desired.
// Agent 1 Read
GET /api/gateway.php/{subdomain}/v1/employees/directory
GET /api/gateway.php/{subdomain}/v1/employees/{id}?fields=cert_type,cert_expiry_date,cert_completion_date,supervisorId
// Agent 2 Write
POST /api/gateway.php/{subdomain}/v1/employees/{id}
Body: { cert_completion_date: "YYYY-MM-DD", cert_expiry_date: "YYYY-MM-DD" }Google Sheets
Used by both agents as the certification tracking log. Agent 1 reads expiry data to cross-reference and writes reminder log entries. Agent 2 writes completion status and updated dates after a successful Typeform submission.
Auth method
OAuth 2.0 via a Google Cloud service account. The service account JSON key file is stored in the credential store. The target spreadsheet must be shared with the service account email address (Editor permission).
Required scopes
https://www.googleapis.com/auth/spreadsheets (read and write to spreadsheets)
Webhook / trigger setup
Not applicable. Google Sheets does not support outbound webhooks natively. The orchestration layer polls or writes via the Sheets API v4 on a schedule or after an upstream trigger fires.
Required configuration
The Spreadsheet ID must be stored in the credential store, not hardcoded. The tracking sheet must have the following named columns in row 1: employee_id, employee_name, cert_type, cert_expiry_date, last_reminder_tier, last_reminder_date, status, completion_date, drive_file_url. The sheet tab name used by the automation must be confirmed and stored in config (default: CertTracker). A separate log tab (default: ReminderLog) receives append-only reminder entries.
Rate limits
Google Sheets API v4 allows 300 requests per minute per project and 60 requests per minute per user. Daily scans across 80 records will not approach this limit. No throttling required at current volume.
Constraints
Batch read using spreadsheets.values.get with a full range is preferred over row-by-row reads to minimise API calls. Writes use spreadsheets.values.append for log entries and spreadsheets.values.update for status changes. The automation must never delete rows; it may only update or append.
// Agent 1 Read
GET sheets/v4/spreadsheets/{spreadsheetId}/values/CertTracker!A:I
// Agent 1 Write (reminder log)
POST sheets/v4/spreadsheets/{spreadsheetId}/values/ReminderLog!A:F:append
Body: [[employee_id, employee_name, cert_type, reminder_tier, reminder_date, status]]
// Agent 2 Write (status update)
PUT sheets/v4/spreadsheets/{spreadsheetId}/values/CertTracker!G{row}:I{row}
Body: [["Complete", completion_date, drive_file_url]]Gmail
Used by Agent 1 only. Sends personalised, tiered reminder emails to employees at the 90-day, 60-day, and 30-day marks, and an overdue notice after the sequence completes.
Auth method
OAuth 2.0. If sending from a shared HR inbox (e.g. hr@[YourCompany.com]), domain-wide delegation must be enabled in Google Workspace Admin and the service account granted impersonation rights for that address. If sending from the automation platform's own Gmail OAuth app, a dedicated sending address (e.g. noreply-hr@[YourCompany.com]) is preferred.
Required scopes
https://www.googleapis.com/auth/gmail.send (send-only; do not request broader mail scopes unless inbox reading is required)
Webhook / trigger setup
Not applicable. Gmail is write-only in this build; no inbound email parsing is used. Inbound certificate submissions are handled entirely by Typeform.
Required configuration
Four email templates must be stored in the credential store or a dedicated config object (not hardcoded in workflow logic): template_90d, template_60d, template_30d, template_overdue. Each template contains placeholders: {{employee_name}}, {{cert_type}}, {{cert_expiry_date}}, {{typeform_submission_url}}. The sender address and sender display name must be stored in the credential store. The Typeform form URL (public link) must be stored in config and injected into each template at send time.
Rate limits
Gmail API allows 250 quota units per user per second; a send costs 100 units. For 80 employees across four tiers, the maximum single-run send volume is 80 emails, well within limits. No throttling required. Google Workspace accounts have a daily send limit of 2,000 messages; this build will never approach that limit.
Constraints
Attachments are not sent in reminder emails. The Typeform link is the sole call to action. HTML email bodies are supported via the Gmail API using RFC 2822 MIME format encoded in base64url. Plain-text fallback must be included in each message part.
// Agent 1 Send
POST https://gmail.googleapis.com/gmail/v1/users/{userId}/messages/send
Body (MIME, base64url encoded):
To: {employee_email}
From: {sender_address}
Subject: Action required: {cert_type} renewal due in {days_remaining} days
Content-Type: multipart/alternative
text/plain: {template_plaintext}
text/html: {template_html}Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Slack
Used by Agent 1 only. Sends a direct message to the relevant manager each time a reminder email is dispatched to an employee, and sends an escalation notification when an employee remains non-compliant after the 30-day reminder.
Auth method
OAuth 2.0 Bot token. A Slack App must be created in the Slack API dashboard (api.slack.com), installed to the workspace, and its Bot token stored in the credential store. The Bot must be invited to any private channels it needs to post to; for direct messages no channel membership is required.
Required scopes
chat:write (post messages as the bot), users:read (look up user IDs by email), users:read.email (required to resolve manager email to Slack user ID)
Webhook / trigger setup
Not applicable. Outbound messages only. No Slack Events API subscription is used in this build.
Required configuration
The Slack Bot token must be stored in the credential store. The escalation notification channel ID (for overdue alerts sent to the HR Coordinator) must be stored in config, not hardcoded. Manager Slack user IDs are resolved at runtime by calling users.lookupByEmail using the supervisor email retrieved from BambooHR. The Slack App display name and icon should be set to reflect the HR team context (e.g. display name: HR Compliance Bot).
Rate limits
Slack Tier 3 rate limit applies to chat.postMessage: 50 requests per minute. At a maximum of 80 manager notifications per daily run, all messages will be sent within two minutes with no throttling issues. A 1-second delay between requests is recommended as a courtesy to avoid burst spikes.
Constraints
Direct messages require resolving the manager's Slack user ID from their email address before calling chat.postMessage. If a manager does not have a Slack account matching their BambooHR supervisor email, the direct message step must fail gracefully and log the failure without blocking the reminder email send.
// Resolve manager Slack ID
GET https://slack.com/api/users.lookupByEmail?email={supervisor_email}
Response: { ok: true, user: { id: "U01XXXXXXX" } }
// Send direct message
POST https://slack.com/api/chat.postMessage
Body: {
channel: "{manager_slack_id}",
text: "Certification reminder sent to {employee_name} ({cert_type}, expires {cert_expiry_date})"
}Typeform
Used by Agent 2 only. The employee-facing submission form captures employee ID, certification name, completion date, new expiry date, and a certificate file upload. A webhook fires to the orchestration layer on each new response.
Auth method
Typeform Personal Access Token (PAT) stored in the credential store for API access. The webhook payload is authenticated using HMAC-SHA256 signature validation: Typeform signs each payload with a shared secret and includes the signature in the Typeform-Signature header. The orchestration layer must validate this signature before processing any submission.
Required scopes
Typeform PAT scopes: responses:read (retrieve response data and file upload URLs), forms:read (retrieve form schema for field ID mapping). Webhook registration requires: webhooks:write, webhooks:read.
Webhook / trigger setup
Webhook must be registered on the target form ID via POST https://api.typeform.com/forms/{form_id}/webhooks/{tag}. The payload URL must be the orchestration layer's publicly accessible inbound endpoint. The webhook secret must be generated, stored in the credential store, and also set in the Typeform webhook configuration so that HMAC-SHA256 validation can be performed on every inbound request. Set enabled: true and verify_ssl: true.
Required configuration
The Typeform form ID must be stored in the credential store. Field IDs for each answer field (employee_id, cert_type, completion_date, new_expiry_date, file_upload) must be retrieved from the form schema and stored in a field-ID map in config, not hardcoded. File uploads are returned as temporary signed URLs valid for one hour; the orchestration layer must download and transfer the file to Google Drive within that window. The public Typeform form URL must be stored in config for injection into Gmail templates.
Rate limits
Typeform API allows 120 requests per minute per token. Webhook delivery is event-driven and not rate-limited on the receive side. At a volume of 30 to 80 submissions per renewal cycle, no throttling is needed.
Constraints
File upload size limit is 10 MB on the Pro plan (4 MB on Basic). PDF certificates must be tested against this limit before go-live. Typeform does not retain file uploads indefinitely; the signed download URL expires in one hour. The automation must treat the webhook receipt as the trigger to immediately download the file.
// Inbound webhook payload (simplified)
{
"event_id": "uuid",
"event_type": "form_response",
"form_response": {
"form_id": "{form_id}",
"token": "{response_token}",
"answers": [
{ "field": { "id": "{f_employee_id}" }, "text": "EMP-042" },
{ "field": { "id": "{f_cert_type}" }, "choice": { "label": "First Aid Level 2" } },
{ "field": { "id": "{f_completion_date}" }, "date": "2025-05-14" },
{ "field": { "id": "{f_new_expiry_date}" }, "date": "2027-05-14" },
{ "field": { "id": "{f_file_upload}" }, "file_url": "https://api.typeform.com/responses/files/..." }
]
}
}Google Drive
Used by Agent 2 only. Receives the downloaded certificate file and saves it to the correct named folder, applying a consistent file-naming convention derived from the employee ID, certification type, and completion date.
Auth method
OAuth 2.0 via the same Google Cloud service account used for Google Sheets. The service account must have Editor access to the root Certificates folder in Google Drive.
Required scopes
https://www.googleapis.com/auth/drive.file (create and manage files the app has created or opened; preferred over full drive scope for least-privilege access)
Webhook / trigger setup
Not applicable. Google Drive is write-only in this build.
Required configuration
The root Google Drive folder ID for certificate storage must be stored in the credential store, not hardcoded. Subfolder structure must be confirmed before go-live: recommended structure is /Certificates/{employee_id}/{cert_type}/. The automation creates subfolders if they do not already exist using files.create with mimeType application/vnd.google-apps.folder. File naming convention: {employee_id}_{cert_type_slug}_{completion_date}.pdf, e.g. EMP042_FirstAidL2_2025-05-14.pdf. Cert type slug mapping must be stored in config.
Rate limits
Google Drive API v3 allows 12,000 requests per 100 seconds per user. File uploads at current volume (up to 80 files per renewal cycle, non-simultaneous) will never approach this limit.
Constraints
Multipart upload must be used for files up to 5 MB; resumable upload for files between 5 MB and 10 MB. The automation must detect file size before choosing the upload method. After upload, the returned file ID and web view URL are written back to the Google Sheets log and optionally to BambooHR as a text field.
// Create subfolder if not exists
POST https://www.googleapis.com/drive/v3/files
Body: { name: "{cert_type_slug}", mimeType: "application/vnd.google-apps.folder",
parents: ["{employee_folder_id}"] }
// Upload certificate file (multipart)
POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart
Metadata part: { name: "{filename}.pdf", parents: ["{subfolder_id}"] }
Media part: {binary file content, mimeType: application/pdf}
// Response
{ id: "{file_id}", webViewLink: "https://drive.google.com/file/d/{file_id}/view" }03Field mappings between tools
The following tables define every field-level mapping at each agent handoff. Monospace field names reflect the exact identifiers used in API payloads and sheet column headers. Any discrepancy between these names and the live configuration must be resolved in the credential store or config object before go-live.
Agent 1 handoff: BambooHR and Google Sheets to Gmail and Slack (Certification Monitor Agent)
Source tool
Source field
Destination tool
Destination field
BambooHR
`id`
Google Sheets
`employee_id`
BambooHR
`displayName`
Google Sheets
`employee_name`
BambooHR
`workEmail`
Gmail
`to` (recipient address)
BambooHR
`supervisorEmail`
Slack
`users.lookupByEmail` input
BambooHR
`cert_type` (custom field)
Gmail
`{{cert_type}}` template placeholder
BambooHR
`cert_expiry_date` (custom field)
Gmail
`{{cert_expiry_date}}` template placeholder
BambooHR
`cert_expiry_date` (custom field)
Google Sheets
`cert_expiry_date`
Google Sheets
`last_reminder_tier`
Orchestration logic
Tier classification (90d / 60d / 30d / overdue)
Orchestration
Computed `reminder_tier`
Google Sheets ReminderLog
`reminder_tier`
Orchestration
Computed `run_timestamp`
Google Sheets ReminderLog
`last_reminder_date`
Config store
`typeform_submission_url`
Gmail
`{{typeform_submission_url}}` template placeholder
Agent 2 handoff: Typeform to Google Drive, BambooHR, and Google Sheets (Renewal Intake and Filing Agent)
Source tool
Source field
Destination tool
Destination field
Typeform
`answers[f_employee_id].text`
BambooHR
`id` (used to resolve employee record URL)
Typeform
`answers[f_employee_id].text`
Google Drive
Folder path segment `{employee_id}`
Typeform
`answers[f_employee_id].text`
Google Sheets
`employee_id` (lookup key for row match)
Typeform
`answers[f_cert_type].choice.label`
BambooHR
`cert_type` (custom field, validated against allowed values)
Typeform
`answers[f_cert_type].choice.label`
Google Drive
Folder path segment `{cert_type_slug}`
Typeform
`answers[f_cert_type].choice.label`
Google Sheets
`cert_type`
Typeform
`answers[f_completion_date].date`
BambooHR
`cert_completion_date` (custom field, ISO 8601)
Typeform
`answers[f_completion_date].date`
Google Sheets
`completion_date`
Typeform
`answers[f_completion_date].date`
Google Drive
File name segment `{completion_date}`
Typeform
`answers[f_new_expiry_date].date`
BambooHR
`cert_expiry_date` (custom field, ISO 8601)
Typeform
`answers[f_new_expiry_date].date`
Google Sheets
`cert_expiry_date` (updated in CertTracker row)
Typeform
`answers[f_file_upload].file_url`
Google Drive
File binary (downloaded and uploaded)
Google Drive
`webViewLink`
Google Sheets
`drive_file_url`
Google Drive
`webViewLink`
BambooHR
`cert_drive_url` (optional text custom field)
Orchestration
Hardcoded string `Complete`
Google Sheets
`status`
Integration and API SpecPage 2 of 3
FS-DOC-05Technical
04Build stack and orchestration
Orchestration layout
Two discrete workflows are maintained in the automation platform: one per agent. Workflow 1 is the Certification Monitor Agent (daily scheduled trigger). Workflow 2 is the Renewal Intake and Filing Agent (webhook trigger). Both workflows draw credentials exclusively from the shared credential store; no secrets appear in workflow logic or node configuration fields.
Shared credential store
A single credential store is shared across both workflows. Credentials are referenced by key name only inside workflow nodes. Rotation of any credential requires updating the store entry only; workflow logic does not change.
Agent 1 trigger mechanism
Poll-based scheduled trigger. The orchestration platform's built-in scheduler fires Workflow 1 once per day at a configured UTC time (recommended: 06:00 UTC). No inbound webhook is required. The trigger reads from BambooHR and Google Sheets on each run.
Agent 2 trigger mechanism
Webhook trigger. Workflow 2 listens on a static inbound URL provided by the orchestration platform. Typeform posts to this URL on each new form response. The first node in Workflow 2 must validate the HMAC-SHA256 signature from the Typeform-Signature header using the shared webhook secret before any processing begins. Requests that fail signature validation must return HTTP 401 and halt the workflow.
Signature validation (Agent 2)
Compute HMAC-SHA256 of the raw request body using the webhook_secret from the credential store. Compare against the value in the Typeform-Signature header (format: sha256={hex_digest}). Reject if they do not match. This must execute before any field parsing.
Retry behaviour
Both workflows use the platform's built-in retry with exponential backoff. Default: 3 attempts, initial delay 30 seconds, backoff multiplier 2 (30s, 60s, 120s). Permanent failures after exhausting retries must route to an error-notification step (Slack alert to the escalation channel) and log the failure to the ReminderLog sheet with status ERROR.
Idempotency (Agent 2)
Agent 2 must check the Typeform response token against a processed-tokens log in Google Sheets before acting on any webhook. If the token is already present, the workflow exits immediately with a no-op log entry. This prevents duplicate filing on webhook replay.
Environment separation
A separate set of credentials, a separate test spreadsheet, a separate Typeform form, and a separate BambooHR API key must be used for QA. The production credential store must never be used during testing.
Credential store contents (all entries below must be present before either workflow is activated in production):
Credential store — all keys required before production activation
// Credential store — key : description
// BambooHR
BAMBOOHR_SUBDOMAIN : Company subdomain (e.g. yourcompany)
BAMBOOHR_API_KEY : API key for service account user
BAMBOOHR_FIELD_ID_CERT_TYPE : Numeric ID of cert_type custom field
BAMBOOHR_FIELD_ID_COMPLETION_DATE : Numeric ID of cert_completion_date custom field
BAMBOOHR_FIELD_ID_EXPIRY_DATE : Numeric ID of cert_expiry_date custom field
BAMBOOHR_FIELD_ID_DRIVE_URL : Numeric ID of cert_drive_url custom field (optional)
// Google (Sheets, Drive, Gmail — shared service account)
GOOGLE_SERVICE_ACCOUNT_JSON : Full JSON key file content for service account
GOOGLE_SHEETS_SPREADSHEET_ID : ID of the master certification tracking spreadsheet
GOOGLE_SHEETS_TAB_CERTTRACKER : Sheet tab name (default: CertTracker)
GOOGLE_SHEETS_TAB_REMINDERLOG : Log tab name (default: ReminderLog)
GOOGLE_SHEETS_TAB_PROCESSEDTOKENS : Idempotency tab name (default: ProcessedTokens)
GOOGLE_DRIVE_ROOT_FOLDER_ID : ID of the root /Certificates folder in Drive
GMAIL_SENDER_ADDRESS : Sending email address (e.g. hr@[YourCompany.com])
GMAIL_SENDER_DISPLAY_NAME : Display name (e.g. HR Compliance — [YourCompany.com])
// Email templates (stored as multiline strings or template IDs)
EMAIL_TEMPLATE_90D : Full HTML+plaintext template for 90-day reminder
EMAIL_TEMPLATE_60D : Full HTML+plaintext template for 60-day reminder
EMAIL_TEMPLATE_30D : Full HTML+plaintext template for 30-day reminder
EMAIL_TEMPLATE_OVERDUE : Full HTML+plaintext template for overdue notice
// Typeform
TYPEFORM_PAT : Personal Access Token
TYPEFORM_FORM_ID : ID of the certificate submission form
TYPEFORM_FORM_URL : Public URL injected into reminder emails
TYPEFORM_WEBHOOK_SECRET : Shared secret for HMAC-SHA256 signature validation
TYPEFORM_FIELD_ID_EMPLOYEE_ID : Field ID for employee ID answer
TYPEFORM_FIELD_ID_CERT_TYPE : Field ID for certification type answer
TYPEFORM_FIELD_ID_COMPLETION_DATE : Field ID for completion date answer
TYPEFORM_FIELD_ID_NEW_EXPIRY_DATE : Field ID for new expiry date answer
TYPEFORM_FIELD_ID_FILE_UPLOAD : Field ID for file upload answer
// Slack
SLACK_BOT_TOKEN : OAuth Bot token (xoxb-...)
SLACK_ESCALATION_CHANNEL_ID : Channel ID for overdue and error alerts
// Drive file naming
DRIVE_CERT_TYPE_SLUG_MAP : JSON map of cert type labels to filename slugs
e.g. { "First Aid Level 2": "FirstAidL2" }05Error handling and retry logic
Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors that exhaust retries must produce a Slack alert to the escalation channel and a log entry in the ReminderLog sheet with status ERROR and a descriptive message field.
Integration
Scenario
Required behaviour
BambooHR (Agent 1 read)
API returns 401 Unauthorized
Halt workflow immediately. Send Slack alert to escalation channel: 'BambooHR API key invalid or expired. Daily scan aborted.' Log ERROR to ReminderLog. Do not retry — credential rotation is required.
BambooHR (Agent 1 read)
API returns 429 Too Many Requests
Pause and retry with exponential backoff: 30s, 60s, 120s. After 3 failed attempts, halt workflow and send Slack alert. Log ERROR. Resume on next scheduled daily run.
BambooHR (Agent 2 write)
PATCH returns 404 (employee not found)
Log ERROR row to ReminderLog with employee_id and response code. Send Slack alert: 'BambooHR write failed: employee {employee_id} not found.' File to Drive and update Sheets still proceed; BambooHR update is retried once after 5 minutes, then flagged for manual resolution.
Google Sheets (Agent 1 or 2)
API returns 403 Forbidden (service account not shared on sheet)
Halt workflow. Send Slack alert: 'Google Sheets access denied. Verify service account sharing on spreadsheet {SPREADSHEET_ID}.' Log ERROR if possible. Do not retry — configuration fix required.
Google Sheets (Agent 2 write)
Row lookup for employee_id returns no match
Log a new row in CertTracker with the submitted data and status 'Unmatched — review required'. Send Slack alert to escalation channel. Continue with Drive filing and BambooHR write using the submitted employee_id.
Gmail (Agent 1 send)
API returns 400 Bad Request (malformed recipient address)
Skip the send for that employee. Log ERROR to ReminderLog with employee_id and the invalid address. Send Slack alert to escalation channel listing affected employees. Continue processing remaining employees.
Gmail (Agent 1 send)
API returns 500 or network timeout
Retry with exponential backoff: 30s, 60s, 120s. After 3 failures, skip send for affected employee, log ERROR, and send Slack alert. The employee is retried on the next scheduled daily run (idempotency check prevents duplicate sends within the same tier).
Slack (Agent 1 notify)
Manager Slack ID cannot be resolved (no Slack account for supervisor email)
Log a warning (not an error) to ReminderLog: 'Slack DM skipped — no Slack user found for {supervisor_email}.' Continue workflow. Do not halt or retry. Escalation channel receives a digest of unresolved managers once per daily run.
Typeform webhook (Agent 2 trigger)
Inbound request fails HMAC-SHA256 signature validation
Return HTTP 401. Halt workflow. Log the rejection with timestamp and partial payload hash to ProcessedTokens tab. Send Slack alert: 'Typeform webhook received with invalid signature — possible replay attack or misconfiguration.' Do not process the submission.
Typeform file download (Agent 2)
Signed file URL has expired (download attempted more than 1 hour after webhook receipt)
Log ERROR to ReminderLog. Send Slack alert: 'Certificate file URL expired for response token {token}. Manual retrieval required — retrieve file from Typeform dashboard and file manually.' Do not proceed with Drive upload or BambooHR update. Mark status as 'File retrieval failed'.
Google Drive upload (Agent 2)
Upload fails due to insufficient storage or permissions error
Retry twice with 60-second delay. After 2 failures, log ERROR to ReminderLog, send Slack alert with file name and employee_id, and halt Drive and Sheets write steps. BambooHR write is also skipped to preserve data consistency. Mark for manual resolution.
Agent 2 idempotency check
Typeform response token already present in ProcessedTokens tab (webhook replay or duplicate delivery)
Exit workflow immediately with a no-op. Append a deduplicated log entry: 'Duplicate webhook received and suppressed for token {token}.' Do not send any alerts. Do not reprocess.
Any error scenario not covered by the table above must be treated as an unhandled exception. The orchestration platform's global error handler must catch all unhandled exceptions and route them to the Slack escalation channel with the workflow name, node name, and a truncated error message. Errors must never fail silently. Contact FullSpec at support@gofullspec.com if a recurring error scenario requires a new handling rule to be added to the workflow.
Integration and API SpecPage 3 of 3