Back to Staff Scheduling & Rostering

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

Staff Scheduling and Rostering

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

This document is the authoritative integration reference for the Staff Scheduling and Rostering automation. It covers every tool in the stack, the exact authentication configuration and API scopes required, field-level mappings between agents, orchestration layout, credential store structure, and failure handling for every integration point. The FullSpec team uses this document during build and configuration; your team uses it for ongoing administration and incident response. All credential values referenced below are placeholders and must be replaced with live secrets before production deployment.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agents
Orchestration layer
Workflow engine coordinating all agents and triggers
Internal service account / platform credential
N/A (platform choice)
All agents
Gmail
Sends availability request emails and personalised shift notification emails to staff
OAuth 2.0 (Google Identity)
Google Workspace (any tier) or free Gmail
Agent 1, Agent 3
Google Sheets
Central availability data store and draft roster surface
OAuth 2.0 (Google Identity)
Google Workspace (any tier) or free Google account
Agent 1, Agent 2
Google Calendar
Recurring weekly timer that fires the scheduling trigger
OAuth 2.0 (Google Identity)
Google Workspace (any tier) or free Google account
Agent 1 (trigger source)
Deputy
Receives published roster via API; source of confirmed shift hours at pay-period close
OAuth 2.0 (Deputy platform)
Deputy Starter or higher (API access required)
Agent 2, Agent 3
Slack
Posts conflict and gap alerts to manager channel; sends personalised shift notifications to staff
OAuth 2.0 (Slack app install)
Slack Free or higher
Agent 2, Agent 3
Xero
Receives timesheet entries for payroll processing at pay-period close
OAuth 2.0 (Xero Identity Server, PKCE)
Xero Starter or higher
Agent 3
Before you connect anything: create sandbox or test instances for Deputy and Xero, and use a dedicated test Google Workspace account for Gmail and Sheets connections. Validate every OAuth flow and confirm token refresh works end to end before any production credential is stored. Production credentials must never be used during development or QA phases.

02Per-tool integration detail

Gmail

Used by Agent 1 (Availability Collection) to dispatch the weekly availability request to all active staff, and by Agent 3 (Roster Publication and Payroll) to send personalised shift confirmation emails after roster publication.

Auth method
OAuth 2.0 via Google Identity Platform. Authorise a dedicated service account or OAuth client ID registered in Google Cloud Console. Use offline access_type to obtain a refresh token; store the refresh token in the credential store, not the access token.
Required scopes
https://www.googleapis.com/auth/gmail.send | https://www.googleapis.com/auth/gmail.readonly (readonly needed only if delivery receipt parsing is implemented; omit if not required)
Webhook / trigger setup
Gmail is not used as a trigger in this automation. Outbound sends only. No inbound webhook is configured. Staff reply-to address should be a monitored alias if reply parsing is required in future.
Required configuration
GMAIL_SENDER_ADDRESS stored in credential store. Email template IDs for availability request and shift confirmation stored in the credential store (not hardcoded). Templates must contain placeholders: {{staff_name}}, {{week_start_date}}, {{availability_form_url}} for Agent 1; {{staff_name}}, {{shift_day}}, {{shift_start}}, {{shift_end}}, {{location}} for Agent 3.
Rate limits
Gmail API: 250 quota units per second per user; sending limit 2,000 messages per day for Google Workspace. At current volume of up to 25 staff per cycle with 4 cycles per month plus one follow-up reminder pass, maximum send volume is approximately 225 emails per month. No throttling required at this volume; however, the orchestration layer should batch sends with a 500 ms delay between requests to stay well within quota.
Constraints
OAuth tokens expire after 1 hour; refresh token rotation must be handled automatically by the orchestration layer. Google Cloud project must have the Gmail API enabled. Sending from a shared alias requires domain-wide delegation or send-as configuration in Workspace admin.
// Input (Agent 1 send)
recipient_email: string          // from STAFF_ROSTER sheet column staff_email
staff_name: string               // from STAFF_ROSTER sheet column full_name
week_start_date: ISO8601 date    // computed by trigger
availability_form_url: string    // from credential store key AVAIL_FORM_URL
// Output
gmail_message_id: string         // stored to AVAIL_LOG sheet for delivery tracking
send_status: 'sent' | 'failed'
Google Sheets

