What are Projects?
Projects are how you organize different environments or applications in PromptGuard. Each project has:
Separate API keys - Isolate credentials per environment
Independent usage tracking - Monitor each project’s requests separately
Dedicated security settings - Configure policies per project
Individual analytics - View metrics for each project
Common Project Structures
By Environment
Production - Live application
Staging - Pre-production testing
Development - Local development
By Application
Customer Portal - Customer-facing chatbot
Admin Dashboard - Internal AI tools
Mobile App - iOS/Android application
By Team
Marketing Team - Marketing automation
Sales Team - Sales assistant
Engineering - Code review assistant
Creating Your First Project
When you sign up for PromptGuard, a “Production” project is automatically created for you. This ensures you can start using PromptGuard immediately.
Creating Additional Projects
Navigate to Projects in the dashboard
Click “Create Project”
Enter project details:
Name : Descriptive name (e.g., “Staging”, “Mobile App”)
Description : Optional context about the project
Click “Create Project”
Your new project is ready! Now you can create API keys for it.
Creating API Keys
Each project can have multiple API keys (e.g., different services, rotating keys):
Select your project from the project selector in the header
Navigate to API Keys
Click “Create API Key”
Enter details:
Name : Descriptive name (e.g., “Backend API”, “Cron Jobs”)
Click “Create API Key”
Save the API key immediately! It’s only shown once during creation. If you lose it, you’ll need to create a new key.
Switching Between Projects
Use the project selector in the dashboard header to quickly switch between projects:
Click the project name in the header
Select a different project from the dropdown
All pages (Analytics, API Keys, etc.) automatically update to show the selected project’s data
The project selector remembers your last selection, so you’ll return to the same project next time you visit the dashboard.
Project URLs
Each project has its own dedicated URLs:
/dashboard/projects/{project-id}/overview
/dashboard/projects/{project-id}/analytics
/dashboard/projects/{project-id}/api-keys
These URLs are shareable - you can bookmark or send teammates links to specific projects.
Viewing All Projects
Navigate to Projects in the dashboard to see all your projects at once:
Project statistics - Requests, flagged count, last activity
Time filtering - View stats for last 7/30/90 days
Search projects - Quickly find projects by name
Create/delete projects - Manage your project portfolio
Deleting Projects
Cannot delete your last project! You must always have at least one project. This prevents accidental lockout from the platform.
To delete a project:
Go to Projects page
Click the delete icon next to the project
Confirm deletion
What happens when you delete a project:
✅ All API keys are immediately revoked
✅ Historical data is preserved for 30 days
✅ Active requests will fail
❌ Cannot be undone
Instead of deleting, consider renaming the project or archiving it (coming soon).
Per-Project Token Limits
Control LLM costs by setting a maximum token count per request on any project. Requests exceeding the limit are rejected with HTTP 413 before reaching the LLM provider - saving you money on runaway prompts.
Setting a Token Limit
Configure via the dashboard (Project → Settings → Token Limit ) or via the database:
UPDATE projects SET max_tokens_per_request = 4096
WHERE id = 'proj_abc123' ;
How It Works
PromptGuard estimates the token count of the incoming prompt using tiktoken (the same tokenizer OpenAI uses)
If the count exceeds max_tokens_per_request, the request is rejected immediately
The response includes the actual token count so you can adjust
{
"error" : "token_limit_exceeded" ,
"detail" : "Request contains ~8,200 tokens, exceeding the project limit of 4,096" ,
"token_count" : 8200 ,
"max_tokens" : 4096
}
Token Counting
PromptGuard uses tiktoken (OpenAI’s tokenizer) for accurate counts. If tiktoken is unavailable, it falls back to a chars / 4 heuristic. Token limits apply to the full prompt text including system messages.
Set conservative limits during development (e.g., 2,048) and increase for production. This catches accidentally large prompts early.
Best Practices
Use Separate Projects for Each Environment
✅ Good: Production, Staging, Development
❌ Bad: One project for everything
Why? Isolates credentials, prevents accidental production data exposure, enables environment-specific security policies.
Name Projects Clearly
✅ Good: "Production - Customer Portal"
✅ Good: "Staging - Mobile App v2"
❌ Bad: "Project 1", "Test", "New"
Why? Makes it easy to identify projects in dropdown, avoids confusion in team environments.
Rotate API Keys Regularly
✅ Good: Create new key → Update production → Delete old key
❌ Bad: Use same key for years
Why? Limits exposure if key is compromised, follows security best practices.
Use Descriptive API Key Names
✅ Good: "Backend API - Server1", "Cron Job - Daily Report"
❌ Bad: "Key 1", "Test", "New Key"
Why? Makes it easy to identify which key is used where when rotating or debugging.
Project Limits
Plan Max Projects Max API Keys per Project Free 3 5 Pro 5 10 Scale Unlimited Unlimited
API Access
Developer API Endpoints : The project management endpoints below are part of the Developer API and are included in the OpenAPI spec. They use API key authentication and are suitable for SDK usage.
Projects can be managed programmatically using the Developer API. All endpoints require API key authentication.
Complete CRUD Operations
import requests
import os
# API key authentication (Developer API)
api_key = os.environ.get( "PROMPTGUARD_API_KEY" )
base_url = "https://api.promptguard.co/api/v1/projects"
headers = {
"X-API-Key" : api_key,
"Content-Type" : "application/json"
}
# CREATE - Create a new project
def create_project ( name , description = None , use_case = "default" , strictness_level = "moderate" ):
payload = {
"name" : name,
"description" : description,
"use_case" : use_case,
"strictness_level" : strictness_level
}
response = requests.post(base_url, headers = headers, json = payload)
if response.status_code == 201 :
project = response.json()
print ( f "Created project: { project[ 'id' ] } " )
return project
elif response.status_code == 400 :
error = response.json()
print ( f "Error: { error.get( 'detail' , 'Invalid request' ) } " )
elif response.status_code == 401 :
print ( "Error: Authentication required. Please log in." )
else :
print ( f "Error: HTTP { response.status_code } " )
return None
# READ - List all projects
def list_projects ():
response = requests.get(base_url, headers = headers)
if response.status_code == 200 :
projects = response.json()
print ( f "Found { len (projects) } projects:" )
for project in projects:
print ( f " - { project[ 'name' ] } ( { project[ 'id' ] } )" )
return projects
else :
print ( f "Error: HTTP { response.status_code } " )
return []
# READ - Get single project
def get_project ( project_id ):
url = f " { base_url } / { project_id } "
response = requests.get(url, headers = headers)
if response.status_code == 200 :
project = response.json()
print ( f "Project: { project[ 'name' ] } " )
print ( f " Description: { project.get( 'description' , 'N/A' ) } " )
print ( f " Use Case: { project.get( 'use_case' , 'default' ) } " )
print ( f " Strictness: { project.get( 'strictness_level' , 'moderate' ) } " )
return project
elif response.status_code == 404 :
print ( f "Error: Project { project_id } not found" )
else :
print ( f "Error: HTTP { response.status_code } " )
return None
# Note: Update endpoint is not available in Developer API
# To update projects, use the dashboard or delete and recreate
# DELETE - Delete project
def delete_project ( project_id ):
url = f " { base_url } / { project_id } "
response = requests.delete(url, headers = headers)
if response.status_code == 200 :
print ( f "Deleted project { project_id } " )
return True
elif response.status_code == 404 :
print ( f "Error: Project { project_id } not found" )
elif response.status_code == 400 :
error = response.json()
if "last project" in error.get( 'detail' , '' ).lower():
print ( "Error: Cannot delete your last project. Create another project first." )
else :
print ( f "Error: { error.get( 'detail' , 'Cannot delete project' ) } " )
else :
print ( f "Error: HTTP { response.status_code } " )
return False
# Example usage
if __name__ == "__main__" :
# Create a new project
project = create_project(
name = "Staging Environment" ,
description = "Pre-production testing" ,
use_case = "default" ,
strictness_level = "moderate"
)
if project:
project_id = project[ 'id' ]
# Get project details
get_project(project_id)
# Note: Update is not available in Developer API
# Use dashboard or delete and recreate if needed
# List all projects
list_projects()
# Note: Uncomment to delete (be careful!)
# delete_project(project_id)
Create Project Response (201 Created)
{
"id" : "proj_abc123def456" ,
"name" : "Staging Environment" ,
"description" : "Pre-production testing" ,
"use_case" : "default" ,
"strictness_level" : "moderate" ,
"fail_mode" : "open" ,
"created_at" : "2024-01-15T10:30:00Z" ,
"updated_at" : "2024-01-15T10:30:00Z"
}
List Projects Response (200 OK)
[
{
"id" : "proj_abc123def456" ,
"name" : "Production" ,
"description" : "Live application" ,
"use_case" : "default" ,
"strictness_level" : "moderate" ,
"created_at" : "2024-01-01T00:00:00Z"
},
{
"id" : "proj_xyz789ghi012" ,
"name" : "Staging Environment" ,
"description" : "Pre-production testing" ,
"use_case" : "support_bot" ,
"strictness_level" : "strict" ,
"created_at" : "2024-01-15T10:30:00Z"
}
]
Get Project Stats Response (200 OK)
{
"project_id" : "proj_abc123def456" ,
"stats" : {
"total_requests" : 1250 ,
"blocked_requests" : 23 ,
"block_rate" : 0.0184 ,
"last_activity" : "2024-01-15T14:30:00Z"
},
"period" : {
"days" : 30 ,
"start_date" : "2023-12-16T00:00:00Z" ,
"end_date" : "2024-01-15T23:59:59Z"
}
}
Error Responses
400 Bad Request - Invalid request or project limit reached
{
"detail" : "Project limit reached. Upgrade your plan to create more projects."
}
401 Unauthorized - Invalid or missing API key
{
"detail" : "Invalid API key"
}
404 Not Found - Project doesn’t exist
{
"detail" : "Project not found"
}
400 Bad Request - Cannot delete last project
{
"detail" : "Cannot delete your last project. Create another project first."
}
Troubleshooting
”Cannot create API key”
Cause: No project selected or project limit reached.
Solution:
Ensure a project is selected in the project selector
Check your plan’s project limits
Upgrade if needed
”API key not working”
Cause: API key belongs to wrong project or was deleted.
Solution:
Verify the API key is correctly set and not empty
Check which project the key belongs to
Ensure the key hasn’t been deleted
Create a new key if needed
”Cannot delete project”
Cause: Trying to delete your last project.
Solution: You must always have at least one project. Create a new project first, then delete the old one.
Next Steps
Create API Keys Learn how to create and manage API keys
View Analytics Monitor your project’s security metrics
Configure Security Rules Set up security policies for your project
Team Access Share projects with your team (coming soon)