Every /connect/* route returns errors in a consistent JSON envelope. Gather (/qsi/gather/*) and legacy vendor routes (/qsi/{vendor}/*) keep their existing shapes.
Envelope shape
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable summary"
},
"meta": {
"requestId": "trace-abc or req_<uuid>",
"timestamp": "2026-06-17T12:00:00.000Z"
}
}
details is omitted when empty (not null, not {}).
requestId is in meta for Gather compatibility.
Authentication and authorization
| Code | HTTP | When |
|---|
UNAUTHORIZED | 401 | Missing/invalid API key or organization context |
FORBIDDEN | 403 | Valid key, wrong scope or access denied |
Validation
| Code | HTTP | When |
|---|
VALIDATION_ERROR | 400 | Invalid body, config, or unresolved teamId |
details contains field-level keys (e.g. { "apiKey": "apiKey is required" }).
Integration lifecycle
| Code | HTTP | When |
|---|
INTEGRATION_NOT_FOUND | 404 | No active integration for org + team + vendor |
INTEGRATION_EXISTS | 409 | Duplicate on POST /connect/{vendor}/integrations |
HEALTH_PROBE_FAILED | 502 | Unexpected probe error (not auth/timeout simulation) |
Health checks: General unhealthy vendor state may return 502/504 with data.healthy: false in a success envelope. Credential rejection (MS6+) returns 502 with error code VENDOR_AUTH_FAILED instead.
Vendor passthrough
Mapped from outbound vendor HTTP failures:
| Code | HTTP | Vendor situation |
|---|
VENDOR_AUTH_FAILED | 502 | Vendor 401/403 or stored credential rejected |
VENDOR_RATE_LIMITED | 429 | Vendor 429 |
VENDOR_UNAVAILABLE | 502 | Vendor 5xx |
VENDOR_TIMEOUT | 504 | Timeout / ECONNABORTED |
VENDOR_BAD_REQUEST | 400 | Other vendor 4xx |
details may include vendorStatus, vendorStatusLabel, or vendorMessage (never raw vendor secrets).
Internal and order errors
| Code | HTTP | When |
|---|
INTERNAL_ERROR | 500 | Unhandled exception or internal-router 5xx |
NOT_FOUND | 404 | Internal-router resource missing |
CONFLICT | 409 | Account provisioning name conflict |
ORDER_FAILED | 400 | Order path: no invite token generated |
Gather errors
Gather uses the same error + meta shape on /qsi/gather/* but with Gather-specific codes. See Gather error handling.