Overview
Proposers are users approved to create workflows and workflow templates. All proposer endpoints require authentication via JWT Bearer token and the proposer role (or admin override).
Authentication
All endpoints use the withProposer middleware which:
- Requires a valid JWT token with
userDid in context
- Checks if user has proposer role via
IsProposer()
- Admin users automatically bypass role checks
Request Proposer Status
Before accessing proposer endpoints, users must first request and be approved for proposer status.
POST /proposers/request
Request proposer status for authenticated user.
Request Body
{
"organization": "string", // Required: organization name
"email": "string" // Required: notification email (must be verified)
}
Response: 201 Created
{
"user_id": "did:privy:...",
"organization": "Community Gardens SF",
"email": "[email protected]",
"is_approved": false,
"created_at": "2024-03-15T10:30:00Z"
}
Error Codes
400: Missing required fields, invalid email, or email not verified
409: User already has approved proposer status
403: Missing authentication
Workflow Templates
Workflow templates allow proposers to save reusable workflow configurations.
GET /proposers/workflow-templates
Get all workflow templates for the authenticated proposer.
Response: 200 OK
[
{
"id": "uuid",
"proposer_id": "did:privy:...",
"template_title": "Weekly Park Cleanup",
"recurrence": "weekly",
"steps": [...],
"created_at": "2024-03-15T10:30:00Z"
}
]
POST /proposers/workflow-templates
Create a new workflow template.
Request Body
{
"template_title": "string", // Required
"recurrence": "one_time|daily|weekly|monthly",
"start_at": "2024-03-20T09:00:00Z", // ISO 8601 timestamp
"steps": [
{
"title": "Step 1",
"bounty": 5000000000000000000, // Wei (5 tokens)
"role_id": "uuid",
"work_items": [...]
}
]
}
Response: 201 Created
Returns the created template object.
Error Codes
400: Invalid recurrence, missing title, invalid step configuration
DELETE /proposers/workflow-templates/
Delete a workflow template owned by the proposer.
Response: 204 No Content
Workflows
POST /proposers/workflows
Create a new workflow from scratch (not from a template).
Request Body
{
"title": "string", // Required
"description": "string",
"recurrence": "one_time|daily|weekly|monthly",
"start_at": "2024-03-20T09:00:00Z",
"supervisor_user_id": "did:privy:...", // Optional
"manager_required": false,
"manager_role_id": "uuid", // Required if manager_required=true
"manager_bounty": 0,
"steps": [
{
"title": "Collect supplies",
"description": "Gather tools from storage",
"bounty": 5000000000000000000,
"role_id": "uuid",
"work_items": [
{
"title": "Photo of supplies",
"item_order": 1,
"optional": false,
"requires_photo": true,
"requires_dropdown": false,
"requires_written_response": false
}
]
}
]
}
Response: 201 Created
Returns workflow with status:
approved if auto-approved (no voting required)
pending if requires voter approval
Workflow Lifecycle
pending → (voting) → approved → in_progress → completed → paid_out
↓
rejected
GET /proposers/workflows
Get all workflows created by the authenticated proposer.
Response: 200 OK
[
{
"id": "uuid",
"series_id": "uuid", // Same for recurring workflows
"proposer_id": "did:privy:...",
"title": "Park Cleanup Week 1",
"status": "approved",
"recurrence": "weekly",
"start_at": 1710921600, // Unix timestamp
"created_at": 1710835200,
"steps": [
{
"id": "uuid",
"title": "Setup",
"step_order": 1,
"status": "available",
"bounty": "5000000000000000000",
"assigned_improver_id": null,
"work_items": [...]
}
],
"votes": {
"approve_count": 5,
"deny_count": 1,
"user_vote": null
}
}
]
GET /proposers/workflows/
Get a specific workflow owned by the proposer.
Response: 200 OK
Returns full workflow details including step submissions (if proposer is also manager/supervisor).
Error Codes
404: Workflow not found or not owned by proposer
DELETE /proposers/workflows/
Delete a workflow. Only allowed if:
- Status is
pending or rejected
- No steps have been claimed
Response: 200 OK
Error Codes
400: Workflow cannot be deleted (already in progress)
404: Workflow not found
POST /proposers/workflow-deletion-proposals
Propose deletion of an active workflow (requires voting).
Request Body
{
"workflow_id": "uuid",
"reason": "string" // Required: reason for deletion
}
Response: 201 Created
Returns deletion proposal object.
Role Request Flow
-
User requests proposer status:
POST /proposers/request
- System validates email is verified
- Sends notification to admin email (
PROPOSER_ADMIN_EMAIL env var)
-
Admin approves: Via admin panel or
PUT /admin/proposers
- Sets
is_approved = true
- User can now access proposer endpoints
-
Proposer creates workflows:
POST /proposers/workflows
- Workflow enters
pending status
- Voters review and approve/deny
-
Workflow approved: Workflow moves to
approved status
- Becomes visible to improvers at
start_at time
- Improvers can claim steps
Data Schemas
WorkItem Object
{
id: string
title: string
item_order: number
optional: boolean
requires_photo: boolean
requires_dropdown: boolean
requires_written_response: boolean
dropdown_options?: [
{
option_text: string
requires_written_response: boolean
notify_emails: string[] // Hidden from most users
}
]
}
Step Object
{
id: string
title: string
description?: string
step_order: number
status: 'locked' | 'available' | 'in_progress' | 'completed' | 'paid_out'
bounty: string // Wei amount
role_id?: string
assigned_improver_id?: string
work_items: WorkItem[]
submission?: {
improver_id: string
submitted_at: number
step_not_possible: boolean
item_responses: [...]
}
}
Notes
- Workflow templates with
recurrence other than one_time create a series of workflows
- Recurring workflows share a
series_id and are blocked until prior instances are paid out
- Proposers can see all their workflows regardless of status
- Step submission data is redacted unless proposer is also supervisor/manager
- Notify emails in dropdown options are redacted unless proposer is supervisor/manager/proposer