Documentation

Documentation

Learn how to integrate ShinRAG into your applications using the REST API or our official TypeScript SDK.

Quick Start

ShinRAG provides two ways to interact with your pipelines, agents, and indexes:

  • REST API: Direct HTTP requests for any programming language
  • SDK: Official TypeScript/JavaScript SDK with full type safety

1. Get Your API Key

Your API key starts with sk_ and is required for all requests.

Get your API key from the dashboard →

2. Find Your Resource IDs

Each pipeline, agent, and index has a unique ID. You can easily copy these IDs using the Copy ID button:

Pipeline ID:

Go to Pipelines, open any pipeline, and click the Copy ID button next to the pipeline name

Agent ID:

Go to Agents, open any agent, and click the Copy ID button next to the agent name

Index ID:

Go to Indexes, open any index, and click the Copy ID button next to the index name

3. Install the SDK (Optional)

For TypeScript/JavaScript projects, install our official SDK:

npm:

npm install @shinrag/sdk

pnpm:

pnpm add @shinrag/sdk

Authentication

All API requests require authentication using an API key. Your API key starts with sk_.

You can authenticate in two ways:

Option 1: X-API-Key Header (Recommended)

X-API-Key: sk_your_api_key_here

Option 2: Authorization Header

Authorization: Bearer sk_your_api_key_here

Organization Scoping

Resources in ShinRAG belong to an organization. To access org-scoped agents, pipelines, indexes, and other resources, include your organization ID in requests.

import { ShinRAGClient } from '@shinrag/sdk';

// Organization-scoped client
const client = new ShinRAGClient({
  apiKey: 'sk_your_api_key_here',
  organizationId: 'org_123'  // Access org resources
});

// Personal workspace client (no org ID needed)
const personalClient = new ShinRAGClient({
  apiKey: 'sk_your_api_key_here'
});

Agents

Agents are RAG-powered assistants that retrieve relevant context from assigned indexes and generate answers using LLMs.

Query an Agent

const result = await client.queryAgent('agent_id', {
  question: 'What are the key features?',
  maxResults: 5,       // Max results from indexes (default: 10)
  temperature: 0.7,    // LLM temperature 0.0-2.0 (default: 0.7)
  maxTokens: 1000      // Max tokens for generation
});

console.log(result.answer);
console.log('Sources:', result.sources);
console.log('Tokens used:', result.tokensUsed);
console.log('Model:', result.model);

Response Type

interface QueryAgentResponse {
  answer: string | null;
  sources: Array<{
    dataset?: string;
    index?: string;
    score: number;
    text: string;
  }>;
  tokensUsed: number;
  model: string;
  warning?: string;
  diagnostic?: {
    totalResultsFound: number;
    threshold: number | null;
    topScores: number[];
  };
}

Manage Agents

// List all agents
const agents = await client.listAgents();

// Get a specific agent
const agent = await client.getAgent('agent_id');

// Create an agent
const newAgent = await client.createAgent({
  name: 'Support Bot',
  description: 'Answers customer questions',
  provider: 'openai',
  model: 'gpt-4o',
  indexIds: ['index_id_1', 'index_id_2'],
  usePlatformKey: true
});

// Update an agent
const updated = await client.updateAgent('agent_id', {
  name: 'Updated Bot',
  instructions: 'Be concise and helpful'
});

// Delete an agent
await client.deleteAgent('agent_id');

Pipelines

Pipelines are visual workflows that chain together agents, synthesis nodes, conditionals, and integrations.

Execute a Pipeline

// Execute a pipeline
const result = await client.executePipeline('pipeline_id', {
  input: 'What are the key features mentioned in the documentation?'
});

console.log(result.output);
console.log('Execution ID:', result.executionId);
console.log('Tokens used:', result.totalTokensUsed);

// Iterate through node results
result.nodeResults.forEach(node => {
  console.log(`Node ${node.nodeId}: ${node.status}`);
  if (node.output) console.log(`  Output: ${node.output}`);
  if (node.warning) console.log(`  Warning: ${node.warning}`);
});

// Convenience alias
const result2 = await client.queryPipeline('pipeline_id', {
  input: 'What are the key features?'
});

Response Type

interface ExecutePipelineResponse {
  executionId: string;
  status: string;
  output?: string;
  outputs?: Array<{
    nodeId: string;
    label?: string;
    output: string;
  }>;
  error?: string;
  nodeResults: Array<{
    nodeId: string;
    status: string;
    output?: string;
    tokensUsed: number;
    warning?: string;
  }>;
  totalTokensUsed: number;
}

Execution Status & History

