Back to Inventory Reorder Management

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

Inventory Reorder Management

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

This document is the authoritative integration reference for the Inventory Reorder Management automation. It covers every tool connected in the workflow, the exact authentication methods and OAuth scopes required, field-level mappings between systems, orchestration architecture, credential storage conventions, and defined failure behaviour for every integration point. The FullSpec team uses this specification during build and QA; it also serves as the ongoing maintenance reference after go-live.

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agent(s)
Cin7
Inventory polling trigger, draft PO creation, PO status reads
API key (Basic auth header)
Business plan or above (REST API access required)
Agent 1, Agent 2
Google Sheets
Sales velocity and lead time reference data; open PO tracking log
OAuth 2.0 (service account JSON or user OAuth)
Google Workspace free tier or personal Google account
Agent 1, Agent 2
Slack
Manager approval request and rejection routing; acknowledgement alert
OAuth 2.0 (Bot token via Slack App)
Free tier sufficient; paid tier required for message retention beyond 90 days
Agent 2
Gmail
Send finalised PO to supplier; send 24-hour acknowledgement chaser
OAuth 2.0 (Gmail API via Google Cloud project)
Any Google account with Gmail enabled
Agent 2
Xero
Create draft bill against supplier and PO value
OAuth 2.0 (PKCE flow, Xero App)
Starter plan or above (Bills API included)
Agent 2
Automation platform
Workflow orchestration layer, credential store, polling schedules, retry logic
Internal (platform credential store, no external auth)
Plan supporting webhook receivers, polling intervals under 5 min, and multi-step workflows
All agents
Before you connect anything: create sandbox or test instances for Cin7, Xero, and Google Sheets and validate all credentials and scopes in those environments first. Do not point any workflow step at production data until the full end-to-end test suite defined in the Test and QA Plan has passed. Gmail and Slack sandbox testing can use a dedicated test Google account and a private Slack workspace respectively.
Integration and API SpecPage 1 of 4
FS-DOC-05Technical

02Per-tool integration detail

Cin7

Cin7 is the source of truth for stock levels and the system in which draft purchase orders are created. The automation platform polls the Cin7 Products endpoint on a scheduled interval to detect SKUs at or below their reorder point, then writes a draft PO via the Purchase Orders endpoint.

Auth method
API key passed as a Basic Authorization header. Credentials: AccountId and ApplicationKey concatenated as AccountId:ApplicationKey, Base64-encoded. Header: Authorization: Basic <encoded_value>
Required scopes
Cin7 uses key-based auth with no OAuth scope model. The API key must belong to a user with the following Cin7 role permissions: Inventory > Read, Purchase Orders > Read and Write, Products > Read. Confirm in Cin7 Admin under Users and Permissions before connecting.
Webhook / trigger setup
Cin7 does not natively push stock-level webhooks on reorder point breach. The automation platform polls GET /api/v1/stock on a 5-minute interval, filtering by onHand <= reorderPoint. Store the last-seen SKU set in the platform's state store to avoid duplicate triggers on the same breach.
Required configuration
Each SKU must have reorderPoint and preferredSupplierId populated in Cin7 before go-live. The automation reads these fields at poll time. Do not hardcode SKU IDs or supplier IDs; read them dynamically from the API response and store the Cin7 API key and AccountId in the credential store under keys CIN7_ACCOUNT_ID and CIN7_API_KEY.
Rate limits
Cin7 REST API: 250 requests/minute per account. At current volume (approx. 287 runs/month, ~120 SKUs polled every 5 minutes), peak request rate is well under 10 requests/minute. No throttling layer is required at this volume; add exponential backoff on 429 responses as a precaution.
Constraints
Draft POs created via API are not automatically visible in the Cin7 mobile app until status is set to Pending. PO line items must include productId, qty, unitPrice, and supplierId. The API rejects POs with missing unitPrice; default to the last purchase price field (lastCost) if no override is provided.
// Poll input
GET /api/v1/stock?page=1&limit=250
// Poll output (filtered)
{ "productId": "P-1042", "sku": "BLK-HOODIE-M", "onHand": 12, "reorderPoint": 20, "preferredSupplierId": "SUP-007" }
// PO create input
POST /api/v1/purchaseorders
{ "supplierId": "SUP-007", "lines": [{ "productId": "P-1042", "qty": 60, "unitPrice": 14.50 }], "expectedDate": "2024-07-15", "status": "Draft" }
// PO create output
{ "purchaseOrderId": "PO-20240701-042", "status": "Draft", "totalValue": 870.00 }
Google Sheets

