Documentation Index
Fetch the complete documentation index at: https://docs.deep.space/llms.txt
Use this file to discover all available pages before exploring further.
The integration object fronts 215+ third-party API endpoints through the platform’s signed proxy. For discovery, billing, and the full workflow see the external APIs guide; for the CLI catalog, see deepspace integrations.
import { integration } from 'deepspace'
import type { IntegrationResponse, RequestOptions } from 'deepspace'
integration
The integration client exposes four HTTP verbs. All return a typed envelope.
const integration: {
get<T>: (endpoint: string, params?: Record<string, string | number | boolean | null | undefined>, options?: RequestOptions) => Promise<IntegrationResponse<T>>
post<T>: (endpoint: string, data?: unknown, options?: RequestOptions) => Promise<IntegrationResponse<T>>
put<T>: (endpoint: string, data?: unknown, options?: RequestOptions) => Promise<IntegrationResponse<T>>
delete<T>: (endpoint: string, data?: unknown, options?: RequestOptions) => Promise<IntegrationResponse<T>>
}
get takes a query-parameter object as its middle argument; the others take an optional JSON body. delete also accepts a body - the api-worker dispatches DELETE with a JSON payload when one is provided.
Endpoint names are two segments: <integration>/<endpoint> (e.g. openai/chat-completion).
The most common verb. Use for actions, completions, lookups, and anything with a request body.const result = await integration.post('openai/chat-completion', {
model: 'claude-sonnet-4-6',
messages: [{ role: 'user', content: 'Hello' }],
})
if (result.success) {
console.log(result.data)
} else {
console.error(result.error, result.issues)
}
For idempotent reads. Pass query parameters as the second argument - they’re serialised onto the URL automatically (null/undefined values are skipped).const result = await integration.get('finnhub/market-news', {
category: 'crypto',
minId: 100,
})
For idempotent updates against REST-style endpoints.const result = await integration.put('notion/update-page', {
pageId: 'abc123',
properties: { Status: 'Done' },
})
For destructive operations. The platform proxy is signed and rate-limited per integration; OAuth scopes apply if the integration is OAuth-backed.const result = await integration.delete('notion/delete-block', {
blockId: 'xyz789',
})
Auth-gate any UI that calls integration.post(...) for 'developer'-billed endpoints. The api-worker accepts anonymous callers, so a public endpoint silently bills the owner for every visitor (or bot) hit. Wrap calling components in useAuth().isSignedIn. See the external APIs guide for billing routing.
IntegrationResponse<T>
type IntegrationResponse<T> =
| { success: true; data: T }
| { success: false; error: string; issues?: ValidationIssue[] }
type ValidationIssue = {
path?: string[]
message: string
code?: string
}
issues appears when the api-worker’s Zod validator rejects the body shape. Read it instead of guessing field names - or run deepspace integrations info <endpoint> to print the schema before you call.
RequestOptions
type RequestOptions = {
headers?: Record<string, string>
timeoutMs?: number // default 120000 (120s)
}
const r = await integration.post('exa/search', body, {
timeoutMs: 30_000,
headers: { 'X-Custom': 'value' },
})
Cross-app platform context
These exports support a small set of cross-app surfaces (inbox, platform fetch). The scaffold does not include <PlatformProvider> - wrap manually if you need this surface.
import { PlatformProvider, usePlatform, useInbox, usePlatformWS } from 'deepspace'
<PlatformProvider>{/* tree */}</PlatformProvider>
function usePlatform(): {
platformFetch: (path: string, init?: RequestInit) => Promise<Response>
inbox: InboxEntry[]
/** Activate the inbox WebSocket. Returns an unsubscribe function. */
subscribeInbox: () => () => void
}
platformFetch prepends /platform and adds the auth header automatically. Throws if no <PlatformProvider> is mounted. subscribeInbox is the primitive useInbox() calls under the hood - apps rarely call it directly.
useInbox()
function useInbox(): InboxEntry[]
type InboxEntry = {
conversationId: string
scope: { type: string; participants?: string[]; appId?: string; contentRef?: string; ticketNumber?: string }
displayName: string
muted: boolean
joinedAt: string
lastMessageAt: string | null
lastMessagePreview: string | null
lastMessageAuthor: string | null
unreadCount: number
}
The inbox WebSocket activates only when at least one component subscribes via useInbox().
Generic platform WebSocket subscription for custom platform-side streams. S is the state shape; the constraint requires a status: ConnectionStatus field so the hook can drive reconnect UI.
function usePlatformWS<S extends { status: ConnectionStatus }>(
options: PlatformWSOptions<S>,
): PlatformWSResult<S>
type PlatformWSOptions<S> = {
/** DO path segment - e.g. 'orders' for /platform/ws/orders/{scopeId} */
path: string
/** Scope ID - e.g. 'app:demo-corp'. Pass undefined to skip the connection. */
scopeId: string | undefined
initialState: S
onMessage: (msg: Record<string, unknown>, prev: S) => S
}
type PlatformWSResult<S> = {
state: S
send: (msg: Record<string, unknown>) => void
}
OAuth endpoints
For OAuth-backed integrations (currently Google), these REST endpoints manage per-user connections. Call via fetch with the session token.
| Endpoint | Method | Purpose |
|---|
/api/integrations/status | GET | Returns connection flags for all OAuth providers |
/api/integrations/oauth/:provider/connect | GET | Initiates OAuth flow (browser navigation) |
/api/integrations/oauth/:provider/disconnect | DELETE | Revokes the current user’s stored tokens |
const r = await fetch('/api/integrations/status', {
headers: { Authorization: `Bearer ${await getAuthToken()}` },
})
const { google } = await r.json()
// { connected: boolean, scopes: string[] }
requiresOAuth response
When a user calls an OAuth endpoint without a connected account:
{ success: false, error: 'requiresOAuth', provider: 'google', connectUrl: '...' }
Redirect the user to connectUrl (or call /api/integrations/oauth/google/connect directly), then retry the original call.
See also