// Get execution status
const status = await client.getPipelineExecutionStatus(
  'pipeline_id',
  'execution_id'
);

// Get full execution details
const execution = await client.getPipelineExecution(
  'pipeline_id',
  'execution_id'
);

// List executions with pagination
const page = await client.getPipelineExecutions('pipeline_id', {
  limit: 20,
  cursor: undefined  // Use page.nextCursor for next page
});

console.log(page.executions);
console.log('Has more:', page.hasMore);

Manage Pipelines

// List all pipelines
const pipelines = await client.listPipelines();

// Get a specific pipeline
const pipeline = await client.getPipeline('pipeline_id');

// Delete a pipeline
await client.deletePipeline('pipeline_id');

Indexes

Indexes store your vector embeddings for semantic search. Query them directly or assign them to agents.

Query an Index

// Search with text
const result = await client.queryIndex({
  indexId: 'index_id',
  queryText: 'What are the key features?',
  limit: 10,
  filter: { category: 'docs' }  // Optional metadata filter
});

console.log(`Found ${result.results.length} results`);
result.results.forEach(item => {
  console.log(`Score: ${item.score}, ID: ${item.id}`);
  console.log('Content:', item.payload.text);
});

// Or use the convenience alias
const result2 = await client.searchIndex({
  indexId: 'index_id',
  queryText: 'authentication',
  limit: 5
});

// Search with a pre-computed vector
const vectorResult = await client.queryIndex({
  indexId: 'index_id',
  queryVector: [0.1, 0.2, 0.3, /* ... */],
  limit: 10
});

Response Type

interface QueryIndexResponse {
  success: boolean;
  results: Array<{
    id: string;
    score: number;
    payload: Record<string, unknown>;
  }>;
}

Manage Indexes & Records

import { PineconeEmbeddingModel } from '@shinrag/sdk';

// List all indexes
const indexes = await client.listIndexes();

// Create an index
const newIndex = await client.createIndex({
  name: 'Product Docs',
  pineconeIndexName: 'my-pinecone-index',
  embeddingModel: PineconeEmbeddingModel.OPENAI_SMALL,
  metric: 'cosine'  // 'cosine' | 'euclidean' | 'dotproduct'
});

// Get index records with pagination
const records = await client.getIndexRecords('index_id', {
  limit: 50,
  paginationToken: 'next_page_token',
  prefix: 'doc_'
});

// Update records (upsert, delete)
const result = await client.updateIndexRecords('index_id', {
  records: [
    { id: 'rec_1', metadata: { text: 'Updated content' } },
    { id: 'rec_new', metadata: { text: 'New record' }, isNew: true },
    { id: 'rec_old', metadata: {}, isDeleted: true }
  ]
});

// Check ingestion job status
const job = await client.getIngestionStatus('job_id');
console.log(job.status);   // 'pending' | 'processing' | 'completed' | 'failed'
console.log(job.progress);  // 0-100

Integrations

Connect external services like Slack, GitHub, databases, and search APIs to use in your pipeline nodes.

// List all integrations
const integrations = await client.listIntegrations();

// Get available integration types
const types = await client.getIntegrationTypes();
const byCategory = await client.getIntegrationTypesByCategory();

// Create an integration (e.g. PostgreSQL)
const pg = await client.createIntegration({
  type: 'postgres',
  name: 'Production DB',
  credentials: {
    host: 'db.example.com',
    port: 5432,
    database: 'mydb',
    user: 'readonly',
    password: 'secret'
  },
  validateCredentials: true
});

// Test a connection
const test = await client.testIntegration('integration_id');
console.log('Connected:', test.success);

// Execute an integration
const result = await client.executeIntegration('integration_id', {
  config: { query: 'SELECT * FROM users LIMIT 10' },
  input: 'Fetch user data'
});

// Slack OAuth
const { url } = await client.getSlackAuthUrl();
// redirect user to url, then on callback:
const slack = await client.completeSlackOAuth(code);
const { channels } = await client.refreshSlackChannels('integration_id');

// GitHub OAuth
const { url: ghUrl } = await client.getGitHubAuthUrl();
const gh = await client.completeGitHubOAuth(code);
const { repositories } = await client.refreshGitHubRepositories('integration_id');
const { issues } = await client.getGitHubIssues('integration_id', 'owner', 'repo');
const { pullRequests } = await client.getGitHubPullRequests('integration_id', 'owner', 'repo');

Supported types: slack, discord, webhook, github, postgres, mysql, mongodb, snowflake, bigquery, perplexity, tavily, http, email

Widgets

Embed AI chat widgets on your website. Widget query endpoints are public and don't require API key authentication.

