Skip to main content

Instruction Sets API

Instruction Sets are curated collections of documents designed for full-context LLM loading. They allow you to create organized sets of documents that can be shared publicly via a unique URL.

Overview

FeatureDescription
Max documents20 per set
Max size100 KB total content
Public accessOptional "anyone with link" sharing
OrderingCustom document order with drag & drop

Management Endpoints

All management endpoints require authentication.

List Instruction Sets

GET /api/workspaces/{workspaceId}/instruction-sets

Returns all Instruction Sets in the workspace.

Example Request

curl "https://api.synjar.com/api/workspaces/ws-123/instruction-sets" \
-H "Authorization: Bearer YOUR_API_KEY"

Response

{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Onboarding Guide",
"description": "Complete onboarding documentation",
"isPublic": true,
"documentCount": 5,
"totalSizeBytes": 45000,
"publicUrl": "https://app.synjar.com/s/550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2025-12-30T10:00:00Z",
"updatedAt": "2025-12-30T14:30:00Z"
}
]
}

Create Instruction Set

POST /api/workspaces/{workspaceId}/instruction-sets

Creates a new Instruction Set.

Request Body

FieldTypeRequiredDescription
namestringYesSet name (max 200 chars)
descriptionstringNoDescription (max 500 chars)
isPublicbooleanNoEnable public access (default: false)

Example Request

curl -X POST "https://api.synjar.com/api/workspaces/ws-123/instruction-sets" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "API Integration Guide",
"description": "Documents for integrating with our API",
"isPublic": true
}'

JavaScript

const response = await fetch(
`https://api.synjar.com/api/workspaces/${workspaceId}/instruction-sets`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'API Integration Guide',
description: 'Documents for integrating with our API',
isPublic: true,
}),
}
);

const instructionSet = await response.json();
console.log(instructionSet.publicUrl);

Python

import requests

response = requests.post(
f'https://api.synjar.com/api/workspaces/{workspace_id}/instruction-sets',
headers={'Authorization': f'Bearer {api_key}'},
json={
'name': 'API Integration Guide',
'description': 'Documents for integrating with our API',
'isPublic': True,
}
)

instruction_set = response.json()
print(instruction_set['publicUrl'])

Response

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "API Integration Guide",
"description": "Documents for integrating with our API",
"isPublic": true,
"documentCount": 0,
"totalSizeBytes": 0,
"publicUrl": "https://app.synjar.com/s/550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2025-12-30T10:00:00Z",
"updatedAt": "2025-12-30T10:00:00Z"
}

Get Instruction Set

GET /api/instruction-sets/{id}

Returns detailed information about an Instruction Set, including its documents.

Example Request

curl "https://api.synjar.com/api/instruction-sets/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer YOUR_API_KEY"

Response

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "API Integration Guide",
"description": "Documents for integrating with our API",
"isPublic": true,
"publicUrl": "https://app.synjar.com/s/550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2025-12-30T10:00:00Z",
"updatedAt": "2025-12-30T14:30:00Z",
"documents": [
{
"documentId": "doc-001",
"title": "Authentication Guide",
"sizeBytes": 12500,
"purpose": "INSTRUCTION",
"order": 0
},
{
"documentId": "doc-002",
"title": "API Reference",
"sizeBytes": 25000,
"purpose": "KNOWLEDGE",
"order": 1
}
],
"totalSizeBytes": 37500,
"documentCount": 2
}

Update Instruction Set

PATCH /api/instruction-sets/{id}

Updates Instruction Set metadata. Supports optimistic locking to prevent concurrent edit conflicts.

Request Body

FieldTypeRequiredDescription
namestringNoNew name (max 200 chars)
descriptionstringNoNew description (max 500 chars)
isPublicbooleanNoEnable/disable public access
expectedUpdatedAtISO 8601NoFor optimistic locking

Example Request

curl -X PATCH "https://api.synjar.com/api/instruction-sets/550e8400" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Guide Name",
"isPublic": false,
"expectedUpdatedAt": "2025-12-30T14:30:00Z"
}'

JavaScript

async function updateInstructionSet(id, updates, lastUpdatedAt) {
const response = await fetch(
`https://api.synjar.com/api/instruction-sets/${id}`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
...updates,
expectedUpdatedAt: lastUpdatedAt,
}),
}
);

if (response.status === 409) {
const error = await response.json();
throw new Error(`Conflict: ${error.error.message}`);
}

return response.json();
}

Python

def update_instruction_set(set_id, updates, last_updated_at=None):
payload = {**updates}
if last_updated_at:
payload['expectedUpdatedAt'] = last_updated_at

