Back to 3PL / Warehouse Coordination

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

3PL / Warehouse Coordination Automation

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

This document is the definitive integration reference for the 3PL / Warehouse Coordination automation. It covers every external tool connected in the build, the exact authentication requirements and API scopes for each, field-level mappings across agent handoffs, the orchestration layout and credential store structure, and the required error-handling behaviour at each integration point. The FullSpec team uses this document as the build authority during development and testing. It should be read alongside the Developer Handover Pack (FS-DOC-04) and the Test and QA Plan (FS-DOC-06).

01Tool inventory

Tool
Role in automation
Auth method
Min plan required
Used by agents
ShipBob
3PL data source: inventory levels, inbound ASNs, outbound dispatch statuses
API key (Bearer token)
Any plan with API access enabled (requires ShipBob support activation)
Agent 1
Cin7
OMS inventory record reads and stock-level writes
API key + Account ID (Basic Auth over HTTPS)
Business plan or above (API access included)
Agent 2, Agent 3
Shopify
Storefront inventory sync: update variant stock levels after reconciliation
OAuth 2.0 access token (private app or custom app)
Basic Shopify or above
Agent 3
Slack
Exception alerts and daily reconciliation summary to fulfilment channel
OAuth 2.0 Bot Token (Slack app installation)
Free tier or above (incoming webhooks available on all tiers)
Agent 3
Google Sheets
Reconciliation log and audit trail: one row appended per run
OAuth 2.0 service account (JSON key) or user OAuth
Google Workspace or free Google account with Sheets access
Agent 2
Orchestration layer (automation platform)
Hosts all three agent workflows, manages scheduling, webhook ingestion, credential store, and inter-agent data passing
Platform-internal credential management
Paid tier supporting webhooks, scheduled triggers, and credential vaults (budgeted at $120/month)
All agents
Before you connect anything: provision sandbox or test credentials for every tool listed above and validate each connection in a non-production environment before any production credentials are entered into the credential store. ShipBob provides a staging environment on request. Cin7 supports read-only API keys for testing. Use a Shopify development store for all integration testing. Never hardcode production credentials in workflow logic.

02Per-tool integration detail

ShipBob

Primary 3PL data source. The automation reads inventory snapshots, inbound receiving records, and outbound fulfillment order statuses. ShipBob also emits webhooks for inbound and outbound status changes that serve as the event-based trigger for Agent 1.

Auth method
Bearer token. Include the token in the Authorization header of every request: Authorization: Bearer {SHIPBOB_API_TOKEN}. Token is generated in the ShipBob Merchant Dashboard under Settings > API.
Required scopes
openid, offline_access, https://api.shipbob.com/inventory_read, https://api.shipbob.com/order_read, https://api.shipbob.com/receiving_read. Confirm scope strings in the ShipBob Developer Portal at the time of app registration, as ShipBob may version these.
Webhook / trigger setup
Register webhooks in the ShipBob Merchant Dashboard under Settings > Webhooks. Subscribe to: fulfillment_order_shipped, receiving_completed, receiving_created. Set the target URL to the Agent 1 inbound webhook endpoint on the orchestration platform. ShipBob signs payloads with an HMAC-SHA256 signature in the X-ShipBob-Hmac-SHA256 header. Agent 1 must validate this signature against the shared secret stored as SHIPBOB_WEBHOOK_SECRET before processing any payload.
Required configuration
SHIPBOB_API_TOKEN stored in the credential store (never hardcoded). SHIPBOB_WEBHOOK_SECRET stored in the credential store. The ShipBob Channel ID for the merchant account stored as SHIPBOB_CHANNEL_ID in the credential store and passed as the channel_id query parameter on all inventory and order API calls.
Rate limits
ShipBob enforces 200 requests per minute per token. At ~220 shipment events per month with one scheduled daily poll plus event-driven webhook triggers, peak sustained request rate will not exceed 30 requests per poll cycle. No throttling layer is required at current volume. Build in a 300 ms inter-request delay as a precaution and implement exponential backoff on 429 responses.
Key endpoints
GET /1.0/inventory (inventory snapshot), GET /1.0/receiving (inbound ASN list), GET /1.0/order (outbound fulfillment orders). All endpoints paginated with page and limit parameters; default page size is 50, set limit=250 and iterate pages to completion each run.
Constraints
ShipBob SKU codes may differ from the internal OMS SKU format. All fetched records must be passed through the SKU normalisation mapping before downstream use. The mapping table is stored in the credential/config store as a JSON object (SHIPBOB_SKU_MAP). New catalogue additions must be added to this map before they will reconcile correctly.
// Inputs
Scheduled trigger (daily cron) OR webhook POST from ShipBob
SHIPBOB_API_TOKEN, SHIPBOB_CHANNEL_ID from credential store
SHIPBOB_SKU_MAP (JSON) from config store
// Outputs
Normalised inventory snapshot array: [{ sku_internal, sku_shipbob, qty_on_hand, qty_committed, qty_receiving }]
Normalised ASN list: [{ asn_id, po_number, sku_internal, qty_expected, received_date, status }]
Normalised outbound list: [{ order_id, sku_internal, qty_shipped, dispatch_date, carrier, tracking }]
Cin7

