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
| Feature | Description |
|---|---|
| Max documents | 20 per set |
| Max size | 100 KB total content |
| Public access | Optional "anyone with link" sharing |
| Ordering | Custom 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
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Set name (max 200 chars) |
description | string | No | Description (max 500 chars) |
isPublic | boolean | No | Enable 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
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | New name (max 200 chars) |
description | string | No | New description (max 500 chars) |
isPublic | boolean | No | Enable/disable public access |
expectedUpdatedAt | ISO 8601 | No | For 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
| Field | Type | Required | Description |
|---|---|---|---|
documentId | string | Yes | Document 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
| Field | Type | Required | Description |
|---|---|---|---|
documentIds | string[] | Yes | Document 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
| Code | HTTP | Description |
|---|---|---|
SIZE_LIMIT_EXCEEDED | 400 | Adding document would exceed 100 KB limit |
DOCUMENT_LIMIT_EXCEEDED | 400 | Maximum 20 documents per set |
DOCUMENT_NOT_VERIFIED | 400 | Only VERIFIED documents can be added |
DOCUMENT_ALREADY_IN_SET | 409 | Document already exists in this set |
CONFLICT | 409 | Concurrent edit detected (optimistic locking) |
NOT_FOUND | 404 | Instruction 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
| Endpoint | Authenticated | Public |
|---|---|---|
| List sets | 60/min | N/A |
| Create/Update/Delete | 30/min | N/A |
| Add/Remove documents | 60/min | N/A |
| Reorder documents | 10/min | N/A |
| View public set (HTML) | N/A | 60/min per IP |
| Get raw content | N/A | 30/min per IP |
Rate Limit Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704110400
Response Fields Reference
Instruction Set Object
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (UUID) |
name | string | Set name |
description | string | Optional description |
isPublic | boolean | Whether publicly accessible |
publicUrl | string | URL for public access (null if private) |
documentCount | number | Number of documents in set |
totalSizeBytes | number | Total content size in bytes |
createdAt | ISO 8601 | Creation timestamp |
updatedAt | ISO 8601 | Last modification timestamp |
documents | array | Documents in order (only in GET /instruction-sets/:id) |
Document Object
| Field | Type | Description |
|---|---|---|
documentId | string | Document UUID |
title | string | Document title |
sizeBytes | number | Content size in bytes |
purpose | string | KNOWLEDGE or INSTRUCTION |
order | number | Position 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