Acts as the central data layer for the entire automation. Agent 1 writes availability responses row by row. Agent 2 reads availability and shift demand data to build the draft roster, then writes the draft back to a designated roster tab. The manager's approval signal is also read from a named cell in this sheet.

Auth method
OAuth 2.0 via Google Identity Platform. Same OAuth client as Gmail if using a combined Google service account. Scopes are separate.
Required scopes
https://www.googleapis.com/auth/spreadsheets | https://www.googleapis.com/auth/drive.file (drive.file limits access to files created by or explicitly shared with the app, reducing blast radius)
Webhook / trigger setup
Google Sheets does not natively emit webhooks to external services. Agent 1 marks the availability sheet complete by writing 'COMPLETE' to a named cell (AVAIL_STATUS, cell A1 of the STATUS tab). Agent 2 polls this cell on a 5-minute interval after the availability window closes. Alternatively, an Apps Script trigger inside the sheet can call the orchestration layer's inbound webhook URL when AVAIL_STATUS changes.
Required configuration
SHEETS_SPREADSHEET_ID stored in credential store. Tab names: STAFF_ROSTER (master staff list), AVAILABILITY_RESPONSES (one row per staff member per week), SHIFT_DEMAND (week-ahead demand table maintained by the manager), DRAFT_ROSTER (output of Agent 2), STATUS (single-cell flags). Column headers must match the field mapping table in section 03 exactly. Do not rename tabs or columns after build without updating the field map.
Rate limits
Sheets API v4: 300 requests per minute per project, 60 requests per minute per user. At current volume (up to 25 staff rows written per cycle, plus read passes by Agent 2) peak usage is well under 60 requests per minute. No throttling required; exponential backoff on 429 responses is sufficient.
Constraints
Spreadsheet must be shared with the OAuth service account email at Editor level. Avoid merged cells in any data range; they break range reads. Availability form (Google Forms) must be configured to submit responses directly to the AVAILABILITY_RESPONSES tab via Forms linked-sheet feature.
// Input (Agent 2 read)
spreadsheet_id: string           // from credential store SHEETS_SPREADSHEET_ID
range: 'AVAILABILITY_RESPONSES!A2:H'  // all staff rows for current week
range: 'SHIFT_DEMAND!A2:E'       // demand requirements for the week
// Output (Agent 2 write)
range: 'DRAFT_ROSTER!A2:K'       // one row per shift slot
range: 'STATUS!A1'               // write 'ROSTER_DRAFT_READY' on completion
// Output (Agent 1 write)
range: 'AVAILABILITY_RESPONSES!A{n}:H{n}'  // append one row per staff response
range: 'AVAIL_LOG!A{n}:D{n}'     // append delivery and response log entry
Google Calendar

Provides the recurring weekly timer that fires the start of each scheduling cycle. The orchestration layer listens to a specific calendar event pattern to determine when to initiate Agent 1.

Auth method
OAuth 2.0 via Google Identity Platform. Same service account as other Google services.
Required scopes
https://www.googleapis.com/auth/calendar.readonly (read-only is sufficient; the automation reads event start times and does not create or modify calendar events)
Webhook / trigger setup
Create a recurring weekly calendar event titled 'ROSTER_CYCLE_START' in the dedicated automation calendar (AUTOMATION_CALENDAR_ID stored in credential store). The orchestration layer polls the Calendar API every hour using the events.list endpoint filtered by the event summary string and timeMin set to the current timestamp. When a matching event is found in the next 15-minute window, the trigger fires. Alternatively, configure a push notification channel via the Calendar API watch endpoint with the orchestration layer's webhook receiver URL.
Required configuration
AUTOMATION_CALENDAR_ID stored in credential store. ROSTER_CYCLE_DAY (e.g. 'Monday') and ROSTER_CYCLE_TIME (e.g. '07:00') stored as environment variables so the schedule can be adjusted without a code change.
Rate limits
Calendar API: 1,000,000 queries per day. Hourly polling generates 24 requests per day, negligible against quota. No throttling required.
Constraints
The automation calendar must be shared with the service account at Reader level minimum. If using push notifications, the watch channel must be renewed before its expiration (maximum 7 days); implement automatic channel renewal 24 hours before expiry.
// Trigger output passed to Agent 1
event_id: string                 // Google Calendar event ID
event_start: ISO8601 datetime    // exact trigger timestamp
week_start_date: ISO8601 date    // derived: Monday of the roster week
week_end_date: ISO8601 date      // derived: Sunday of the roster week
Integration and API SpecPage 1 of 4
FS-DOC-05Technical
Deputy

