{"slug":"developers/PHASE_3_GATEWAY_API_CONTRACT","title":"Phase 3: Gateway API Contract","section":"developers","sectionLabel":"Developers","status":"unclassified","type":"document","path":"developers/PHASE_3_GATEWAY_API_CONTRACT.mdx","bytes":10038,"description":null,"updated":null,"source":"integratewise/Integratewise-docs-wiki","content":"\n\n> **Tier C — Historical.** This document is a point-in-time snapshot preserved for reference. For current architecture, see [CANONICAL_PLATFORM_ARCHITECTURE.md](../architecture/CANONICAL_PLATFORM_ARCHITECTURE.md).\n\nThe binding contract between all frontends and the IntegrateWise platform. Every HTTP request flows through this contract. No exceptions.\n\n## Core Principle\n\n**Every frontend calls Gateway. Gateway dispatches to platform services. Frontends never reach beyond Gateway.**\n\n```\nFrontend\n  ↓\nGateway SDK (in frontend)\n  ↓\nGateway API (HTTP/gRPC)\n  ↓\nPlatform Services (Spine, Memory, Entity360, Governance, Skills, etc.)\n```\n\n---\n\n## Authentication Flow\n\n### 1. Stack Auth Token\nUser authenticates via Stack Auth (OAuth, email/password).\n\n```\nStack Auth\n  ↓\nAccess Token (JWT)\n  ↓\nRefresh Token (stored securely)\n```\n\n### 2. Gateway Authentication\nFrontend sends Stack Auth token to Gateway.\n\n```\nPOST /gateway/auth/validate\nAuthorization: Bearer <stack_auth_token>\n\nResponse:\n{\n  \"user_id\": \"usr_123\",\n  \"org_id\": \"org_456\",\n  \"team_id\": \"team_789\",\n  \"role\": \"admin\",\n  \"permissions\": [\"read\", \"write\", \"delete\"],\n  \"gateway_token\": \"<scoped_gateway_jwt>\",\n  \"expires_at\": 1719000000\n}\n```\n\nGateway returns a scoped gateway token (not reusable across orgs).\n\n### 3. All Subsequent Requests\nFrontend uses gateway token.\n\n```\nAuthorization: Bearer <gateway_token>\nX-Org-ID: org_456\nX-Team-ID: team_789\n```\n\n---\n\n## Request/Response Envelope\n\n### Standard Request\n\n```json\n{\n  \"namespace\": \"workspace\",\n  \"action\": \"listEntities\",\n  \"version\": \"v1\",\n  \"params\": {\n    \"type\": \"customer\",\n    \"filters\": { \"status\": \"active\" },\n    \"limit\": 50,\n    \"offset\": 0\n  },\n  \"context\": {\n    \"request_id\": \"req_abc123\",\n    \"timestamp\": 1719000000,\n    \"trace_id\": \"trace_xyz789\"\n  }\n}\n```\n\n### Standard Response\n\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"entities\": [\n      {\n        \"id\": \"ent_123\",\n        \"type\": \"customer\",\n        \"fields\": { \"name\": \"Acme Inc\", \"status\": \"active\" },\n        \"version\": 1,\n        \"updated_at\": 1719000000\n      }\n    ],\n    \"pagination\": {\n      \"limit\": 50,\n      \"offset\": 0,\n      \"total\": 1250,\n      \"has_more\": true\n    }\n  },\n  \"context\": {\n    \"request_id\": \"req_abc123\",\n    \"processed_at\": 1719000000,\n    \"latency_ms\": 125\n  }\n}\n```\n\n### Error Response\n\n```json\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"UNAUTHORIZED\",\n    \"message\": \"User does not have permission to read customer entities\",\n    \"details\": {\n      \"required_permission\": \"entity.customer.read\",\n      \"user_role\": \"viewer\"\n    },\n    \"request_id\": \"req_abc123\",\n    \"timestamp\": 1719000000\n  }\n}\n```\n\n---\n\n## Error Format\n\nAll errors follow this structure:\n\n| Code | HTTP | Meaning |\n|------|------|---------|\n| `INVALID_REQUEST` | 400 | Malformed request |\n| `UNAUTHORIZED` | 401 | Invalid or expired auth token |\n| `FORBIDDEN` | 403 | Valid auth but insufficient permissions |\n| `NOT_FOUND` | 404 | Resource does not exist |\n| `CONFLICT` | 409 | Optimistic lock violation or constraint violation |\n| `RATE_LIMITED` | 429 | Rate limit exceeded |\n| `INTERNAL_ERROR` | 500 | Server error |\n| `SERVICE_UNAVAILABLE` | 503 | Downstream service unavailable |\n\n---\n\n## Pagination\n\nAll list endpoints support:\n\n```\nGET /gateway/workspace/entities?type=customer&limit=50&offset=100\n\nResponse includes:\n{\n  \"pagination\": {\n    \"limit\": 50,\n    \"offset\": 100,\n    \"total\": 1250,\n    \"has_more\": true,\n    \"cursor\": \"cur_next_set_123\"  // optional: use instead of offset for stability\n  }\n}\n```\n\n---\n\n## Streaming Responses\n\nFor long-running operations:\n\n```\nPOST /gateway/workspace/search/stream\nContent-Type: application/json\n\nRequest:\n{\n  \"action\": \"searchEntities\",\n  \"query\": \"customer name contains 'tech'\",\n  \"limit\": 1000\n}\n\nResponse (Server-Sent Events):\nevent: progress\ndata: {\"matched\": 100, \"total_estimate\": 1250}\n\nevent: progress\ndata: {\"matched\": 500, \"total_estimate\": 1250}\n\nevent: result\ndata: {\"id\": \"ent_123\", \"type\": \"customer\", \"name\": \"TechCorp Inc\"}\n\nevent: result\ndata: {\"id\": \"ent_124\", \"type\": \"customer\", \"name\": \"Tech Solutions Ltd\"}\n\nevent: complete\ndata: {\"total\": 642, \"duration_ms\": 2341}\n```\n\n---\n\n## Realtime Events\n\nFrontends subscribe to Spine changes via WebSocket:\n\n```\nWebSocket Connection:\nwss://gateway.integratewise.com/realtime?token=<gateway_token>\n\nSubscribe:\n{\n  \"action\": \"subscribe\",\n  \"namespaces\": [\"workspace\", \"memory\"],\n  \"filters\": {\n    \"workspace\": { \"org_id\": \"org_456\", \"type\": \"customer\" },\n    \"memory\": { \"org_id\": \"org_456\" }\n  }\n}\n\nEvents:\n{\n  \"namespace\": \"workspace\",\n  \"event\": \"entity.created\",\n  \"entity_id\": \"ent_999\",\n  \"type\": \"customer\",\n  \"changes\": { \"name\": \"New Corp\", \"status\": \"pending\" },\n  \"version\": 1,\n  \"timestamp\": 1719000000\n}\n\n{\n  \"namespace\": \"workspace\",\n  \"event\": \"entity.updated\",\n  \"entity_id\": \"ent_123\",\n  \"type\": \"customer\",\n  \"changes\": { \"status\": \"active\" },\n  \"version\": 5,\n  \"timestamp\": 1719000100,\n  \"previous_version\": 4\n}\n\n{\n  \"namespace\": \"memory\",\n  \"event\": \"conversation.new\",\n  \"conversation_id\": \"conv_456\",\n  \"summary\": \"Customer renewal discussion\",\n  \"participants\": [\"usr_123\", \"usr_456\"],\n  \"timestamp\": 1719000200\n}\n```\n\n---\n\n## Versioning\n\n### API Version in Request\n\n```\nGET /gateway/v1/workspace/entities\n```\n\nvs.\n\n```\nGET /gateway/v2/workspace/entities\n```\n\n### Capability Versioning\n\nEach namespace can have independent versions:\n\n```\n{\n  \"versions\": {\n    \"workspace\": \"v1\",\n    \"memory\": \"v2\",\n    \"twin\": \"v1\",\n    \"approvals\": \"v3\",\n    \"integrations\": \"v1\"\n  }\n}\n```\n\nFrontends declare which versions they support at connection:\n\n```\nPOST /gateway/auth/validate\n{\n  \"stack_auth_token\": \"...\",\n  \"supported_versions\": {\n    \"workspace\": [\"v1\", \"v2\"],\n    \"memory\": [\"v2\"],\n    \"twin\": [\"v1\"]\n  }\n}\n```\n\n---\n\n## Capability Namespaces\n\n### 1. `workspace`\nCore entity management (customers, deals, tickets, documents, etc.)\n\n```\nworkspace.listEntities()\nworkspace.getEntity(id)\nworkspace.createEntity(data)\nworkspace.updateEntity(id, changes)\nworkspace.deleteEntity(id)\nworkspace.search(query)\nworkspace.bulkWrite(entities)\n```\n\n### 2. `memory`\nOrganizational knowledge and conversations.\n\n```\nmemory.search(query)\nmemory.getConversation(id)\nmemory.listConversations(filters)\nmemory.createConversation(data)\nmemory.addMessage(conversation_id, message)\nmemory.getTimeline(entity_id)\nmemory.getRelationships(entity_id)\n```\n\n### 3. `twin`\nAI reasoning and chat.\n\n```\ntwin.createSession(context)\ntwin.sendMessage(session_id, message)\ntwin.getResponse(session_id)\ntwin.streamResponse(session_id)\ntwin.explainEntity(entity_id)\ntwin.draftAction(action_type, entity_id)\ntwin.executeAction(action_id)\n```\n\n### 4. `approvals`\nHuman governance.\n\n```\napprovals.getPendingReviews(user_id)\napprovals.submitForReview(action_id, reviewers)\napprovals.approve(action_id, comment)\napprovals.reject(action_id, comment)\napprovals.getAuditTrail(action_id)\napprovals.getPolicies(org_id)\n```\n\n### 5. `integrations`\nExternal system connections.\n\n```\nintegrations.listConnected(org_id)\nintegrations.getConnectionStatus(integration_id)\nintegrations.authorize(provider)\nintegrations.revoke(integration_id)\nintegrations.sync(integration_id)\nintegrations.getAvailable()\nintegrations.getCapabilities(provider)\n```\n\n### 6. `skills`\nPlatform capabilities and automations.\n\n```\nskills.listAvailable(org_id)\nskills.execute(skill_id, params)\nskills.schedule(skill_id, params, cron_expression)\nskills.getExecutionHistory(skill_id)\nskills.create(definition)  // org-specific automation\nskills.update(skill_id, definition)\n```\n\n### 7. `entity360`\nUnified entity view.\n\n```\nentity360.get(entity_id)  // full view: fields, relationships, history, governance, memory\nentity360.getRelated(entity_id)\nentity360.getTimeline(entity_id, limit)\nentity360.getGovernance(entity_id)  // approval status, policies, actions pending\n```\n\n### 8. `identity`\nUser and team management.\n\n```\nidentity.getCurrentUser()\nidentity.getTeam(team_id)\nidentity.listTeamMembers(team_id)\nidentity.getOrganization(org_id)\nidentity.getPermissions(user_id)\nidentity.getRoles(org_id)\nidentity.getRoleDefinition(role_name)\n```\n\n---\n\n## Rate Limiting\n\n```\nX-RateLimit-Limit: 10000\nX-RateLimit-Remaining: 9250\nX-RateLimit-Reset: 1719003600\n\n429 Too Many Requests\nRetry-After: 60\n```\n\n---\n\n## Monitoring & Observability\n\nEvery request includes:\n\n```\nX-Request-ID: req_abc123\nX-Trace-ID: trace_xyz789\nX-Span-ID: span_def456\nX-User-ID: usr_123\nX-Org-ID: org_456\nX-Team-ID: team_789\n```\n\nResponse includes:\n\n```\nX-Process-Time: 125ms\nX-Cache-Hit: false\nX-Latency-Breakdown: gateway=10ms,spine=50ms,entity360=65ms\n```\n\n---\n\n## Security Headers\n\nAll responses include:\n\n```\nStrict-Transport-Security: max-age=31536000; includeSubDomains\nX-Content-Type-Options: nosniff\nX-Frame-Options: DENY\nX-XSS-Protection: 1; mode=block\nContent-Security-Policy: default-src 'self'\n```\n\n---\n\n## Backward Compatibility\n\n- Old API versions remain supported for 12 months\n- Deprecation notices sent in headers 6 months before removal\n- Migration guides published when versions are deprecated\n- Gateway maintains adapter layer for old versions\n\n---\n\n## Testing & Development\n\n### Mock Gateway (for offline frontend development)\n\n```\n\nconst gateway = createMockGateway({\n  fixtures: 'fixtures/production-like-data.json'\n})\n\n// Behaves like real Gateway but uses local data\n```\n\n### Gateway Sandbox (for integration testing)\n\n```\nPOST https://sandbox-gateway.integratewise.com/...\n\nUses in-memory Spine and Memory. Resets on new test.\n```\n\n---\n\n## Summary\n\nThis contract defines:\n- ✅ How frontends authenticate\n- ✅ How they request data\n- ✅ How they receive responses\n- ✅ How they handle errors\n- ✅ How they stream and subscribe to realtime events\n- ✅ What capabilities are available\n- ✅ How to version APIs\n- ✅ Security and observability requirements\n\nEvery frontend (AI Workspace, Wise Docs, Wise Ops, etc.) follows this contract exactly. No variations, no shortcuts.\n"}