Unclassified

Phase 3: Gateway API Contract

Tier C — Historical. This document is a point-in-time snapshot preserved for reference. For current architecture, see CANONICAL_PLATFORM_ARCHITECTURE.md.

The binding contract between all frontends and the IntegrateWise platform. Every HTTP request flows through this contract. No exceptions.

Core Principle

Every frontend calls Gateway. Gateway dispatches to platform services. Frontends never reach beyond Gateway.

Frontend
  ↓
Gateway SDK (in frontend)
  ↓
Gateway API (HTTP/gRPC)
  ↓
Platform Services (Spine, Memory, Entity360, Governance, Skills, etc.)

Authentication Flow

1. Stack Auth Token

User authenticates via Stack Auth (OAuth, email/password).

Stack Auth
  ↓
Access Token (JWT)
  ↓
Refresh Token (stored securely)

2. Gateway Authentication

Frontend sends Stack Auth token to Gateway.

POST /gateway/auth/validate
Authorization: Bearer <stack_auth_token>

Response:
{
  "user_id": "usr_123",
  "org_id": "org_456",
  "team_id": "team_789",
  "role": "admin",
  "permissions": ["read", "write", "delete"],
  "gateway_token": "<scoped_gateway_jwt>",
  "expires_at": 1719000000
}

Gateway returns a scoped gateway token (not reusable across orgs).

3. All Subsequent Requests

Frontend uses gateway token.

Authorization: Bearer <gateway_token>
X-Org-ID: org_456
X-Team-ID: team_789

Request/Response Envelope

Standard Request

{
  "namespace": "workspace",
  "action": "listEntities",
  "version": "v1",
  "params": {
    "type": "customer",
    "filters": { "status": "active" },
    "limit": 50,
    "offset": 0
  },
  "context": {
    "request_id": "req_abc123",
    "timestamp": 1719000000,
    "trace_id": "trace_xyz789"
  }
}

Standard Response

{
  "success": true,
  "data": {
    "entities": [
      {
        "id": "ent_123",
        "type": "customer",
        "fields": { "name": "Acme Inc", "status": "active" },
        "version": 1,
        "updated_at": 1719000000
      }
    ],
    "pagination": {
      "limit": 50,
      "offset": 0,
      "total": 1250,
      "has_more": true
    }
  },
  "context": {
    "request_id": "req_abc123",
    "processed_at": 1719000000,
    "latency_ms": 125
  }
}

Error Response

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "User does not have permission to read customer entities",
    "details": {
      "required_permission": "entity.customer.read",
      "user_role": "viewer"
    },
    "request_id": "req_abc123",
    "timestamp": 1719000000
  }
}

Error Format

All errors follow this structure:

CodeHTTPMeaning
INVALID_REQUEST400Malformed request
UNAUTHORIZED401Invalid or expired auth token
FORBIDDEN403Valid auth but insufficient permissions
NOT_FOUND404Resource does not exist
CONFLICT409Optimistic lock violation or constraint violation
RATE_LIMITED429Rate limit exceeded
INTERNAL_ERROR500Server error
SERVICE_UNAVAILABLE503Downstream service unavailable

Pagination

All list endpoints support:

GET /gateway/workspace/entities?type=customer&limit=50&offset=100

Response includes:
{
  "pagination": {
    "limit": 50,
    "offset": 100,
    "total": 1250,
    "has_more": true,
    "cursor": "cur_next_set_123"  // optional: use instead of offset for stability
  }
}

Streaming Responses

For long-running operations:

POST /gateway/workspace/search/stream
Content-Type: application/json

Request:
{
  "action": "searchEntities",
  "query": "customer name contains 'tech'",
  "limit": 1000
}

Response (Server-Sent Events):
event: progress
data: {"matched": 100, "total_estimate": 1250}

event: progress
data: {"matched": 500, "total_estimate": 1250}

event: result
data: {"id": "ent_123", "type": "customer", "name": "TechCorp Inc"}

event: result
data: {"id": "ent_124", "type": "customer", "name": "Tech Solutions Ltd"}

event: complete
data: {"total": 642, "duration_ms": 2341}

Realtime Events

Frontends subscribe to Spine changes via WebSocket:

WebSocket Connection:
wss://gateway.integratewise.com/realtime?token=<gateway_token>

Subscribe:
{
  "action": "subscribe",
  "namespaces": ["workspace", "memory"],
  "filters": {
    "workspace": { "org_id": "org_456", "type": "customer" },
    "memory": { "org_id": "org_456" }
  }
}

Events:
{
  "namespace": "workspace",
  "event": "entity.created",
  "entity_id": "ent_999",
  "type": "customer",
  "changes": { "name": "New Corp", "status": "pending" },
  "version": 1,
  "timestamp": 1719000000
}