Google Sheets serves two distinct purposes: (1) the sales velocity and lead time reference table read by Agent 1 to calculate reorder quantities, and (2) the open PO tracking log written by Agent 2 after each PO is dispatched.

Auth method
OAuth 2.0. Use a Google Cloud service account with a downloaded JSON key file for server-to-server access. Store the JSON key contents in the credential store under key GSHEETS_SERVICE_ACCOUNT_JSON. Grant the service account Editor access to both target spreadsheets.
Required scopes
https://www.googleapis.com/auth/spreadsheets (read and write to spreadsheets). If Drive access is needed to locate the file by name, also include https://www.googleapis.com/auth/drive.readonly. Prefer hardcoded spreadsheet IDs over Drive search.
Webhook / trigger setup
Google Sheets is read and written to on demand; it is not a trigger source for this workflow. No webhook setup required.
Required configuration
Reference sheet (Sales Velocity and Lead Times) must have columns: sku, avg_daily_sales, lead_time_days, safety_stock_units, preferred_supplier_email. Tracking sheet (PO Tracker) must have columns: po_number, sku, supplier_name, supplier_email, qty_ordered, unit_price, total_value, po_date, expected_delivery, status, acknowledged. Store the spreadsheet IDs (not URLs) in the credential store under GSHEETS_REFERENCE_SHEET_ID and GSHEETS_TRACKER_SHEET_ID.
Rate limits
Google Sheets API: 300 read requests/minute per project, 60 write requests/minute per user. At current volume this automation makes fewer than 60 Sheets calls/hour. No throttling required; implement exponential backoff on 429 and 503 responses.
Constraints
Appending rows to the tracker sheet must use the values:append endpoint with insertDataOption=INSERT_ROWS to avoid overwriting existing data. The reference sheet must not use merged cells or frozen mid-table rows as these break range reads. All date values must be written in ISO 8601 format (YYYY-MM-DD) to ensure consistent sorting.
// Reference sheet read input
GET sheets/v4/spreadsheets/{GSHEETS_REFERENCE_SHEET_ID}/values/SKUReference!A2:F
// Reference sheet read output (one row)
{ "sku": "BLK-HOODIE-M", "avg_daily_sales": 4.2, "lead_time_days": 14, "safety_stock_units": 10, "preferred_supplier_email": "orders@supplier.com" }
// Tracker append input
POST sheets/v4/spreadsheets/{GSHEETS_TRACKER_SHEET_ID}/values/POTracker!A:L:append
{ "values": [["PO-20240701-042", "BLK-HOODIE-M", "Apex Garments", "orders@supplier.com", 60, 14.50, 870.00, "2024-07-01", "2024-07-15", "Sent", "Pending"]] }
Slack

Slack is used by Agent 2 to send an approval request to the operations manager when a PO value exceeds the configured approval threshold. The manager responds via Slack interactive buttons (Approve or Reject). A secondary alert is posted to the operations channel if no supplier acknowledgement is received within 24 hours.