OMS and inventory master record. Agent 2 reads current stock levels per SKU to compare against the ShipBob dataset. Agent 3 writes approved stock adjustments back to Cin7 with a structured adjustment note per change.

Auth method
HTTP Basic Authentication. Credentials are a Cin7 Account ID and an API Key combined as Base64(AccountID:APIKey) in the Authorization header: Authorization: Basic {BASE64_CREDENTIALS}. These are generated in Cin7 Settings > Integrations > API.
Required scopes
Cin7 uses key-level permissions rather than OAuth scopes. The API key must be granted: Products (Read), Stock Adjustments (Read, Write), Purchase Orders (Read). Confirm with the Cin7 account administrator that the key does not have IP restrictions that would block the orchestration platform's egress IPs.
Webhook / trigger setup
Cin7 is not a trigger source in this automation. Agent 2 polls Cin7 synchronously during each reconciliation run. No inbound webhook registration is required.
Required configuration
CIN7_ACCOUNT_ID stored in credential store. CIN7_API_KEY stored in credential store. CIN7_BASE_URL stored as config: https://api.cin7.com/api/v1. The Stock Adjustment reason code to use for automated adjustments stored as CIN7_ADJUSTMENT_REASON (e.g. '3PL Reconciliation - Automated').
Rate limits
Cin7 permits 1,000 API requests per day per account on the Business plan. A single reconciliation run reads one record per unique SKU. At a typical catalogue of up to 500 SKUs per run plus adjustment writes, daily consumption will not exceed 600 requests. No throttling is required at current volume. Implement exponential backoff on 429 and 503 responses with a maximum of 3 retries.
Key endpoints
GET /Product?fields=id,code,stockOnHand (inventory read, paginated), POST /StockAdjustment (write approved adjustments). When writing adjustments, include: productId, qty (signed integer), reason, memo (timestamp and run ID), and warehouseId matching the Cin7 location for ShipBob inventory.
Constraints
The Cin7 warehouseId for the ShipBob location must be confirmed during scoping and stored as CIN7_WAREHOUSE_ID in the config store. If Cin7 is already natively synced to Shopify, the Agent 3 Shopify write step may create double-adjustments: verify this during API access setup. Stock adjustments are audited in Cin7 against the user or API key that created them, so a dedicated API key (not a shared user key) is strongly recommended.
// Inputs (Agent 2 read)
Normalised SKU list from Agent 1 output
CIN7_ACCOUNT_ID, CIN7_API_KEY, CIN7_BASE_URL, CIN7_WAREHOUSE_ID from credential store
// Outputs (Agent 2)
Cin7 inventory snapshot: [{ sku_internal, cin7_product_id, qty_on_hand }]
Classified result set: [{ sku_internal, cin7_product_id, shipbob_qty, cin7_qty, variance, classification }]
// Inputs (Agent 3 write)
Classified result set filtered to classification == 'minor_variance' or 'matched'
CIN7_ADJUSTMENT_REASON, CIN7_WAREHOUSE_ID from config store
// Outputs (Agent 3)
Cin7 StockAdjustment confirmation: [{ sku_internal, cin7_product_id, adjustment_qty, adjustment_id, timestamp }]
Shopify

Storefront inventory system. Agent 3 pushes confirmed stock levels to Shopify after Cin7 adjustments are written, updating available inventory per variant so the storefront reflects accurate counts without manual entry.