Receives the finalised roster from Agent 3 via the Deputy REST API, creating or updating shift records for each staff member. At pay-period close, Agent 3 also reads confirmed timesheet data from Deputy to export to Xero.

Auth method
OAuth 2.0 via Deputy's OAuth server. Register a Deputy OAuth application in the Deputy Marketplace or developer portal. Redirect URI must point to the orchestration layer's OAuth callback endpoint. Store the access token and refresh token in the credential store. Token endpoint: https://{subdomain}.deputy.com/oauth/access_token
Required scopes
me | longlife | roster | employee | timesheet | report (Deputy uses named scope strings; 'roster' covers shift read and write; 'timesheet' covers timesheet read for payroll export; 'longlife' enables refresh token persistence beyond session)
Webhook / trigger setup
Agent 3 calls Deputy's shift creation endpoint after receiving the approval signal from Google Sheets. No inbound webhook from Deputy is required for this flow. If future shift-swap handling is added, the Deputy webhook for ShiftPublish events should be configured to post to the orchestration layer's receiver.
Required configuration
DEPUTY_SUBDOMAIN stored in credential store (e.g. 'yourcompany.deputy.com'). DEPUTY_LOCATION_ID stored in credential store (the business location shifts are created under). Staff Deputy employee IDs mapped to internal staff IDs in the STAFF_ROSTER sheet column deputy_employee_id. Do not hardcode any location or employee IDs.
Rate limits
Deputy API: 200 requests per minute per access token. Publishing a 25-staff roster requires approximately 25 POST /api/v1/resource/Roster/BULK calls (one per shift or one bulk call with up to 50 shifts). Well within rate limits. No throttling required at current volume; implement exponential backoff on 429 responses.
Constraints
Deputy Starter plan or higher is required for API access. Shifts cannot be created for employees not yet in Deputy; staff onboarding to Deputy must precede automation go-live. Published shifts are visible to staff in the Deputy app immediately after the API write; ensure the approval gate is enforced before any Deputy call is made.
// Input (Agent 3 shift creation)
POST /api/v1/resource/Roster/BULK
body: [{ EmployeeId, StartTime, EndTime, OperationalUnitId, Comment, Published }]
// Input (Agent 3 timesheet read at pay-period close)
GET /api/v1/resource/Timesheet?search={EmployeeId,StartDate,EndDate,Status:'Approved'}
// Output (shift creation response)
roster_id[]: integer[]           // Deputy-assigned shift IDs, stored to DRAFT_ROSTER sheet
// Output (timesheet read response)
timesheet[]: { EmployeeId, StartTime, EndTime, TotalTime, Status }
Slack

Used by Agent 2 to post conflict and rule-breach alerts to the manager's designated channel, and by Agent 3 to send personalised shift notifications to each staff member's direct message or a shared shifts channel.

