Getting Started with the PlanOps API
This guide will walk you through making your first API call to PlanOps in under 5 minutes.
Quick Start
1. Get Your Access Token
Follow Authentication Guide to obtain a token. For quick testing:
- Sign in to PlanOps in your browser
- Open DevTools (F12) → Console
- Run:
const token = await window.Clerk.getToken(); console.log(token); - Copy the token
2. Make Your First Request
Try fetching your projects:
curl https://test-api.projectjump.app/api/v1/projects \
-H "Authorization: Bearer YOUR_TOKEN"
Response:
{
"items": [
{
"id": "proj_abc123",
"name": "Office Building Construction",
"description": "New office development project",
"status": "active",
"created_at": "2025-01-15T10:30:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 50
}
🎉 Congratulations! You just made your first API call.
Common Use Cases
List Projects
Get all projects you have access to:
import requests
headers = {'Authorization': f'Bearer {token}'}
response = requests.get(
'https://test-api.projectjump.app/api/v1/projects',
headers=headers
)
projects = response.json()
for project in projects['items']:
print(f"{project['name']} ({project['id']})")
Create a Task
Add a new task to a project:
task_data = {
"title": "Review architectural drawings",
"description": "Complete review by end of week",
"project_id": "proj_abc123",
"status": "pending",
"priority": "high",
"due_date": "2025-01-20T17:00:00Z"
}
response = requests.post(
'https://test-api.projectjump.app/api/v1/tasks',
headers=headers,
json=task_data
)
task = response.json()
print(f"Created task: {task['id']}")
Search Documents
Find documents by keyword:
params = {
"query": "foundation drawings",
"limit": 10,
"project_id": "proj_abc123"
}
response = requests.get(
'https://test-api.projectjump.app/api/v1/search',
headers=headers,
params=params
)
results = response.json()
for doc in results['items']:
print(f"{doc['title']} - {doc['document_type']}")
Upload a Document
Upload a file to a project:
# Read the file
with open('drawing.pdf', 'rb') as f:
files = {'file': ('drawing.pdf', f, 'application/pdf')}
data = {
'project_id': 'proj_abc123',
'document_type': 'drawing',
'title': 'Site Plan - Rev A',
}
response = requests.post(
'https://test-api.projectjump.app/api/v1/documents',
headers={'Authorization': f'Bearer {token}'},
files=files,
data=data
)
document = response.json()
print(f"Uploaded: {document['id']}")
Error Handling
Always handle errors appropriately:
import requests
def api_call(endpoint, method='GET', **kwargs):
"""Make an API call with error handling."""
url = f'https://test-api.projectjump.app{endpoint}'
headers = kwargs.pop('headers', {})
headers['Authorization'] = f'Bearer {token}'
response = requests.request(method, url, headers=headers, **kwargs)
# Handle errors
if response.status_code == 401:
raise Exception("Token expired or invalid - get a new token")
elif response.status_code == 403:
raise Exception("Permission denied - check user permissions")
elif response.status_code == 404:
raise Exception("Resource not found")
elif response.status_code >= 400:
error = response.json().get('detail', 'Unknown error')
raise Exception(f"API error: {error}")
return response.json()
# Usage
try:
projects = api_call('/api/v1/projects')
print(f"Found {len(projects['items'])} projects")
except Exception as e:
print(f"Error: {e}")
Pagination
Most list endpoints support pagination:
def fetch_all_projects():
"""Fetch all projects across multiple pages."""
all_projects = []
page = 1
page_size = 50
while True:
response = requests.get(
'https://test-api.projectjump.app/api/v1/projects',
headers=headers,
params={'page': page, 'page_size': page_size}
)
data = response.json()
all_projects.extend(data['items'])
# Check if there are more pages
if len(data['items']) < page_size:
break
page += 1
return all_projects
projects = fetch_all_projects()
print(f"Total projects: {len(projects)}")
Rate Limiting
The API implements rate limiting to ensure fair usage:
- Rate limit: 100 requests per minute per user
- Headers:
X-RateLimit-Limit: Maximum requests allowedX-RateLimit-Remaining: Requests remainingX-RateLimit-Reset: Time when limit resets (Unix timestamp)
Handle rate limits:
import time
response = requests.get(url, headers=headers)
if response.status_code == 429: # Too Many Requests
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
response = requests.get(url, headers=headers) # Retry
Best Practices
1. Reuse Tokens
Don't fetch a new token for every request. Tokens are valid for 60 minutes:
class PlanOpsClient:
def __init__(self, token):
self.token = token
self.base_url = 'https://test-api.projectjump.app'
self.headers = {'Authorization': f'Bearer {token}'}
def get_projects(self):
return requests.get(
f'{self.base_url}/api/v1/projects',
headers=self.headers
).json()
def get_tasks(self, project_id):
return requests.get(
f'{self.base_url}/api/v1/tasks',
headers=self.headers,
params={'project_id': project_id}
).json()
# Initialize once
client = PlanOpsClient(token)
# Reuse for multiple calls
projects = client.get_projects()
tasks = client.get_tasks('proj_abc123')
2. Use Meaningful Error Messages
Log request details for debugging:
import logging
logger = logging.getLogger(__name__)
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
except requests.HTTPError as e:
logger.error(
f"API request failed: {e.response.status_code} "
f"{e.response.text} (URL: {url})"
)
raise
3. Validate Data Before Sending
Check required fields before making requests:
def create_task(title, project_id, **kwargs):
"""Create a task with validation."""
if not title or not project_id:
raise ValueError("title and project_id are required")
task_data = {
'title': title,
'project_id': project_id,
**kwargs
}
return requests.post(
'https://test-api.projectjump.app/api/v1/tasks',
headers=headers,
json=task_data
).json()
Next Steps
Now that you've made your first API calls, explore:
- API Reference - Full endpoint documentation
- Common Workflows - Real-world integration examples
- Authentication - Advanced auth flows
Example Projects
Check out these example integrations:
Python Script
#!/usr/bin/env python3
"""Export all tasks from a project to CSV."""
import csv
import requests
import sys
TOKEN = "your_token_here"
PROJECT_ID = "proj_abc123"
headers = {'Authorization': f'Bearer {TOKEN}'}
# Fetch tasks
response = requests.get(
'https://test-api.projectjump.app/api/v1/tasks',
headers=headers,
params={'project_id': PROJECT_ID}
)
tasks = response.json()['items']
# Write to CSV
with open('tasks.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['id', 'title', 'status', 'priority', 'due_date'])
writer.writeheader()
writer.writerows(tasks)
print(f"Exported {len(tasks)} tasks to tasks.csv")
Node.js Integration
const fetch = require('node-fetch');
const API_BASE = 'https://test-api.projectjump.app';
const TOKEN = 'your_token_here';
async function getProjects() {
const response = await fetch(`${API_BASE}/api/v1/projects`, {
headers: { 'Authorization': `Bearer ${TOKEN}` }
});
if (!response.ok) {
throw new Error(`API error: ${response.statusText}`);
}
return response.json();
}
async function main() {
const projects = await getProjects();
console.log(`Found ${projects.items.length} projects`);
for (const project of projects.items) {
console.log(`- ${project.name} (${project.status})`);
}
}
main().catch(console.error);
Need Help?
- Questions? Check the API Reference
- Issues? Review Authentication Guide
- Support? Contact us through your dashboard
Last updated: 2025-12-12