Auth method
OAuth 2.0 access token via a Shopify Custom App. Create the app in the Shopify Partner Dashboard or directly in the store admin under Settings > Apps > Develop apps. The access token is displayed once on app installation; store it immediately as SHOPIFY_ACCESS_TOKEN in the credential store. Include in all requests: X-Shopify-Access-Token: {SHOPIFY_ACCESS_TOKEN}.
Required scopes
read_inventory, write_inventory, read_products. Request these scopes during custom app configuration in the Shopify admin. Do not request broader scopes (read_orders, write_orders) as they are not required and increase the attack surface.
Webhook / trigger setup
Shopify is a write target only in this automation. No inbound webhooks are consumed from Shopify. Agent 3 initiates all calls after receiving confirmed Cin7 adjustment results.
Required configuration
SHOPIFY_ACCESS_TOKEN in credential store. SHOPIFY_STORE_DOMAIN in config store (e.g. yourcompany.myshopify.com). SHOPIFY_LOCATION_ID in config store: the inventory location ID corresponding to the ShipBob fulfilment location in Shopify, retrieved via GET /admin/api/2024-01/locations.json during setup. SKU-to-Shopify inventory_item_id mapping must be pre-built and stored as SHOPIFY_INVENTORY_MAP (JSON) in the config store.
Rate limits
Shopify REST Admin API allows 2 requests per second (leaky bucket, burst of 40) on standard plans. At ~220 events per month across daily runs, peak write load per run is bounded by the number of SKUs adjusted. For up to 500 SKU writes per run spaced across 300 ms delays, the burst bucket will not be exhausted. No throttling layer is required. Implement retry on 429 using the Retry-After header value returned by Shopify.
Key endpoints
POST /admin/api/2024-01/inventory_levels/set.json with body: { inventory_item_id, location_id, available }. Use set (absolute) rather than adjust (relative) to ensure the Shopify level exactly matches the confirmed Cin7 figure after each reconciliation run.
Constraints
Confirm whether a native Cin7-Shopify sync is active. If it is, disable it or coordinate write sequencing to avoid double-adjustments. The SHOPIFY_INVENTORY_MAP must contain an entry for every SKU in the reconciliation scope; unmapped SKUs must be logged as warnings and excluded from the write, not silently skipped. All inventory writes must use the specific location_id for the ShipBob warehouse, not the default Shopify location.
// Inputs
Cin7 adjustment confirmation list from Agent 3 Cin7 write step
SHOPIFY_ACCESS_TOKEN, SHOPIFY_STORE_DOMAIN, SHOPIFY_LOCATION_ID, SHOPIFY_INVENTORY_MAP from credential/config store
// Outputs
Shopify inventory level set confirmation: [{ sku_internal, inventory_item_id, location_id, available_set, timestamp }]
Warning list for unmapped SKUs: [{ sku_internal, reason }]
Integration and API SpecPage 1 of 3
FS-DOC-05Technical
Slack

Notification delivery channel. Agent 3 posts structured exception alerts for major discrepancies and missing ASNs, and sends a daily reconciliation summary to the designated fulfilment channel.

Auth method
OAuth 2.0 Bot Token. Create a Slack app at api.slack.com/apps, add the Bot Token Scopes below, install the app to the workspace, and copy the Bot User OAuth Token. Store as SLACK_BOT_TOKEN in the credential store. Include in all API calls: Authorization: Bearer {SLACK_BOT_TOKEN}.
Required scopes
chat:write, chat:write.public (to post to channels the bot has not been invited to), channels:read (to resolve channel names to IDs at startup). Do not request files:write or users:read unless a future feature requires them.
Webhook / trigger setup
Slack is a write target only. No incoming webhooks are used; all messages are sent via the Slack Web API (chat.postMessage). Store the fulfilment channel ID as SLACK_CHANNEL_FULFILMENT and the finance channel ID as SLACK_CHANNEL_FINANCE in the config store. Channel IDs are stable; do not resolve channel names dynamically at runtime.
Required configuration
SLACK_BOT_TOKEN in credential store. SLACK_CHANNEL_FULFILMENT (channel ID, e.g. C04XXXXXXXX) in config store. SLACK_CHANNEL_FINANCE in config store. SLACK_ALERT_MENTION_USER (optional Slack user ID to @mention on critical alerts) in config store. Message templates are defined in Agent 3 workflow logic, not in Slack; keep them version-controlled in the workflow.
Rate limits
Slack Web API chat.postMessage is rate-limited to approximately 1 message per second per channel (Tier 3: burst of 20). At current volume, Agent 3 sends at most one summary plus a bounded number of exception alerts per run. No throttling is required. Space rapid sequential messages with a 1,100 ms delay to stay safely under burst limits.
Constraints
The Slack bot must be invited to both the fulfilment and finance channels before the first production run (use /invite @botname in each channel). If the channel is private, the bot must be a member. Exception alert messages must include: SKU code, expected count, actual count, variance classification, and a direct URL to the relevant Cin7 product record for fast investigation.
// Inputs
Classified discrepancy list: items where classification == 'major_discrepancy' or asn_status == 'missing'
Daily summary payload: { run_date, total_skus, matched, minor_variance, major_discrepancy, adjustments_written, open_exceptions }
SLACK_BOT_TOKEN, SLACK_CHANNEL_FULFILMENT, SLACK_CHANNEL_FINANCE from credential/config store
// Outputs
Slack message timestamp (ts) for each posted message: [{ channel_id, ts, message_type }]
Delivery confirmation or error response from Slack API
Google Sheets