// Manage widgets (authenticated)
const widgets = await client.listWidgets();
const widget = await client.createWidget({
  name: 'Support Chat',
  agentId: 'agent_id'
});

// Public endpoints (no auth needed for end users)
const info = await client.getWidgetByKey('widget_key');

// Query a widget with session continuity
const answer = await client.queryWidget('widget_key', {
  question: 'How do I get started?',
  sessionId: 'session_123'  // Optional: maintain conversation
});

console.log(answer.answer);
console.log('Session:', answer.sessionId);

// Get conversation history
const history = await client.getWidgetSessionHistory(
  'widget_key',
  'session_123'
);
console.log(history.messages);  // Array of { role, content }

Batch Execution

Run a pipeline with multiple inputs in a single batch for bulk processing.

// Create a batch
const batch = await client.createBatch('pipeline_id', {
  inputs: [
    'What is the return policy?',
    'How do I contact support?',
    'What are the shipping options?'
  ],
  name: 'FAQ Batch'
});

// Poll for completion
let status = await client.getBatchStatus(batch.batchId);
while (status.status === 'pending' || status.status === 'processing') {
  await new Promise(r => setTimeout(r, 2000));
  status = await client.getBatchStatus(batch.batchId);
  console.log(`Progress: ${status.processedItems}/${status.totalItems}`);
}

// Check results
if (status.results) {
  status.results.forEach(item => {
    console.log(`Input: ${item.input}`);
    console.log(`Output: ${item.output}`);
  });
}

Webhooks & Schedules

Automate pipeline execution with webhooks (trigger on external events) and schedules (run on a cron schedule).

Webhooks

// Create a webhook to trigger a pipeline
const webhook = await client.createWebhook('pipeline_id', {
  name: 'Incoming Data Webhook',
  description: 'Triggers pipeline on new data',
  secretToken: 'my-secret',        // Optional: for verification
  inputMapping: '{{body.query}}'   // Optional: extract input from payload
});

console.log('Webhook URL:', webhook.webhookKey);

// List & delete webhooks
const webhooks = await client.listWebhooks('pipeline_id');
await client.deleteWebhook('pipeline_id', 'webhook_id');

Schedules

// Create a cron schedule
const schedule = await client.createSchedule('pipeline_id', {
  name: 'Daily Report',
  cronExpression: '0 9 * * *',               // Every day at 9 AM
  inputTemplate: 'Generate daily summary',
  timezone: 'America/New_York'                // Optional
});

console.log('Next run:', schedule.nextRunAt);

// List & delete schedules
const schedules = await client.listSchedules('pipeline_id');
await client.deleteSchedule('pipeline_id', 'schedule_id');

Cost Tracking

Monitor token usage, compute costs, and track spending across your pipelines.

// Get cost summary (last 30 days)
const summary = await client.getCostSummary(30);
console.log('Total cost:', summary.totalCostDollars);
console.log('Total tokens:', summary.totalTokens);
console.log('Executions:', summary.executionCount);

// Cost breakdown by pipeline
const pipelineCosts = await client.getPipelineCosts(30);
pipelineCosts.forEach(p => {
  console.log(`${p.chainName}: $${p.totalCostDollars}`);
});

// Daily cost trend
const trend = await client.getCostTrend(30);

// Cost for a specific execution
const execCost = await client.getExecutionCost('execution_id');
console.log('Node costs:', execCost.nodeCosts);

// Get current cost rates
const rates = await client.getCostRates();

API Keys

Programmatically manage your API keys.

// List all API keys
const keys = await client.listApiKeys();

// Create a new API key
const newKey = await client.createApiKey({ name: 'Production' });
console.log(newKey.key);  // sk_... (only shown once!)

// Delete an API key
await client.deleteApiKey('key_id');

Error Handling

The SDK throws ShinRAGError for API errors with detailed information.

import { ShinRAGClient, ShinRAGError } from '@shinrag/sdk';

const client = new ShinRAGClient({
  apiKey: 'sk_your_api_key_here'
});

try {
  const result = await client.executePipeline('pipeline-id', {
    input: 'Your query here'
  });
  console.log(result.output);
} catch (error) {
  if (error instanceof ShinRAGError) {
    console.error('API Error:', error.message);
    console.error('Status Code:', error.statusCode);
    console.error('Response:', error.response);
  } else {
    console.error('Unknown error:', error);
  }
}

Error Codes

Status CodeDescription
400Bad Request - Invalid request body or missing required fields
401Unauthorized - Invalid or missing API key
403Forbidden - You don't have permission to access this resource (e.g., not a member of the organization)
404Not Found - Resource not found or doesn't belong to your account
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Server error occurred