Every Connect vendor namespace (/connect/{vendor}/*) implements these three meta-routes before vendor-specific data routes (orders, catalog, results).
Auth: Customer API key with integrations scope. Partner master keys (accounts scope) are rejected with 403.
Platform liveness (not vendor-specific): GET /connect/health — no auth.
Every vendor namespace implements these three meta-routes:
| Route | Auth | Purpose |
|---|
POST /connect/{vendor}/integrations | integrations | Save vendor credentials for this customer |
GET /connect/{vendor}/health | integrations | Live probe of this customer’s stored credentials |
DELETE /connect/{vendor}/integrations | integrations | Disconnect and archive the integration |
Do not conflate platform health (GET /connect/health) with vendor health.
POST /connect/{vendor}/integrations
Save vendor credentials for the authenticated customer’s org + team.
Vendor-specific configuration. Must include a vendor discriminator where applicable (e.g. StubVendor).
Team scope comes from the API credential, not the request body.
Success — 201 Created
{
"data": {
"integrationId": "uuid",
"type": "StubVendor",
"healthy": true
},
"meta": {
"requestId": "req_...",
"timestamp": "2026-06-17T12:00:00.000Z"
}
}
After save, Connect runs the vendor health probe with the request config. healthy reflects the probe at save time. Probe failures on POST do not return 502 — use GET /health for strict HTTP status semantics.
Errors
| HTTP | Code | When |
|---|
| 400 | VALIDATION_ERROR | Missing/invalid config |
| 401 | UNAUTHORIZED | Missing/invalid API key |
| 403 | FORBIDDEN | Wrong scope (e.g. accounts only) |
| 409 | INTEGRATION_EXISTS | Active integration already exists |
| 500 | INTERNAL_ERROR | Unexpected failure |
curl -s -X POST "https://connect.humanly.io/connect/stub/integrations" \
-H 'Content-Type: application/json' \
-H "x-api-key: $CUSTOMER_KEY" \
-d '{
"config": {
"apiKey": "stub-test-vendor-key"
}
}'
GET /connect/{vendor}/health
Live connectivity check using stored credentials.
Healthy — 200 OK
{
"data": {
"healthy": true,
"vendorStatus": "ok",
"lastCheckedAt": "2026-06-17T12:00:00.000Z"
},
"meta": { "requestId": "...", "timestamp": "..." }
}
lastCheckedAt is the timestamp of this probe (not cached).
Unhealthy vendor state
When the vendor is reachable but reports unhealthy (timeout, rejected credentials, etc.), responses may use 502 or 504 with data.healthy: false in the success envelope, or a standardized error envelope for credential rejection:
| Situation | HTTP | Shape |
|---|
| General unhealthy probe | 502 / 504 | data.healthy: false, vendorStatus |
| Credential rejected (MS6+) | 502 | Error envelope VENDOR_AUTH_FAILED |
See Error envelope for VENDOR_* codes.
Errors
| HTTP | Code | When |
|---|
| 404 | INTEGRATION_NOT_FOUND | No active integration for org + team + type |
| 401 / 403 | UNAUTHORIZED / FORBIDDEN | Auth failures |
DELETE /connect/{vendor}/integrations
Disconnect — removes the integration row.
Success — 200 OK
{
"data": {
"archived": true,
"archivedAt": "2026-06-17T12:00:00.000Z"
},
"meta": { "requestId": "...", "timestamp": "..." }
}
archived: true is the partner-facing disconnect signal.
Errors
| HTTP | Code | When |
|---|
| 404 | INTEGRATION_NOT_FOUND | No integration to delete |
| 401 / 403 | UNAUTHORIZED / FORBIDDEN | Auth failures |
Stub vendor (non-production)
The stub vendor is available only when NODE_ENV is development, test, or staging. Use it for smoke tests — see Getting started.