Audit log and reconciliation record. Agent 2 appends one row per reconciliation run to the master log sheet, capturing run metadata, SKU-level variance counts, adjustments made, and open exceptions for operations and finance review.

Auth method
OAuth 2.0 via a Google Cloud service account. Create a service account in the Google Cloud Console under IAM and Admin > Service Accounts, generate a JSON key, and store the entire JSON key as GOOGLE_SERVICE_ACCOUNT_KEY in the credential store. Share the target Google Sheet with the service account email address (e.g. automation@yourproject.iam.gserviceaccount.com) with Editor permissions.
Required scopes
https://www.googleapis.com/auth/spreadsheets (read and write to Sheets). Do not request https://www.googleapis.com/auth/drive; the narrower Sheets scope is sufficient and should be preferred.
Webhook / trigger setup
Google Sheets is a write target only. No triggers are consumed from Sheets in this automation. Agent 2 appends rows using the Sheets API v4 values.append method after each reconciliation pass completes.
Required configuration
GOOGLE_SHEETS_LOG_ID: the Spreadsheet ID of the master reconciliation log, stored in the config store (extracted from the sheet URL: docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/edit). GOOGLE_SHEETS_LOG_TAB: the tab name for the log (default: 'Reconciliation Log'). Sheet must be pre-created with the header row in place: Run Date, Run ID, Total SKUs, Matched, Minor Variance, Major Discrepancy, Adjustments Written, Open Exceptions, Run Duration (s), Triggered By.
Rate limits
Google Sheets API allows 300 write requests per minute per project and 60 requests per minute per user. A single run appends one row (one API call). At one or more runs per day the rate limit will never be approached. No throttling is required.
Constraints
The service account key JSON must be rotated at least annually and whenever team access changes. The spreadsheet must not be deleted or moved; if the GOOGLE_SHEETS_LOG_ID becomes invalid, Agent 2 will throw a non-recoverable error. Store the Sheet URL alongside the ID in the config store for human reference. Do not store sensitive SKU or financial data beyond what is needed for the audit log row.
// Inputs
Reconciliation run summary: { run_date, run_id, total_skus, matched, minor_variance, major_discrepancy, adjustments_written, open_exceptions, duration_seconds, triggered_by }
GOOGLE_SERVICE_ACCOUNT_KEY, GOOGLE_SHEETS_LOG_ID, GOOGLE_SHEETS_LOG_TAB from credential/config store
// Outputs
Sheets API append response: { spreadsheetId, tableRange, updates.updatedRows }
Confirmed row number of appended entry (for logging)

03Field mappings between tools

The following tables define the exact field-level mappings at each agent handoff point. All source and destination field names are given in monospace notation matching the API response or request body keys used by each tool. The SKU normalisation step (Agent 1) is the critical gateway: no field downstream should ever carry a raw ShipBob SKU; all records must use sku_internal after normalisation.

Handoff 1: Agent 1 (ShipBob) to Agent 2 (Cin7 reconciliation)