Auth method
OAuth 2.0 via Slack app installation. Create a Slack app in the Slack API console (api.slack.com/apps). Install to workspace using the OAuth flow. Store the bot_access_token in the credential store under key SLACK_BOT_TOKEN. Use a dedicated bot user, not a personal user token.
Required scopes
chat:write | chat:write.public | users:read | users:read.email (users:read.email is required to resolve staff email addresses to Slack user IDs for DM targeting)
Webhook / trigger setup
For manager alerts (Agent 2): configure an incoming webhook URL scoped to the manager's alert channel (SLACK_MANAGER_CHANNEL_ID in credential store). For staff DMs (Agent 3): use the chat.postMessage API method with channel set to the resolved Slack user ID. Resolve Slack user ID from staff email using users.lookupByEmail before the first message send; cache the result in the STAFF_ROSTER sheet column slack_user_id.
Required configuration
SLACK_BOT_TOKEN stored in credential store. SLACK_MANAGER_CHANNEL_ID stored in credential store. SLACK_STAFF_NOTIFY_CHANNEL_ID stored in credential store (fallback channel if DM resolution fails). Slack message templates (Block Kit JSON) stored as versioned strings in the credential store or config file, not hardcoded inline.
Rate limits
Slack Web API: Tier 3 methods (chat.postMessage) allow 50 requests per minute. With 25 staff notified per cycle, all notifications can be sent within 30 seconds with no throttling needed. Implement a 300 ms delay between each postMessage call as a precaution.
Constraints
The Slack app must be installed and approved by a Slack workspace admin before build. Staff must be members of the workspace for DM delivery; any staff member not in Slack falls back to Gmail notification. Bot must be invited to the manager alert channel (SLACK_MANAGER_CHANNEL_ID) before it can post there.
// Input (Agent 2 conflict alert)
channel: SLACK_MANAGER_CHANNEL_ID
blocks: ConflictSummaryBlockKit    // list of unresolved shifts with rule breach type
// Input (Agent 3 staff DM)
channel: slack_user_id             // resolved from staff email via users.lookupByEmail
blocks: ShiftConfirmationBlockKit  // staff_name, shift_day, shift_start, shift_end
// Output
ts: string                         // Slack message timestamp, stored for audit log
ok: boolean                        // success flag; false triggers Gmail fallback
Xero

Receives timesheet entries from Agent 3 at pay-period close. Confirmed shift hours are read from Deputy and posted to Xero as manual journal or timesheet records ready for payroll processing.

Auth method
OAuth 2.0 with PKCE via Xero Identity Server. Register the automation as a Xero app at developer.xero.com. Use the authorisation code flow with PKCE (no client_secret required). Redirect URI must point to the orchestration layer's OAuth callback. Store access_token and refresh_token in the credential store under keys XERO_ACCESS_TOKEN and XERO_REFRESH_TOKEN. Xero access tokens expire after 30 minutes; refresh_token lifetime is 60 days (rolling). Implement automatic refresh before every API call.
Required scopes
openid | profile | email | accounting.transactions | accounting.contacts.read | payroll.timesheets (payroll.timesheets is required for direct timesheet creation; accounting.transactions is a fallback if the payroll API is not available on the connected Xero plan)
Webhook / trigger setup
Xero is called by Agent 3 on a scheduled trigger at pay-period close, not via an inbound webhook. The pay-period close date is stored as XERO_PAY_PERIOD_CLOSE_DAY (e.g. 'Friday') in the credential store. The orchestration layer fires the Xero export step when the current date matches this value and approved Deputy timesheets are available.
Required configuration
XERO_TENANT_ID stored in credential store (obtained from the /connections endpoint after OAuth). XERO_PAYROLL_CALENDAR_ID stored in credential store. Staff Xero employee IDs mapped in the STAFF_ROSTER sheet column xero_employee_id. XERO_EARNINGS_RATE_ID stored in credential store for the standard hourly rate. Do not hardcode any Xero IDs.
Rate limits
Xero API: 60 calls per minute, 5,000 calls per day. A pay-period export for 25 staff is approximately 25 to 50 API calls. Well within limits. No throttling required; implement exponential backoff on 429 and 503 responses.
Constraints
Xero payroll API is only available in Xero Payroll-enabled regions (AU, NZ, UK). If the Xero plan does not include payroll, use the accounting.transactions endpoint to create a manual journal entry summarising total hours per employee instead. Xero employee records must be active and mapped to Deputy employee IDs before the first payroll export.
// Input (Agent 3 timesheet post)
POST /api.xro/2.0/Timesheets
body: { EmployeeID, StartDate, EndDate, Status:'Draft',
        TimesheetLines: [{ EarningsRateID, NumberOfUnits[] }] }
