POST /v1/contents

Retrieve complete content for documents and observations by ID. Use this after search to fetch full content for results.

Endpoint

POST https://lightfast.ai/api/v1/contents

Authentication

See Authentication for details.

bash
Authorization: Bearer YOUR_API_KEY
X-Workspace-ID: ws_abc123

Request Body

typescript
{
  ids: string[]  // Array of content IDs (1-50 IDs per request)
}

Content IDs use prefixes like doc_* or obs_* and are returned from the search endpoint.

Response

typescript
{
  items: Array<{
    id: string               // Content ID
    title: string | null     // Content title (may be null)
    url: string              // Link to source
    snippet: string          // Content snippet
    content?: string         // Full content (observations only)
    source: string           // Source system (github, linear, etc.)
    type: string             // Content type (pull_request, issue, etc.)
    occurredAt?: string      // When content was created (ISO 8601)
    metadata?: Record<string, unknown>  // Additional metadata
  }>
  missing: string[]          // IDs that were not found
  requestId: string          // Request ID for debugging
}

Example Request

bash
curl -X POST https://lightfast.ai/api/v1/contents \
  -H "Authorization: Bearer $LIGHTFAST_API_KEY" \
  -H "X-Workspace-ID: $LIGHTFAST_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["obs_abc123", "obs_def456"]
  }'

Example Response

json
{
  "items": [
    {
      "id": "obs_abc123",
      "title": "Implement OAuth 2.0 authentication",
      "url": "https://github.com/org/repo/pull/123",
      "snippet": "Added OAuth 2.0 authentication flow with refresh tokens...",
      "content": "## Summary\n\nThis PR implements OAuth 2.0 authentication flow with the following features:\n\n- Authorization code flow\n- Refresh token rotation\n- JWT validation\n- PKCE support\n\n## Implementation Details\n\n...",
      "source": "github",
      "type": "pull_request",
      "occurredAt": "2024-03-15T10:30:00Z",
      "metadata": {
        "repository": "org/repo",
        "state": "merged",
        "labels": ["security", "authentication"]
      }
    },
    {
      "id": "obs_def456",
      "title": "Security: Review authentication flow",
      "url": "https://github.com/org/repo/issues/456",
      "snippet": "We should review the current authentication implementation...",
      "source": "github",
      "type": "issue",
      "occurredAt": "2024-02-20T09:15:00Z"
    }
  ],
  "missing": [],
  "requestId": "req_abc123def456"
}

Handling Missing IDs

If some IDs are not found, they appear in the missing array:

json
{
  "items": [
    {
      "id": "obs_abc123",
      "title": "Found document",
      "url": "https://github.com/org/repo/pull/123",
      "snippet": "...",
      "source": "github",
      "type": "pull_request"
    }
  ],
  "missing": ["obs_invalid", "obs_deleted"],
  "requestId": "req_xyz789"
}
typescript
const response = await fetch('https://lightfast.ai/api/v1/contents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'X-Workspace-ID': workspaceId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ ids: ['obs_abc123', 'obs_invalid'] })
})

const data = await response.json()

// Handle found items
data.items.forEach(item => {
  console.log('Found:', item.title)
})

// Handle missing IDs
if (data.missing.length > 0) {
  console.warn('Not found:', data.missing.join(', '))
}

Use Cases

typescript
// 1. Search for relevant content
const searchResponse = await fetch('https://lightfast.ai/api/v1/search', {
  method: 'POST',
  headers: { /* ... */ },
  body: JSON.stringify({ query: 'authentication implementation' })
})
const searchData = await searchResponse.json()

// 2. Get full content for top results
const contentResponse = await fetch('https://lightfast.ai/api/v1/contents', {
  method: 'POST',
  headers: { /* ... */ },
  body: JSON.stringify({
    ids: searchData.data.slice(0, 5).map(r => r.id)
  })
})
const contentData = await contentResponse.json()

// 3. Display full content
contentData.items.forEach(item => {
  console.log('Title:', item.title)
  console.log('Content:', item.content || item.snippet)
  console.log('---')
})

Build a Document Viewer

typescript
async function getDocument(id: string) {
  const response = await fetch('https://lightfast.ai/api/v1/contents', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.LIGHTFAST_API_KEY}`,
      'X-Workspace-ID': process.env.LIGHTFAST_WORKSPACE_ID!,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ ids: [id] })
  })

  const data = await response.json()

  if (data.missing.includes(id)) {
    throw new Error('Document not found')
  }

  return data.items[0]
}

// Usage
const doc = await getDocument('obs_abc123')
console.log(doc.title)
console.log(doc.content)

Batch Retrieval

Retrieve multiple documents efficiently in a single request (max 50 IDs):

typescript
// Efficient: Single batch request
const response = await fetch('https://lightfast.ai/api/v1/contents', {
  method: 'POST',
  headers: { /* ... */ },
  body: JSON.stringify({
    ids: ['obs_1', 'obs_2', 'obs_3', 'obs_4', 'obs_5']
  })
})

// Less efficient: Multiple individual requests
for (const id of ids) {
  await fetch('https://lightfast.ai/api/v1/contents', {
    body: JSON.stringify({ ids: [id] })
  })
}

Limit: Maximum 50 IDs per request. For more IDs, make multiple requests.

Error Handling

typescript
const response = await fetch('https://lightfast.ai/api/v1/contents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'X-Workspace-ID': workspaceId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ ids })
})

if (!response.ok) {
  const error = await response.json()
  console.error('Request failed:', error.error, error.message)
  return
}

const data = await response.json()

// Partial success - some IDs found, some missing
if (data.missing.length > 0) {
  console.warn(`${data.missing.length} IDs not found`)
}

See Error Reference for all error codes.

Next Steps