Source tool
Source field
Destination tool
Destination field
ShipBob API
`inventory[].fulfillable_quantity`
Agent 2 normalised dataset
`shipbob_qty_on_hand`
ShipBob API
`inventory[].committed_quantity`
Agent 2 normalised dataset
`shipbob_qty_committed`
ShipBob API
`inventory[].awaiting_quantity`
Agent 2 normalised dataset
`shipbob_qty_receiving`
ShipBob API (via SHIPBOB_SKU_MAP)
`inventory[].name` (mapped)
Agent 2 normalised dataset
`sku_internal`
ShipBob API
`receiving[].id`
Agent 2 normalised dataset
`asn_id`
ShipBob API
`receiving[].purchase_order_number`
Agent 2 normalised dataset
`po_number`
ShipBob API
`receiving[].status`
Agent 2 normalised dataset
`asn_status`
ShipBob API
`receiving[].expected_arrival_date`
Agent 2 normalised dataset
`asn_expected_date`
ShipBob API
`order[].id`
Agent 2 normalised dataset
`shipbob_order_id`
ShipBob API
`order[].shipments[].tracking_number`
Agent 2 normalised dataset
`tracking_number`

Handoff 2: Agent 2 (Cin7 read + classification) to Agent 3 (Cin7 write + Shopify + Slack + Sheets)

Source tool
Source field
Destination tool
Destination field
Agent 2 classified dataset
`sku_internal`
Cin7 POST /StockAdjustment
`productId` (resolved via Cin7 product lookup)
Agent 2 classified dataset
`variance` (signed integer)
Cin7 POST /StockAdjustment
`qty`
Agent 2 classified dataset
`run_id`
Cin7 POST /StockAdjustment
`memo` (prefixed: '3PL Reconciliation - Automated | run_id: ...')
Agent 2 classified dataset
`sku_internal`
Shopify inventory_levels/set.json
`inventory_item_id` (resolved via SHOPIFY_INVENTORY_MAP)
Agent 2 classified dataset
`shipbob_qty_on_hand`
Shopify inventory_levels/set.json
`available`
Agent 2 classified dataset
`classification` == 'major_discrepancy'
Slack chat.postMessage
Alert block: `text` field (formatted message)
Agent 2 classified dataset
`sku_internal`
Slack alert block
`text` (SKU identifier in message body)
Agent 2 classified dataset
`shipbob_qty_on_hand`
Slack alert block
`text` (actual count field in message body)
Agent 2 classified dataset
`cin7_qty`
Slack alert block
`text` (expected count field in message body)
Agent 2 run summary
`total_skus`, `matched`, `minor_variance`, `major_discrepancy`, `adjustments_written`
Google Sheets values.append
Columns D through H of log tab row
Orchestration layer
`run_date`, `run_id`, `duration_seconds`, `triggered_by`
Google Sheets values.append
Columns A through C and I through J of log tab row
Integration and API SpecPage 2 of 3
FS-DOC-05Technical

04Build stack and orchestration

Orchestration layout
Three discrete workflows, one per agent. Agent 1 (3PL Data Fetch and Normalisation), Agent 2 (Reconciliation and Discrepancy), Agent 3 (Update and Notification). Each workflow is independently deployable and testable. Agents are chained by data passing: Agent 1 output is the trigger payload for Agent 2; Agent 2 output is the trigger payload for Agent 3. No shared mutable state exists between agents outside the credential and config store.
Credential store
A single platform-level credential store is used across all three agent workflows. All API tokens, account IDs, and OAuth credentials are stored as named secret entries in this store. No credential value appears in any workflow logic, mapping expression, or log output. Access to the credential store is restricted to the FullSpec build account and the nominated technical owner at [YourCompany.com].
Config store
Non-secret configuration values (channel IDs, spreadsheet IDs, warehouse IDs, SKU maps, threshold values) are stored as named config entries in the platform config or environment variable store, separate from secret credentials. Config values can be updated by the operations team without touching workflow logic.
Agent 1 trigger mechanism
Dual trigger: (1) scheduled cron firing once daily at a configured time (e.g. 06:00 local business time), and (2) inbound webhook listener endpoint hosted by the orchestration platform, receiving ShipBob fulfillment_order_shipped, receiving_completed, and receiving_created events. Webhook payloads are validated using HMAC-SHA256 signature verification against SHIPBOB_WEBHOOK_SECRET before the workflow proceeds. Invalid signatures must be rejected with HTTP 401 and logged.
Agent 2 trigger mechanism
Internal trigger: Agent 2 is invoked programmatically by Agent 1 upon successful completion of the data fetch and normalisation step. The normalised dataset is passed as the input payload. Agent 2 does not expose a public webhook endpoint.
Agent 3 trigger mechanism
Internal trigger: Agent 3 is invoked programmatically by Agent 2 upon successful completion of reconciliation and classification. The classified result set and run summary are passed as the input payload. Agent 3 does not expose a public webhook endpoint.
Discrepancy thresholds
Minor variance threshold and major discrepancy threshold are stored as RECONCILIATION_MINOR_THRESHOLD (integer, default 2) and RECONCILIATION_MAJOR_THRESHOLD (integer, default 10) in the config store. These values are set in agreement with the operations manager before go-live and can be adjusted at any time without a rebuild.
Logging
All agent runs produce a structured run log (run_id, start_time, end_time, trigger_type, items_processed, errors). Run logs are retained in the orchestration platform for a minimum of 90 days. The Google Sheets log provides a human-readable audit trail for the operations and finance teams independently of platform logs.