// Output
TimesheetID: GUID                // Xero-assigned ID, stored to PAYROLL_LOG sheet
Status: 'Draft' | 'Approved'     // Xero status after creation
ValidationErrors[]: string[]     // surface to orchestration error handler if non-empty
Integration and API SpecPage 2 of 4
FS-DOC-05Technical

03Field mappings between tools

The tables below define the exact field-level mappings for each agent handoff in the automation chain. Source and destination field names are given in monospace format as they appear in the respective API payloads or sheet column headers. All sheet column names are case-sensitive and must not be changed after build.

Agent 1 handoff: Gmail trigger to Google Sheets availability log

Source tool
Source field
Destination tool
Destination field
Google Calendar
`event_start` (ISO8601)
Google Sheets: AVAILABILITY_RESPONSES
`week_start_date` (col A)
Gmail send response
`message_id`
Google Sheets: AVAIL_LOG
`gmail_message_id` (col B)
Staff master list (STAFF_ROSTER)
`staff_email`
Gmail API
`to` (recipient address)
Staff master list (STAFF_ROSTER)
`full_name`
Gmail template
`{{staff_name}}` placeholder
Credential store
`AVAIL_FORM_URL`
Gmail template
`{{availability_form_url}}` placeholder
Google Forms response
`responder_email`
Google Sheets: AVAILABILITY_RESPONSES
`staff_email` (col B)
Google Forms response
`monday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_mon` (col C)
Google Forms response
`tuesday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_tue` (col D)
Google Forms response
`wednesday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_wed` (col E)
Google Forms response
`thursday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_thu` (col F)
Google Forms response
`friday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_fri` (col G)
Google Forms response
`saturday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_sat` (col H)
Google Forms response
`sunday_available` (boolean)
Google Sheets: AVAILABILITY_RESPONSES
`avail_sun` (col I)
Google Forms response
`preferred_hours` (integer)
Google Sheets: AVAILABILITY_RESPONSES
`preferred_hours` (col J)
Orchestration layer
`response_received_at` (ISO8601)
Google Sheets: AVAILABILITY_RESPONSES
`responded_at` (col K)

Agent 2 handoff: Google Sheets availability and demand data to Deputy draft roster

Source tool
Source field
Destination tool
Destination field
Google Sheets: AVAILABILITY_RESPONSES
`staff_email` (col B)
Google Sheets: DRAFT_ROSTER
`staff_email` (col A)
Google Sheets: STAFF_ROSTER
`deputy_employee_id`
Google Sheets: DRAFT_ROSTER
`deputy_employee_id` (col B)
Google Sheets: SHIFT_DEMAND
`shift_date` (ISO8601)
Google Sheets: DRAFT_ROSTER
`shift_date` (col C)
Google Sheets: SHIFT_DEMAND
`shift_start_time`
Google Sheets: DRAFT_ROSTER
`shift_start` (col D)
Google Sheets: SHIFT_DEMAND
`shift_end_time`
Google Sheets: DRAFT_ROSTER
`shift_end` (col E)
Agent 2 logic output
`conflict_flag` (boolean)
Google Sheets: DRAFT_ROSTER
`conflict_flag` (col F)
Agent 2 logic output
`conflict_reason` (string)
Google Sheets: DRAFT_ROSTER
`conflict_reason` (col G)
Agent 2 logic output
`award_breach` (boolean)
Google Sheets: DRAFT_ROSTER
`award_breach` (col H)
Orchestration layer
`draft_created_at` (ISO8601)
Google Sheets: STATUS
`ROSTER_DRAFT_READY` (cell A1)
Google Sheets: DRAFT_ROSTER filtered conflicts
`conflict_reason`
Slack Block Kit
`conflict_description` field in ConflictSummaryBlockKit

Agent 3 handoff: Google Sheets draft roster to Deputy shift creation, and Deputy timesheet to Xero