response = requests.patch(
f'https://api.synjar.com/api/instruction-sets/{set_id}',
headers={'Authorization': f'Bearer {api_key}'},
json=payload
)

if response.status_code == 409:
raise Exception(f"Conflict: {response.json()['error']['message']}")

return response.json()

Response

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Updated Guide Name",
"description": "Documents for integrating with our API",
"isPublic": false,
"publicUrl": null,
"updatedAt": "2025-12-30T15:00:00Z"
}

Delete Instruction Set

DELETE /api/instruction-sets/{id}

Permanently deletes an Instruction Set. Documents are NOT deleted (only removed from set).

Example Request

curl -X DELETE "https://api.synjar.com/api/instruction-sets/550e8400" \
-H "Authorization: Bearer YOUR_API_KEY"

Response

204 No Content

Document Management

Add Document to Set

POST /api/instruction-sets/{id}/documents

Adds a document to the Instruction Set. Only VERIFIED documents can be added.

Request Body

FieldTypeRequiredDescription
documentIdstringYesDocument UUID to add

Example Request

curl -X POST "https://api.synjar.com/api/instruction-sets/550e8400/documents" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"documentId": "doc-003"}'

JavaScript

async function addDocumentToSet(setId, documentId) {
const response = await fetch(
`https://api.synjar.com/api/instruction-sets/${setId}/documents`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ documentId }),
}
);

if (!response.ok) {
const error = await response.json();
if (error.error.code === 'SIZE_LIMIT_EXCEEDED') {
throw new Error('Adding this document would exceed the 100 KB limit');
}
if (error.error.code === 'DOCUMENT_LIMIT_EXCEEDED') {
throw new Error('Maximum 20 documents allowed per set');
}
throw new Error(error.error.message);
}

return response.json();
}

Python

def add_document_to_set(set_id, document_id):
response = requests.post(
f'https://api.synjar.com/api/instruction-sets/{set_id}/documents',
headers={'Authorization': f'Bearer {api_key}'},
json={'documentId': document_id}
)

if response.status_code == 400:
error = response.json()['error']
if error['code'] == 'SIZE_LIMIT_EXCEEDED':
raise Exception('Adding this document would exceed the 100 KB limit')
if error['code'] == 'DOCUMENT_LIMIT_EXCEEDED':
raise Exception('Maximum 20 documents allowed per set')

response.raise_for_status()
return response.json()

Response

{
"documentId": "doc-003",
"title": "Error Handling Guide",
"sizeBytes": 8500,
"purpose": "INSTRUCTION",
"order": 2
}

Remove Document from Set

DELETE /api/instruction-sets/{id}/documents/{documentId}

Removes a document from the set. The document itself is NOT deleted.

Example Request

curl -X DELETE "https://api.synjar.com/api/instruction-sets/550e8400/documents/doc-003" \
-H "Authorization: Bearer YOUR_API_KEY"

Response

204 No Content

Reorder Documents

PATCH /api/instruction-sets/{id}/documents/reorder

Updates the order of documents in the set.

Request Body

FieldTypeRequiredDescription
documentIdsstring[]YesDocument IDs in desired order

Example Request

curl -X PATCH "https://api.synjar.com/api/instruction-sets/550e8400/documents/reorder" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"documentIds": ["doc-002", "doc-001", "doc-003"]}'

JavaScript

async function reorderDocuments(setId, documentIds) {
const response = await fetch(
`https://api.synjar.com/api/instruction-sets/${setId}/documents/reorder`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ documentIds }),
}
);

return response.json();
}

Python

def reorder_documents(set_id, document_ids):
response = requests.patch(
f'https://api.synjar.com/api/instruction-sets/{set_id}/documents/reorder',
headers={'Authorization': f'Bearer {api_key}'},
json={'documentIds': document_ids}
)

response.raise_for_status()
return response.json()

Response

{
"documents": [
{"documentId": "doc-002", "order": 0},
{"documentId": "doc-001", "order": 1},
{"documentId": "doc-003", "order": 2}
]
}

Public Access Endpoints

These endpoints do NOT require authentication when the Instruction Set is public.

View Instruction Set (HTML)

GET /s/{id}

Returns an HTML page with the combined content of all documents in the set.

Access Control

  • Public sets (isPublic: true): Anyone with the link can view
  • Private sets (isPublic: false): Returns 404 Not Found

Example

# Opens in browser
open "https://app.synjar.com/s/550e8400-e29b-41d4-a716-446655440000"

Response

HTML page with:

  • Set name and description
  • Combined document content in order
  • Responsive styling for readability