The following code block shows the complete credential store and config store entry list. All entries must be provisioned before any agent workflow is activated in production.

Credential store and config store entries (orchestration platform)
// === CREDENTIAL STORE (secret, encrypted at rest) ===

SHIPBOB_API_TOKEN          // Bearer token from ShipBob Merchant Dashboard
SHIPBOB_WEBHOOK_SECRET     // HMAC-SHA256 signing secret for webhook validation
CIN7_ACCOUNT_ID            // Cin7 account identifier (Basic Auth username)
CIN7_API_KEY               // Cin7 API key (Basic Auth password)
SHOPIFY_ACCESS_TOKEN       // Custom app OAuth access token (X-Shopify-Access-Token header)
SLACK_BOT_TOKEN            // Slack bot OAuth token (Bearer, chat:write scope)
GOOGLE_SERVICE_ACCOUNT_KEY // Full JSON key for Google Cloud service account (multi-line)

// === CONFIG STORE (non-secret, auditable) ===

SHIPBOB_CHANNEL_ID         // ShipBob merchant channel ID (passed as channel_id param)
SHIPBOB_SKU_MAP            // JSON object: { 'SHIPBOB-SKU-001': 'INTERNAL-SKU-001', ... }

CIN7_BASE_URL              // 'https://api.cin7.com/api/v1'
CIN7_WAREHOUSE_ID          // Cin7 location ID for the ShipBob warehouse
CIN7_ADJUSTMENT_REASON     // e.g. '3PL Reconciliation - Automated'

SHOPIFY_STORE_DOMAIN       // e.g. 'yourcompany.myshopify.com'
SHOPIFY_LOCATION_ID        // Shopify inventory location ID for ShipBob fulfilment location
SHOPIFY_INVENTORY_MAP      // JSON object: { 'INTERNAL-SKU-001': 'shopify_inventory_item_id', ... }

SLACK_CHANNEL_FULFILMENT   // Slack channel ID for fulfilment alerts (e.g. 'C04XXXXXXXX')
SLACK_CHANNEL_FINANCE      // Slack channel ID for daily finance summary
SLACK_ALERT_MENTION_USER   // Optional Slack user ID for @mention on critical alerts

GOOGLE_SHEETS_LOG_ID       // Spreadsheet ID of the master reconciliation log sheet
GOOGLE_SHEETS_LOG_TAB      // Sheet tab name (default: 'Reconciliation Log')

RECONCILIATION_MINOR_THRESHOLD  // Integer: max variance to auto-correct (default: 2)
RECONCILIATION_MAJOR_THRESHOLD  // Integer: variance triggering Slack alert (default: 10)

DAILY_TRIGGER_TIME         // Cron expression for scheduled daily run (e.g. '0 6 * * 1-5')
RUN_TIMEZONE               // Timezone for cron scheduling (e.g. 'America/New_York')

05Error handling and retry logic

Every integration point has a defined failure behaviour. Unhandled exceptions must never fail silently. All errors must be logged to the platform run log with a structured error object containing: integration name, error code, message, timestamp, and run ID. Where a Slack alert channel is reachable, critical integration failures must also post a Slack notification to SLACK_CHANNEL_FULFILMENT.