Source tool
Source field
Destination tool
Destination field
Google Sheets: DRAFT_ROSTER
`deputy_employee_id` (col B)
Deputy API: Roster
`EmployeeId`
Google Sheets: DRAFT_ROSTER
`shift_date` (col C)
Deputy API: Roster
`StartTime` (date part)
Google Sheets: DRAFT_ROSTER
`shift_start` (col D)
Deputy API: Roster
`StartTime` (time part)
Google Sheets: DRAFT_ROSTER
`shift_end` (col E)
Deputy API: Roster
`EndTime`
Credential store
`DEPUTY_LOCATION_ID`
Deputy API: Roster
`OperationalUnitId`
Deputy API: Roster response
`Id` (roster_id)
Google Sheets: DRAFT_ROSTER
`deputy_roster_id` (col I)
Deputy API: Timesheet
`EmployeeId`
Google Sheets: STAFF_ROSTER
`deputy_employee_id` (lookup key)
Google Sheets: STAFF_ROSTER
`xero_employee_id`
Xero API: Timesheets
`EmployeeID`
Deputy API: Timesheet
`TotalTime` (decimal hours)
Xero API: Timesheets
`NumberOfUnits[]` (per day array)
Deputy API: Timesheet
`StartTime` (date)
Xero API: Timesheets
`StartDate`
Credential store
`XERO_EARNINGS_RATE_ID`
Xero API: Timesheets
`EarningsRateID`
Xero API response
`TimesheetID`
Google Sheets: PAYROLL_LOG
`xero_timesheet_id` (col C)

04Build stack and orchestration