Get Raw Content (Text)

GET /s/{id}/raw

Returns plain text content of all documents, suitable for LLM context.

Example Request

curl "https://app.synjar.com/s/550e8400-e29b-41d4-a716-446655440000/raw"

JavaScript

async function getInstructionSetContent(publicUrl) {
const response = await fetch(`${publicUrl}/raw`);
if (!response.ok) {
throw new Error('Instruction set not found or not public');
}
return response.text();
}

// Usage with OpenAI
async function chatWithContext(question, instructionSetUrl) {
const context = await getInstructionSetContent(instructionSetUrl);

const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [
{
role: 'system',
content: `Use this context to answer questions:\n\n${context}`,
},
{ role: 'user', content: question },
],
});

return response.choices[0].message.content;
}

Python

import requests
from openai import OpenAI

def get_instruction_set_content(public_url):
response = requests.get(f'{public_url}/raw')
response.raise_for_status()
return response.text

# Usage with OpenAI
def chat_with_context(question, instruction_set_url):
context = get_instruction_set_content(instruction_set_url)

client = OpenAI()
response = client.chat.completions.create(
model='gpt-4',
messages=[
{
'role': 'system',
'content': f'Use this context to answer questions:\n\n{context}',
},
{'role': 'user', 'content': question},
],
)

return response.choices[0].message.content

Response

Content-Type: text/plain

# Authentication Guide

This guide covers how to authenticate with our API...

---

# API Reference

## Endpoints

### GET /api/users
...

Error Codes

Instruction Set Errors

CodeHTTPDescription
SIZE_LIMIT_EXCEEDED400Adding document would exceed 100 KB limit
DOCUMENT_LIMIT_EXCEEDED400Maximum 20 documents per set
DOCUMENT_NOT_VERIFIED400Only VERIFIED documents can be added
DOCUMENT_ALREADY_IN_SET409Document already exists in this set
CONFLICT409Concurrent edit detected (optimistic locking)
NOT_FOUND404Instruction set or document not found

Error Response Format

{
"error": {
"code": "SIZE_LIMIT_EXCEEDED",
"message": "Adding this document would exceed the 100 KB size limit",
"details": {
"currentSize": 95000,
"documentSize": 8000,
"maxSize": 102400
},
"suggestion": "Remove some documents or choose a smaller document"
}
}

Conflict Error (409)

When another user has modified the set:

{
"error": {
"code": "CONFLICT",
"message": "This set was modified by another user",
"details": {
"lastModifiedAt": "2025-12-30T15:00:00Z"
},
"suggestion": "Refresh the page to see the latest changes"
}
}

Rate Limits

EndpointAuthenticatedPublic
List sets60/minN/A
Create/Update/Delete30/minN/A
Add/Remove documents60/minN/A
Reorder documents10/minN/A
View public set (HTML)N/A60/min per IP
Get raw contentN/A30/min per IP

Rate Limit Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704110400

Response Fields Reference

Instruction Set Object

FieldTypeDescription
idstringUnique identifier (UUID)
namestringSet name
descriptionstringOptional description
isPublicbooleanWhether publicly accessible
publicUrlstringURL for public access (null if private)
documentCountnumberNumber of documents in set
totalSizeBytesnumberTotal content size in bytes
createdAtISO 8601Creation timestamp
updatedAtISO 8601Last modification timestamp
documentsarrayDocuments in order (only in GET /instruction-sets/:id)

Document Object

FieldTypeDescription
documentIdstringDocument UUID
titlestringDocument title
sizeBytesnumberContent size in bytes
purposestringKNOWLEDGE or INSTRUCTION
ordernumberPosition in set (0-indexed)

Integration Examples

Building a Custom Instructions Bot

import OpenAI from 'openai';

const openai = new OpenAI();

async function createAssistantWithInstructions(instructionSetUrl) {
// Fetch the instruction set content
const response = await fetch(`${instructionSetUrl}/raw`);
const instructions = await response.text();

// Create an assistant with the instructions
const assistant = await openai.beta.assistants.create({
name: 'Custom Support Bot',
instructions: instructions,
model: 'gpt-4-turbo-preview',
});

return assistant;
}

Syncing Instructions to Claude

import anthropic
import requests

def create_claude_message_with_instructions(question, instruction_set_url):
# Fetch instruction set content
response = requests.get(f'{instruction_set_url}/raw')
instructions = response.text

client = anthropic.Anthropic()

message = client.messages.create(
model='claude-3-opus-20240229',
max_tokens=1024,
system=instructions,
messages=[
{'role': 'user', 'content': question}
]
)

return message.content[0].text

See also