Integration
Scenario
Required behaviour
ShipBob API (Agent 1)
HTTP 401 Unauthorized on inventory or order fetch
Halt Agent 1 immediately. Log error with credential reference. Post Slack alert to SLACK_CHANNEL_FULFILMENT: 'ShipBob API authentication failed. Check SHIPBOB_API_TOKEN. Run aborted.' Do not proceed to Agent 2. No silent failure.
ShipBob API (Agent 1)
HTTP 429 Too Many Requests
Pause and retry after 60 seconds (exponential backoff: 60s, 120s, 240s). Maximum 3 retries. If all retries exhausted, log error and post Slack alert. Abort run and mark for manual retry.
ShipBob Webhook (Agent 1)
Invalid or missing HMAC-SHA256 signature on inbound webhook
Reject payload with HTTP 401. Log the rejection including the source IP and truncated payload hash. Do not process the payload. Alert is not required for single occurrences; if 5+ rejections occur within 1 hour, post a Slack security alert.
ShipBob API (Agent 1)
SKU in ShipBob response not present in SHIPBOB_SKU_MAP
Exclude the unmapped SKU from the normalised dataset. Log a warning entry per unmapped SKU. Include unmapped SKU count in the Google Sheets log row. Post a Slack warning if unmapped SKU count exceeds 5 in a single run. Do not halt the run.
Cin7 API (Agent 2, read)
HTTP 401 or 403 on product inventory read
Halt Agent 2 immediately. Log error. Post Slack alert: 'Cin7 read authentication failed. Check CIN7_ACCOUNT_ID and CIN7_API_KEY. Reconciliation aborted.' Do not proceed to Agent 3.
Cin7 API (Agent 2, read)
HTTP 503 Service Unavailable or connection timeout
Retry with exponential backoff: 30s, 60s, 120s. Maximum 3 retries. If all retries fail, post Slack alert and abort. Log run as 'failed - upstream unavailable'. Operations coordinator receives alert and must perform manual reconciliation for that run.
Cin7 API (Agent 3, write)
HTTP 400 Bad Request on StockAdjustment POST
Log the full request payload and response body. Mark the affected SKU adjustment as 'failed'. Continue processing remaining SKUs. After all writes attempted, post Slack alert listing all failed SKU writes with their error responses. Do not retry 400 errors without investigating the payload.
Shopify API (Agent 3)
HTTP 429 Too Many Requests on inventory_levels/set.json
Read the Retry-After header from the Shopify response and pause for that duration before retrying. Retry up to 3 times per SKU. If retries exhausted for a specific SKU, log as 'failed' and continue with remaining SKUs. Include failed Shopify writes in the Slack daily summary.
Shopify API (Agent 3)
SKU not found in SHOPIFY_INVENTORY_MAP
Skip the Shopify write for that SKU. Log a warning with the SKU identifier. Do not halt the agent. Include unmapped Shopify SKU warnings in the Google Sheets log row and the daily Slack summary. Operations team must update SHOPIFY_INVENTORY_MAP before the next run.
Slack API (Agent 3)
HTTP 401 or invalid_auth on chat.postMessage
Log the Slack authentication failure to the platform run log. Attempt to send a fallback notification via email to the operations team email address (if configured as FALLBACK_EMAIL in config store). If no fallback is configured, log and complete the run. Slack failures must never prevent Cin7 and Shopify writes from completing.
Google Sheets API (Agent 2)
HTTP 403 on values.append (permission denied)
Log the error with the spreadsheet ID and service account email. Post Slack alert: 'Google Sheets log write failed. Check service account permissions on GOOGLE_SHEETS_LOG_ID.' The reconciliation run data must be retained in the platform run log as a fallback. Do not abort the agent; the Sheets write is non-blocking.
Any agent (all integrations)
Unhandled exception or unexpected runtime error
Catch all unhandled exceptions at the top-level agent error handler. Log full stack trace and error details to the platform run log with severity 'CRITICAL'. Post immediate Slack alert to SLACK_CHANNEL_FULFILMENT with run ID, agent name, and error summary. Mark the run as 'failed'. Operations coordinator must investigate before the next scheduled run. Unhandled exceptions must never fail silently.
Manual fallback protocol: if two or more consecutive scheduled runs fail across any critical integration (ShipBob read, Cin7 read, or Cin7 write), the operations coordinator must be notified via the Slack alert and must revert to the manual reconciliation procedure documented in the SOP (FS-DOC-03) until the integration fault is resolved. The FullSpec team is reachable at support@gofullspec.com for integration fault escalation.
Integration and API SpecPage 3 of 3

More documents for this process

Every document generated for 3PL / Warehouse Coordination.

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