Auth method
OAuth 2.0 Bot token. Create a Slack App in the Slack API console, install it to the workspace, and store the Bot User OAuth Token in the credential store under SLACK_BOT_TOKEN.
Required scopes
chat:write (post messages), chat:write.public (post to channels without joining), im:write (send DMs to the manager), users:read (resolve manager user ID from email), users:read.email (look up user by email address), channels:read (resolve channel ID by name). Interactive components (approve/reject buttons) require the app's Interactivity and Shortcuts feature to be enabled with a valid Request URL pointing to the automation platform's webhook receiver.
Webhook / trigger setup
Enable Interactivity in the Slack App settings. Set the Request URL to the automation platform's inbound webhook endpoint (stored as SLACK_INTERACTION_WEBHOOK_URL). Validate the request signature using the Slack signing secret (stored as SLACK_SIGNING_SECRET) on every interaction payload before processing.
Required configuration
Store the operations manager's Slack user ID under SLACK_MANAGER_USER_ID. Store the operations channel ID under SLACK_OPS_CHANNEL_ID. The approval threshold dollar value is stored as APPROVAL_THRESHOLD_USD in the credential store, not hardcoded. Slack Block Kit message templates for the approval request and the acknowledgement alert are defined as JSON templates in the platform's template store, not inline in the workflow step.
Rate limits
Slack Web API: Tier 3 methods (chat.postMessage) allow 50 requests/minute. At current volume (15 to 30 POs/month), Slack calls number fewer than 5 per day on average. No throttling required.
Constraints
Interactive message buttons expire after 30 minutes by default. If the manager does not respond within 30 minutes, the workflow must re-send the approval request or escalate. The interaction payload contains the original PO reference in the action value field; always validate this reference before proceeding. Slack does not guarantee delivery order; do not use message timestamps as workflow state.
// Approval request payload (chat.postMessage)
POST https://slack.com/api/chat.postMessage
{ "channel": "{SLACK_MANAGER_USER_ID}",
  "blocks": [
    { "type": "section", "text": { "type": "mrkdwn", "text": "*PO Approval Required*\nSKU: BLK-HOODIE-M | Qty: 60 | Value: $870.00 | Supplier: Apex Garments" } },
    { "type": "actions", "elements": [
      { "type": "button", "text": { "type": "plain_text", "text": "Approve" }, "style": "primary", "value": "PO-20240701-042|approve" },
      { "type": "button", "text": { "type": "plain_text", "text": "Reject" }, "style": "danger", "value": "PO-20240701-042|reject" }
    ]}
  ]
}
// Interaction callback received
{ "type": "block_actions", "actions": [{ "value": "PO-20240701-042|approve" }], "user": { "id": "U0123456789" } }
Gmail

Gmail is used by Agent 2 to send the finalised purchase order PDF to the supplier and, if no acknowledgement is received within 24 hours, to send an automatic follow-up chaser. Both sends originate from the operations team's designated sending address.

Auth method
OAuth 2.0 via the Gmail API (Google Cloud project). The sending account must be authenticated with a refresh token stored in the credential store under GMAIL_OAUTH_REFRESH_TOKEN and GMAIL_CLIENT_ID and GMAIL_CLIENT_SECRET. Use offline access type to obtain a long-lived refresh token.
Required scopes
https://www.googleapis.com/auth/gmail.send (compose and send email on behalf of the authenticated user). If sent-mail audit is required, also include https://www.googleapis.com/auth/gmail.readonly to verify send status. Do not request https://mail.google.com/ (full access) unless strictly necessary.
Webhook / trigger setup
Gmail is send-only in this workflow. No incoming webhook or Gmail push notification is configured for PO send. The 24-hour chaser is triggered by the automation platform's built-in wait/timer step, not by a Gmail reply detection. If supplier reply detection is added in a future phase, configure Gmail push notifications via the Cloud Pub/Sub API.
Required configuration
Store the sending email address as GMAIL_SENDER_ADDRESS. PO email subject and body templates are stored in the platform template store with placeholders: {{po_number}}, {{supplier_name}}, {{sku}}, {{qty}}, {{total_value}}, {{expected_delivery}}. The PO PDF attachment is generated by the automation platform from Cin7 API data before the Gmail step. Store the chaser email template separately under template key GMAIL_CHASER_TEMPLATE.
Rate limits
Gmail API: 250 quota units/second per user; sending limit is 500 messages/day for Google Workspace accounts and 100/day for personal Gmail. At 15 to 30 POs/month (plus up to 30 chasers), daily send volume is typically under 5. No throttling required.
Constraints
Gmail API send requires the message to be constructed as a RFC 2822-compliant MIME message, Base64url-encoded, and passed in the raw field of the POST body. PDF attachments must be Base64-encoded and included as a MIME multipart/mixed part. The from address in the MIME headers must exactly match the authenticated sending account or the API will reject the send.
// Gmail send input (POST users.messages.send)
POST https://gmail.googleapis.com/gmail/v1/users/me/messages/send
{ "raw": "<Base64url-encoded RFC 2822 message>" }
// Decoded MIME structure
From: operations@yourcompany.com
To: orders@supplier.com
Subject: Purchase Order PO-20240701-042 - BLK-HOODIE-M
Content-Type: multipart/mixed
  -- Part 1: text/plain body with {{po_number}}, {{qty}}, {{total_value}} resolved
  -- Part 2: application/pdf; name=PO-20240701-042.pdf (Base64-encoded)