{
  "namespace": "workspace",
  "event": "entity.updated",
  "entity_id": "ent_123",
  "type": "customer",
  "changes": { "status": "active" },
  "version": 5,
  "timestamp": 1719000100,
  "previous_version": 4
}

{
  "namespace": "memory",
  "event": "conversation.new",
  "conversation_id": "conv_456",
  "summary": "Customer renewal discussion",
  "participants": ["usr_123", "usr_456"],
  "timestamp": 1719000200
}

Versioning

API Version in Request

GET /gateway/v1/workspace/entities

vs.

GET /gateway/v2/workspace/entities

Capability Versioning

Each namespace can have independent versions:

{
  "versions": {
    "workspace": "v1",
    "memory": "v2",
    "twin": "v1",
    "approvals": "v3",
    "integrations": "v1"
  }
}

Frontends declare which versions they support at connection:

POST /gateway/auth/validate
{
  "stack_auth_token": "...",
  "supported_versions": {
    "workspace": ["v1", "v2"],
    "memory": ["v2"],
    "twin": ["v1"]
  }
}

Capability Namespaces

1. workspace

Core entity management (customers, deals, tickets, documents, etc.)

workspace.listEntities()
workspace.getEntity(id)
workspace.createEntity(data)
workspace.updateEntity(id, changes)
workspace.deleteEntity(id)
workspace.search(query)
workspace.bulkWrite(entities)

2. memory

Organizational knowledge and conversations.

memory.search(query)
memory.getConversation(id)
memory.listConversations(filters)
memory.createConversation(data)
memory.addMessage(conversation_id, message)
memory.getTimeline(entity_id)
memory.getRelationships(entity_id)

3. twin

AI reasoning and chat.

twin.createSession(context)
twin.sendMessage(session_id, message)
twin.getResponse(session_id)
twin.streamResponse(session_id)
twin.explainEntity(entity_id)
twin.draftAction(action_type, entity_id)
twin.executeAction(action_id)

4. approvals

Human governance.

approvals.getPendingReviews(user_id)
approvals.submitForReview(action_id, reviewers)
approvals.approve(action_id, comment)
approvals.reject(action_id, comment)
approvals.getAuditTrail(action_id)
approvals.getPolicies(org_id)

5. integrations

External system connections.

integrations.listConnected(org_id)
integrations.getConnectionStatus(integration_id)
integrations.authorize(provider)
integrations.revoke(integration_id)
integrations.sync(integration_id)
integrations.getAvailable()
integrations.getCapabilities(provider)

6. skills

Platform capabilities and automations.

skills.listAvailable(org_id)
skills.execute(skill_id, params)
skills.schedule(skill_id, params, cron_expression)
skills.getExecutionHistory(skill_id)
skills.create(definition)  // org-specific automation
skills.update(skill_id, definition)

7. entity360

Unified entity view.

entity360.get(entity_id)  // full view: fields, relationships, history, governance, memory
entity360.getRelated(entity_id)
entity360.getTimeline(entity_id, limit)
entity360.getGovernance(entity_id)  // approval status, policies, actions pending

8. identity

User and team management.

identity.getCurrentUser()
identity.getTeam(team_id)
identity.listTeamMembers(team_id)
identity.getOrganization(org_id)
identity.getPermissions(user_id)
identity.getRoles(org_id)
identity.getRoleDefinition(role_name)

Rate Limiting

X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9250
X-RateLimit-Reset: 1719003600

429 Too Many Requests
Retry-After: 60

Monitoring & Observability

Every request includes:

X-Request-ID: req_abc123
X-Trace-ID: trace_xyz789
X-Span-ID: span_def456
X-User-ID: usr_123
X-Org-ID: org_456
X-Team-ID: team_789

Response includes:

X-Process-Time: 125ms
X-Cache-Hit: false
X-Latency-Breakdown: gateway=10ms,spine=50ms,entity360=65ms

Security Headers

All responses include:

Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'

Backward Compatibility

  • Old API versions remain supported for 12 months
  • Deprecation notices sent in headers 6 months before removal
  • Migration guides published when versions are deprecated
  • Gateway maintains adapter layer for old versions

Testing & Development

Mock Gateway (for offline frontend development)


const gateway = createMockGateway({
  fixtures: 'fixtures/production-like-data.json'
})

// Behaves like real Gateway but uses local data

Gateway Sandbox (for integration testing)

POST https://sandbox-gateway.integratewise.com/...

Uses in-memory Spine and Memory. Resets on new test.

Summary

This contract defines:

  • ✅ How frontends authenticate
  • ✅ How they request data
  • ✅ How they receive responses
  • ✅ How they handle errors
  • ✅ How they stream and subscribe to realtime events
  • ✅ What capabilities are available
  • ✅ How to version APIs
  • ✅ Security and observability requirements

Every frontend (AI Workspace, Wise Docs, Wise Ops, etc.) follows this contract exactly. No variations, no shortcuts.