Orchestration layout
Three discrete workflows, one per agent (Availability Collection, Roster Drafting, Roster Publication and Payroll). Each workflow is independently deployable and restartable. A shared credential store (environment variable vault within the automation platform) is referenced by all three workflows. No credentials are stored in workflow logic or version-controlled code.
Agent 1 trigger
Webhook (push) or scheduled poll against Google Calendar events.list endpoint. Preferred: Calendar API push notification (watch channel) posting to the orchestration layer's /trigger/availability-collection inbound webhook. Fallback: hourly poll checking for a ROSTER_CYCLE_START event within a 15-minute window. On trigger, Agent 1 initialises the week_start_date variable and begins the Gmail send loop.
Agent 2 trigger
Poll on Google Sheets STATUS tab cell A1 for the value 'COMPLETE'. Polling interval: every 5 minutes, beginning 23 hours after the Agent 1 trigger fires. Polling window: 48 hours. If 'COMPLETE' is not written within 48 hours, Agent 2 raises an alert to SLACK_MANAGER_CHANNEL_ID and halts. No signature validation required for this internal poll.
Agent 3 trigger
Poll on Google Sheets STATUS tab cell A1 for the value 'ROSTER_APPROVED'. The manager sets this value by editing the STATUS tab or by clicking an approval button in the Slack conflict alert (Slack interactive component posting to the orchestration layer's /trigger/roster-approved webhook endpoint with a signed payload). Slack payload signature must be validated using the SLACK_SIGNING_SECRET before processing. Xero export sub-step is triggered by a secondary scheduler matching the XERO_PAY_PERIOD_CLOSE_DAY value.
Credential store structure
All secrets are stored in the automation platform's encrypted environment variable vault. See code block below for the full list of required keys.
Inter-workflow communication
Workflows communicate exclusively via Google Sheets STATUS tab cell writes. No direct inter-workflow API calls. This ensures each workflow is independently observable and retryable without cascading side effects.
Logging
Every workflow writes a structured log entry (timestamp, workflow_name, step_name, status, error_message) to Google Sheets: AUTOMATION_LOG tab after each major action. Log entries must never be deleted; the tab is append-only.
Credential store: full key list. Rotate access tokens automatically; rotate client secrets and refresh tokens on a 90-day schedule.
// Credential store: required keys (all values injected at runtime, never hardcoded)

// Google (shared OAuth client)
GOOGLE_CLIENT_ID=<oauth_client_id>
GOOGLE_CLIENT_SECRET=<oauth_client_secret>
GOOGLE_REFRESH_TOKEN=<refresh_token>          // single token with all Google scopes

// Google Sheets
SHEETS_SPREADSHEET_ID=<google_sheets_file_id>

// Google Calendar
AUTOMATION_CALENDAR_ID=<google_calendar_id>
ROSTER_CYCLE_DAY=Monday                       // day of week trigger fires
ROSTER_CYCLE_TIME=07:00                       // local time trigger fires

// Gmail
GMAIL_SENDER_ADDRESS=roster@yourcompany.com
AVAIL_FORM_URL=https://forms.gle/<form_id>
GMAIL_TEMPLATE_AVAIL_REQUEST=<template_id_or_body_key>
GMAIL_TEMPLATE_SHIFT_CONFIRM=<template_id_or_body_key>

// Deputy
DEPUTY_SUBDOMAIN=yourcompany                  // subdomain only, not full URL
DEPUTY_CLIENT_ID=<deputy_oauth_client_id>
DEPUTY_CLIENT_SECRET=<deputy_oauth_client_secret>
DEPUTY_ACCESS_TOKEN=<access_token>            // auto-refreshed by orchestration layer
DEPUTY_REFRESH_TOKEN=<refresh_token>
DEPUTY_LOCATION_ID=<operational_unit_id>

// Slack
SLACK_BOT_TOKEN=xoxb-<token>
SLACK_SIGNING_SECRET=<signing_secret>         // for interactive component validation
SLACK_MANAGER_CHANNEL_ID=C<channel_id>
SLACK_STAFF_NOTIFY_CHANNEL_ID=C<channel_id>  // fallback if DM resolution fails

// Xero
XERO_CLIENT_ID=<xero_app_client_id>
XERO_TENANT_ID=<xero_organisation_tenant_id>
XERO_ACCESS_TOKEN=<access_token>              // auto-refreshed before every call
XERO_REFRESH_TOKEN=<refresh_token>
XERO_PAYROLL_CALENDAR_ID=<payroll_calendar_guid>
XERO_EARNINGS_RATE_ID=<earnings_rate_guid>
XERO_PAY_PERIOD_CLOSE_DAY=Friday             // day of week payroll export fires
Integration and API SpecPage 3 of 4
FS-DOC-05Technical

05Error handling and retry logic

Unhandled exceptions must never fail silently. Every integration point has a defined failure behaviour. If none of the rows below match a failure scenario encountered during operation, the orchestration layer must log the exception with full context and post an alert to SLACK_MANAGER_CHANNEL_ID before halting the affected workflow step. Do not swallow errors.
Integration
Scenario
Required behaviour
Google Calendar (trigger poll)
Calendar API returns 401 Unauthorized
Attempt one token refresh using GOOGLE_REFRESH_TOKEN. If refresh succeeds, retry the request immediately. If refresh fails, post alert to SLACK_MANAGER_CHANNEL_ID with error detail, write ERROR entry to AUTOMATION_LOG, and halt Agent 1 for the current cycle. Do not retry the trigger until the next scheduled window.
Gmail (availability send)
send() returns 4xx for one or more staff recipients
Log failed recipient and error code to AVAIL_LOG. Retry after 60 seconds with exponential backoff (max 3 attempts). If all retries fail, mark the staff member's AVAIL_LOG row as SEND_FAILED and continue sending to remaining recipients. After the send loop completes, post a summary of failed sends to SLACK_MANAGER_CHANNEL_ID so the manager can follow up manually.
Gmail (availability send)
Daily send quota exceeded (250 quota units/second or 2,000 messages/day)
Halt send loop. Post quota-exceeded alert to SLACK_MANAGER_CHANNEL_ID including number of unsent staff. Write partial send state to AVAIL_LOG. Resume send loop at 00:01 the following day. If the roster cycle timing cannot tolerate a 24-hour delay, the manager must manually contact remaining staff.
Google Sheets (Agent 1 write)
Spreadsheet API returns 429 Too Many Requests
Apply exponential backoff: wait 2 seconds, then 4, then 8, then 16, up to 5 retries. If all retries fail, write the failed payload to the AUTOMATION_LOG with status WRITE_FAILED and post an alert to SLACK_MANAGER_CHANNEL_ID. Do not continue to the next step until the write succeeds or the alert is acknowledged.
Google Sheets (Agent 2 poll for COMPLETE status)
COMPLETE flag not written within 48-hour polling window
Post alert to SLACK_MANAGER_CHANNEL_ID: 'Availability collection did not complete within 48 hours. Manual review required.' Write TIMEOUT entry to AUTOMATION_LOG. Halt Agent 2 for the current cycle. The manager must review the AVAILABILITY_RESPONSES tab, manually set STATUS!A1 to COMPLETE, and trigger Agent 2 manually via the orchestration layer's manual trigger endpoint.
Deputy (shift creation)
API returns 400 Bad Request for one or more shift payloads
Log the failing shift payload and error response to AUTOMATION_LOG. Skip the failed shift and continue creating remaining shifts. After the loop completes, post a summary of failed shifts (staff name, date, error reason) to SLACK_MANAGER_CHANNEL_ID. Do not partially publish a roster without alerting the manager to gaps.
Deputy (shift creation)
API returns 401 Unauthorized (access token expired)
Attempt one token refresh using DEPUTY_REFRESH_TOKEN against the Deputy token endpoint. If refresh succeeds, retry the failed request once. If refresh fails (e.g. refresh token expired or revoked), halt Agent 3 immediately, post alert to SLACK_MANAGER_CHANNEL_ID with instructions to re-authorise the Deputy OAuth connection, and write AUTH_FAILURE to AUTOMATION_LOG.
Slack (manager conflict alert)
chat.postMessage returns error 'not_in_channel' or 'channel_not_found'
Retry with SLACK_STAFF_NOTIFY_CHANNEL_ID as fallback. If that also fails, send the conflict summary via Gmail to GMAIL_SENDER_ADDRESS with subject 'ACTION REQUIRED: Roster conflicts flagged'. Write SLACK_FALLBACK_USED to AUTOMATION_LOG. Do not proceed to Roster Approval polling until a conflict alert has been successfully delivered by at least one channel.
Slack (staff shift notification)
users.lookupByEmail returns 'users_not_found' for one or more staff
Fall back to Gmail for that staff member's shift notification. Log the unresolved staff email to AUTOMATION_LOG with status SLACK_DM_FALLBACK. Continue Slack DM delivery for remaining staff. Do not halt the workflow. After the notification loop completes, update the STAFF_ROSTER sheet column slack_user_id with 'UNRESOLVABLE' for audit purposes.
Xero (timesheet creation)
API returns ValidationErrors[] in the response body
Do not mark the export as successful. Log all validation error strings and the associated EmployeeID to AUTOMATION_LOG. Post the error detail to SLACK_MANAGER_CHANNEL_ID with instructions to resolve in Xero manually or correct the staff mapping and re-trigger the export. The re-trigger endpoint must be documented in the SOP. Do not duplicate timesheet entries; check for an existing TimesheetID before retrying.
Xero (token refresh)
Refresh token expired (60-day rolling window lapsed)
Halt the Xero export step. Post alert to SLACK_MANAGER_CHANNEL_ID and send email to GMAIL_SENDER_ADDRESS: 'Xero connection requires re-authorisation. Payroll export has not run.' Write AUTH_FAILURE to AUTOMATION_LOG. The FullSpec team must guide re-authorisation via the OAuth flow before the next pay-period close. Contact support@gofullspec.com if re-authorisation fails.
All integrations
Unclassified exception or network timeout at any step
Catch all unhandled exceptions at the workflow level. Write UNHANDLED_EXCEPTION with full stack trace and step context to AUTOMATION_LOG. Post an alert to SLACK_MANAGER_CHANNEL_ID: 'An unexpected error occurred in [workflow_name] at step [step_name]. Manual review required.' Never swallow the exception silently. Halt the affected step and await manual intervention or a scheduled retry no sooner than 15 minutes later.
Retry policy summary: all retries use exponential backoff starting at 2 seconds, doubling on each attempt, with a maximum of 5 retries unless otherwise specified per row above. After the final retry is exhausted, always log and alert before halting. Never loop indefinitely. For support or escalation on any integration failure, contact the FullSpec team at support@gofullspec.com.
Integration and API SpecPage 4 of 4

More documents for this process

Every document generated for Staff Scheduling & Rostering.

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