// Gmail send output
{ "id": "18a3f9c2b1d4e5f6", "threadId": "18a3f9c2b1d4e5f6", "labelIds": ["SENT"] }
Xero

Xero receives a draft bill creation call from Agent 2 after the PO is dispatched to the supplier. The bill records the expected liability against the correct supplier contact, linked to the PO number as a reference, so the accounts team has immediate visibility of incoming payables.

Auth method
OAuth 2.0 with PKCE flow. Create a Xero App in the Xero Developer Portal, complete the OAuth 2.0 PKCE authorisation, and store the resulting tokens in the credential store under XERO_ACCESS_TOKEN, XERO_REFRESH_TOKEN, XERO_CLIENT_ID, XERO_CLIENT_SECRET, and XERO_TENANT_ID. Xero access tokens expire after 30 minutes; implement automatic refresh using the refresh token before each API call.
Required scopes
accounting.transactions (create and read bills and invoices), accounting.contacts.read (look up supplier contact by name or ContactID). Do not request accounting.settings or payroll scopes; principle of least privilege applies.
Webhook / trigger setup
Xero is a write target only in this workflow. No webhook from Xero is consumed. If future phases require payment status sync, configure a Xero webhook for Invoice events with signature validation using the Xero-delivered webhook key.
Required configuration
The automation must look up the Xero ContactID for each supplier by name using GET /Contacts?where=Name=="Apex Garments" before creating a bill. Do not hardcode ContactIDs; supplier names in the Google Sheets reference table must exactly match the Xero Contacts display name. Store the Xero Tenant ID as XERO_TENANT_ID in the credential store. Bill DueDate defaults to PO expected_delivery date unless overridden.
Rate limits
Xero API: 60 calls/minute per app per tenant; daily limit 5,000 calls. At 15 to 30 bills/month this automation makes fewer than 5 Xero calls per day. No throttling required. Implement retry with 60-second backoff on 429 responses.
Constraints
Xero bills (ACCPAY type) require Type, Contact (with ContactID), Date, DueDate, Status (DRAFT), and at least one LineItem with Description, Quantity, UnitAmount, and AccountCode. The AccountCode for purchase liability must be confirmed with the client's accountant before go-live; store it as XERO_PURCHASES_ACCOUNT_CODE in the credential store. Draft bills are not automatically approved; that remains a manual step for the accounts team.
// Supplier contact lookup
GET https://api.xero.com/api.xro/2.0/Contacts?where=Name%3D%3D%22Apex%20Garments%22
// Contact lookup response
{ "Contacts": [{ "ContactID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "Name": "Apex Garments" }] }
// Bill create input
POST https://api.xero.com/api.xro/2.0/Invoices
{ "Type": "ACCPAY", "Contact": { "ContactID": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" },
  "Date": "2024-07-01", "DueDate": "2024-07-15", "Status": "DRAFT",
  "Reference": "PO-20240701-042",
  "LineItems": [{ "Description": "BLK-HOODIE-M x60", "Quantity": 60, "UnitAmount": 14.50, "AccountCode": "{XERO_PURCHASES_ACCOUNT_CODE}" }]
}
// Bill create response
{ "Invoices": [{ "InvoiceID": "x9y8z7w6-v5u4-3210-fedc-ba9876543210", "InvoiceNumber": "BILL-0042", "Status": "DRAFT" }] }
Integration and API SpecPage 2 of 4
FS-DOC-05Technical

03Field mappings between tools

The tables below define the exact field mappings for each agent handoff in the workflow. Source and destination field names are shown in monospace to reflect their exact API or sheet column names. All mappings are resolved at runtime; no values are hardcoded in the workflow steps.

Handoff 1: Cin7 poll output to Agent 1 (Reorder Calculation Agent) context

Source tool
Source field
Destination tool
Destination field
Cin7
productId
Agent 1 context
sku_id
Cin7
sku
Agent 1 context
sku_code
Cin7
onHand
Agent 1 context
current_stock
Cin7
reorderPoint
Agent 1 context
reorder_point
Cin7
preferredSupplierId
Agent 1 context
supplier_id
Cin7
lastCost
Agent 1 context
unit_price

Handoff 2: Google Sheets reference table to Agent 1 (Reorder Calculation Agent) context

Source tool
Source field
Destination tool
Destination field
Google Sheets
avg_daily_sales
Agent 1 context
avg_daily_sales
Google Sheets
lead_time_days
Agent 1 context
lead_time_days
Google Sheets
safety_stock_units
Agent 1 context
safety_stock
Google Sheets
preferred_supplier_email
Agent 1 context
supplier_email

Handoff 3: Agent 1 output to Cin7 PO creation (Agent 2 input)

Source tool
Source field
Destination tool
Destination field
Agent 1 output
sku_id
Cin7
lines[].productId
Agent 1 output
reorder_qty
Cin7
lines[].qty
Agent 1 output
unit_price
Cin7
lines[].unitPrice
Agent 1 output
supplier_id
Cin7
supplierId
Agent 1 output
expected_delivery_date
Cin7
expectedDate

Handoff 4: Cin7 PO creation response to Agent 2 (PO Dispatch and Tracking Agent) context

Source tool
Source field
Destination tool
Destination field
Cin7
purchaseOrderId
Agent 2 context
po_number
Cin7
totalValue
Agent 2 context
po_total_value
Cin7
status
Agent 2 context
po_status

Handoff 5: Agent 2 context to Gmail PO send

Source tool
Source field
Destination tool
Destination field
Agent 2 context
supplier_email
Gmail
to
Agent 2 context
po_number
Gmail
subject (template: {{po_number}})
Agent 2 context
po_number
Gmail body template
{{po_number}}
Agent 2 context
sku_code
Gmail body template
{{sku}}
Agent 2 context
reorder_qty
Gmail body template
{{qty}}
Agent 2 context
po_total_value
Gmail body template
{{total_value}}
Agent 2 context
expected_delivery_date
Gmail body template
{{expected_delivery}}

Handoff 6: Agent 2 context to Xero bill creation

Source tool
Source field
Destination tool
Destination field
Agent 2 context
supplier_name
Xero
Contact.Name (lookup)
Agent 2 context
po_number
Xero
Reference
Agent 2 context
po_date
Xero
Date
Agent 2 context
expected_delivery_date
Xero
DueDate
Agent 2 context
sku_code + reorder_qty
Xero
LineItems[].Description
Agent 2 context
reorder_qty
Xero
LineItems[].Quantity
Agent 2 context
unit_price
Xero
LineItems[].UnitAmount

Handoff 7: Agent 2 context to Google Sheets PO Tracker append

Source tool
Source field
Destination tool
Destination field
Agent 2 context
po_number
Google Sheets
po_number
Agent 2 context
sku_code
Google Sheets
sku
Agent 2 context
supplier_name
Google Sheets
supplier_name
Agent 2 context
supplier_email
Google Sheets
supplier_email
Agent 2 context
reorder_qty
Google Sheets
qty_ordered
Agent 2 context
unit_price
Google Sheets
unit_price
Agent 2 context
po_total_value
Google Sheets
total_value
Agent 2 context
po_date
Google Sheets
po_date
Agent 2 context
expected_delivery_date
Google Sheets
expected_delivery
Agent 2 context
po_status
Google Sheets
status
Static value
"Pending"
Google Sheets
acknowledged
Integration and API SpecPage 3 of 4
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
Two discrete workflows: one per agent. Workflow 1 runs the Reorder Calculation Agent (Agent 1). Workflow 2 runs the PO Dispatch and Tracking Agent (Agent 2). Agent 1 passes its output payload to Agent 2 via an internal webhook call or a shared platform message queue, keeping the agents independently deployable and testable.
Shared credential store
Both workflows draw all secrets, IDs, and configurable thresholds from a single shared credential store. No credentials or threshold values are hardcoded in any workflow step. See the code block below for the full credential store schema.
Agent 1 trigger mechanism
Poll. The automation platform runs a scheduled poll against the Cin7 GET /api/v1/stock endpoint every 5 minutes. The platform's state store holds a snapshot of the last-known on-hand quantities per SKU. A trigger fires only when a SKU transitions from above to at-or-below its reorderPoint, preventing repeated triggers for the same breach event. Poll interval is configurable via the POLL_INTERVAL_MINUTES credential store key.
Agent 2 trigger mechanism
Webhook (internal). Agent 2 is triggered by an inbound webhook payload posted by Agent 1 upon completion of the reorder quantity calculation and draft PO data preparation. The webhook endpoint is protected by a shared HMAC-SHA256 signature; Agent 1 signs the payload using AGENT_WEBHOOK_SECRET and Agent 2 validates the X-FullSpec-Signature header before processing.
Slack interaction callback
Webhook (external). The Slack App posts approval button interaction payloads to the automation platform's publicly accessible inbound webhook URL (SLACK_INTERACTION_WEBHOOK_URL). The platform validates the X-Slack-Signature header using SLACK_SIGNING_SECRET before processing the approve or reject action.
24-hour chaser timer
After the Gmail PO send step in Agent 2, the workflow registers a deferred execution event keyed to the po_number with a 24-hour delay. If no acknowledgement flag is set on the matching Google Sheets tracker row before the timer fires, the chaser branch executes: a Gmail chaser email is sent and a Slack alert is posted to SLACK_OPS_CHANNEL_ID.
Logging
All workflow run logs, including trigger events, API call outcomes, retry attempts, and error states, are written to the automation platform's native execution log. Log retention must be set to a minimum of 90 days. Failed runs must generate an alert to SLACK_OPS_CHANNEL_ID within 5 minutes of failure.
All values in angle brackets must be replaced with real credentials before deployment. Never commit secrets to version control.
// Credential store contents (all keys required before first run)

// Cin7
CIN7_ACCOUNT_ID           = "<cin7-account-id>"
CIN7_API_KEY              = "<cin7-application-key>"

// Google Sheets
GSHEETS_SERVICE_ACCOUNT_JSON    = "<full JSON key file contents>"
GSHEETS_REFERENCE_SHEET_ID      = "<spreadsheet-id-of-sku-reference-sheet>"
GSHEETS_TRACKER_SHEET_ID        = "<spreadsheet-id-of-po-tracker-sheet>"

// Gmail
GMAIL_OAUTH_REFRESH_TOKEN = "<oauth2-refresh-token>"
GMAIL_CLIENT_ID           = "<google-cloud-client-id>"
GMAIL_CLIENT_SECRET       = "<google-cloud-client-secret>"
GMAIL_SENDER_ADDRESS      = "operations@yourcompany.com"

// Xero
XERO_CLIENT_ID            = "<xero-app-client-id>"
XERO_CLIENT_SECRET        = "<xero-app-client-secret>"
XERO_ACCESS_TOKEN         = "<xero-oauth2-access-token>"
XERO_REFRESH_TOKEN        = "<xero-oauth2-refresh-token>"
XERO_TENANT_ID            = "<xero-organisation-tenant-id>"
XERO_PURCHASES_ACCOUNT_CODE = "<chart-of-accounts-code-for-purchases>"

// Slack
SLACK_BOT_TOKEN           = "xoxb-<slack-bot-token>"
SLACK_SIGNING_SECRET      = "<slack-app-signing-secret>"
SLACK_MANAGER_USER_ID     = "U<slack-user-id-of-operations-manager>"
SLACK_OPS_CHANNEL_ID      = "C<slack-channel-id-of-ops-channel>"
SLACK_INTERACTION_WEBHOOK_URL = "https://<platform-host>/webhooks/slack-interactions"

// Internal agent-to-agent webhook
AGENT_WEBHOOK_SECRET      = "<hmac-sha256-shared-secret>"
AGENT2_INBOUND_WEBHOOK_URL = "https://<platform-host>/webhooks/po-dispatch-agent"

// Business logic thresholds (configurable without code change)
APPROVAL_THRESHOLD_USD    = 500
POLL_INTERVAL_MINUTES     = 5
CHASER_DELAY_HOURS        = 24
APPROVAL_THRESHOLD_USD, POLL_INTERVAL_MINUTES, and CHASER_DELAY_HOURS are business logic parameters, not secrets. They are stored in the credential store for centralised, code-free adjustment by the FullSpec team or the process owner without requiring a workflow redeploy.

05Error handling and retry logic

Every integration point in the automation has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors that cannot be resolved by automated retry must generate a Slack alert to the operations channel and log a structured error entry in the platform execution log.

Integration
Scenario
Required behaviour
Cin7 poll
API returns 401 Unauthorized
Halt polling immediately. Post alert to SLACK_OPS_CHANNEL_ID: 'Cin7 API auth failure, polling suspended.' Do not retry with the same credentials. Require manual credential refresh.
Cin7 poll
API returns 429 Too Many Requests
Pause polling. Retry after exponential backoff: 30 seconds, then 60 seconds, then 120 seconds. After 3 failed retries, post Slack alert and suspend polling until next scheduled interval.
Cin7 poll
SKU missing reorderPoint field (null or zero)
Skip the SKU. Append the SKU code to a 'skipped SKUs' log entry in the platform execution log. Do not trigger the reorder flow. Post a daily digest to SLACK_OPS_CHANNEL_ID listing all skipped SKUs if count > 0.
Cin7 PO creation
API returns 400 Bad Request (missing or invalid field)
Halt the workflow for this SKU. Log the full request payload and API error response. Post Slack alert with SKU code and error reason. Do not retry automatically; require manual review of PO data.
Google Sheets read (reference)
SKU not found in reference sheet
Halt the reorder calculation for this SKU. Log the missing SKU. Post Slack alert: 'SKU {sku_code} not found in reference sheet. Reorder calculation skipped.' Do not proceed to PO creation.
Google Sheets read/write
API returns 503 Service Unavailable
Retry up to 3 times with exponential backoff: 15 seconds, 30 seconds, 60 seconds. If all retries fail, post Slack alert and halt the current workflow run. The next poll cycle will re-evaluate the trigger condition.
Slack approval message
chat.postMessage fails (network error or invalid user ID)
Retry once after 30 seconds. If the second attempt fails, fall back to sending the approval request via Gmail to the operations manager's email address. Log the Slack failure and the fallback action.
Slack interaction callback
Signature validation fails (invalid X-Slack-Signature)
Reject the payload immediately with HTTP 400. Log the rejection with the received signature and timestamp. Do not process the action. Post Slack alert to SLACK_OPS_CHANNEL_ID: 'Suspicious Slack interaction received and rejected.'
Slack approval
No manager response within 30 minutes (button expiry)
Re-send the approval request message to the manager. If a second 30-minute window passes with no response, escalate by posting to SLACK_OPS_CHANNEL_ID and sending a Gmail alert to the manager. Do not auto-approve high-value POs.
Gmail send (PO)
API returns 400 or 403 (malformed message or auth failure)
Halt the PO send step. Log the error with the full MIME message structure. Post Slack alert with the PO number and error detail. Do not proceed to Xero bill creation or Sheets logging until the send is confirmed successful.
Xero bill creation
Supplier contact not found in Xero (lookup returns empty array)
Do not create the bill. Log the missing supplier name. Post Slack alert: 'Xero contact not found for supplier {supplier_name}. Bill creation skipped.' The PO send to Gmail and Sheets logging proceed independently; Xero bill requires manual creation.
Xero bill creation
Access token expired (401 Unauthorized)
Automatically refresh the access token using XERO_REFRESH_TOKEN before retrying the bill creation call. If the refresh also returns 401, halt and post Slack alert: 'Xero token refresh failed. Manual re-authorisation required.'
Google Sheets tracker append
Append fails after 3 retries
Log the failed row data to the platform execution log in full. Post Slack alert to SLACK_OPS_CHANNEL_ID with the PO number and all field values so the row can be manually added. Never silently drop a PO log entry.
Gmail chaser send
24-hour timer fires but acknowledgement status is already 'Confirmed' in Sheets
Cancel the chaser send. No action required. Log 'Chaser suppressed: acknowledgement already recorded for {po_number}'.'
The rule is absolute: no failure anywhere in the workflow may pass without a log entry and, for any failure that blocks PO creation, dispatch, or Xero billing, a Slack alert to SLACK_OPS_CHANNEL_ID. Silent failures in a financial workflow create reconciliation gaps that are costly to unwind. Every exception path is tested in the QA plan before go-live.
Integration and API SpecPage 4 of 4

More documents for this process

Every document generated for Inventory Reorder Management.

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