Complete API reference for estimio - Free Online Planning Poker Tool.
Most endpoints require authentication via JWT token stored in an HTTP-only cookie. Some endpoints support optional authentication (guests can access).
The following endpoints have rate limiting:
Rate limit responses include Retry-After header indicating when to retry.
All endpoints return JSON with the following structure:
{
"success": true|false,
"data": {...},
"error": "Error message",
"message": "Success message"
}
Register a new user account.
Rate Limit: 3 attempts per hour per IP
Request Body:
{
"email": "user@example.com",
"password": "securepassword123"
}
Response (200):
{
"success": true,
"message": "Registration successful. Please check your email to verify your account."
}
Errors:
Log in to an existing account.
Rate Limit: 5 attempts per 15 minutes per IP
Request Body:
{
"email": "user@example.com",
"password": "securepassword123"
}
Response (200):
{
"success": true,
"user": {
"id": "user-id",
"email": "user@example.com",
"emailVerified": true,
"geminiEnabled": false
},
"token": "jwt-token-here"
}
Errors:
Verify email address via link (redirects to frontend).
Parameters:
Response: Redirects to frontend with ?success=true or ?error=invalid
Verify email address via API.
Parameters:
Response (200):
{
"success": true,
"message": "Email verified successfully"
}
Errors:
Request password reset email.
Rate Limit: 3 attempts per hour per IP
Request Body:
{
"email": "user@example.com"
}
Response (200):
{
"success": true,
"message": "If an account exists, a password reset email has been sent"
}
Note: Always returns success to prevent email enumeration.
Reset password using reset token.
Parameters:
Request Body:
{
"password": "newsecurepassword123"
}
Response (200):
{
"success": true,
"message": "Password reset successfully"
}
Errors:
Get current authenticated user.
Authentication: Optional (returns null if not authenticated)
Response (200):
{
"success": true,
"user": {
"id": "user-id",
"email": "user@example.com",
"emailVerified": true,
"geminiEnabled": false
}
}
Or if not authenticated:
{
"success": true,
"user": null
}
Log out current user (clears auth cookie).
Response (200):
{
"success": true,
"message": "Logged out successfully"
}
Delete user account and all associated data (GDPR compliance).
Authentication: Required
Response (200):
{
"success": true,
"message": "Account deleted successfully"
}
Errors:
Enable or disable Gemini AI features.
Authentication: Required
Request Body:
{
"enabled": true
}
Response (200):
{
"success": true,
"geminiEnabled": true
}
Errors:
Get user's Jira connection configuration.
Authentication: Required
Response (200):
{
"success": true,
"connection": {
"id": "connection-id",
"type": "cloud",
"baseUrl": "https://company.atlassian.net",
"organizationId": "company",
"username": "user@example.com",
"storyPointsFieldId": "Story Points"
}
}
Or if no connection:
{
"success": true,
"connection": null
}
Create or update Jira connection.
Authentication: Required
Request Body (Jira Cloud):
{
"type": "cloud",
"organizationId": "company",
"username": "user@example.com",
"token": "api-token",
"storyPointsFieldId": "Story Points"
}
Request Body (Jira Server):
{
"type": "server",
"baseUrl": "https://jira.company.com",
"username": "username",
"password": "password",
"storyPointsFieldId": "Story Points"
}
Response (200):
{
"success": true,
"message": "Jira connection created"
}
Errors:
Delete Jira connection.
Authentication: Required
Response (200):
{
"success": true,
"message": "Jira connection deleted"
}
Test Jira connection.
Authentication: Required
Request Body: Same as POST /api/jira/connections`
Response (200):
{
"success": true,
"message": "Connection successful"
}
Errors:
Get list of Jira projects.
Authentication: Required
Query Parameters:
connectionId (optional): Connection ID to useResponse (200):
{
"success": true,
"projects": [
{
"id": "10000",
"key": "PROJ",
"name": "Project Name"
}
]
}
Get list of sprints for a project.
Authentication: Required
Query Parameters:
projectKey: Jira project key (e.g., "PROJ")connectionId (optional): Connection ID to useResponse (200):
{
"success": true,
"sprints": [
{
"id": 123,
"name": "Sprint 1",
"state": "active"
}
]
}
Get Jira issues for a sprint or project.
Authentication: Required
Query Parameters:
projectKey: Jira project keysprintId (optional): Sprint IDconnectionId (optional): Connection ID to useResponse (200):
{
"success": true,
"issues": [
{
"key": "PROJ-123",
"summary": "Issue title",
"description": "Issue description",
"storyPoints": 5
}
]
}
Generate AI summary for a story (legacy endpoint).
Authentication: Required
Rate Limit: 20 requests per minute per user
Request Body:
{
"issueKey": "PROJ-123",
"summary": "Story summary",
"description": "Story description"
}
Response (200):
{
"success": true,
"summary": "AI-generated summary text"
}
Errors:
Generate structured AI summary for a Jira story.
Authentication: Required
Rate Limit: 20 requests per minute per user
Request Body:
{
"key": "PROJ-123",
"summary": "Story summary",
"description": "Story description",
"acceptanceCriteria": "Acceptance criteria",
"comments": []
}
Response (200):
{
"success": true,
"summary": {
"oneSentenceSummary": "Summary text",
"keyConstraints": ["Constraint 1", "Constraint 2"],
"acceptanceCriteria": "Condensed criteria",
"risksDependencies": ["Risk 1"],
"technicalDifficulty": 5
}
}
Predict story complexity and estimate story points.
Authentication: Required
Rate Limit: 20 requests per minute per user
Request Body:
{
"storyTitle": "Story title",
"description": "Story description",
"acceptanceCriteria": "Acceptance criteria"
}
Response (200):
{
"success": true,
"prediction": {
"suggestedPoints": "8",
"confidence": "high",
"reasoning": "Reasoning text",
"similarStoriesCount": 3,
"teamAverage": "7.5"
}
}
Create a new planning session.
Authentication: Optional (logged-in users can save sessions)
Request Body:
{
"moderatorName": "John Doe",
"title": "Sprint Planning"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"moderatorName": "John Doe",
"participants": [],
"storyTitle": "",
"votesRevealed": false,
"createdAt": 1234567890
}
}
Join an existing session.
Rate Limit: 10 requests per minute per IP
Parameters:
Request Body:
{
"name": "Participant Name"
}
Response (200):
{
"success": true,
"participantId": "participant-id",
"session": {
"code": "ABC123",
"moderatorName": "John Doe",
"participants": [...],
"storyTitle": "Story title",
"votesRevealed": false
}
}
Errors:
Get session details.
Parameters:
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"moderatorName": "John Doe",
"participants": [...],
"storyTitle": "Story title",
"votesRevealed": false,
"issues": [],
"currentIssueIndex": 0
}
}
Errors:
Submit a vote for the current story.
Parameters:
Request Body:
{
"participantId": "participant-id",
"vote": "8"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"participants": [...],
"votesRevealed": false
}
}
Errors:
Reveal all votes for the current story.
Parameters:
Request Body:
{
"participantId": "participant-id"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"votesRevealed": true,
"participants": [...]
}
}
Errors:
Reset votes for the current story.
Parameters:
Request Body:
{
"participantId": "participant-id"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"votesRevealed": false,
"participants": [...]
}
}
Errors:
Move to the next story in the session.
Parameters:
Request Body:
{
"participantId": "participant-id"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"currentIssueIndex": 1,
"storyTitle": "Next story title",
"votesRevealed": false,
"participants": [...]
}
}
Errors:
Trigger AI to vote on the current story.
Parameters:
Request Body:
{
"participantId": "participant-id"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"participants": [...]
}
}
Errors:
Update the current story title.
Parameters:
Request Body:
{
"participantId": "participant-id",
"storyTitle": "New story title"
}
Response (200):
{
"success": true,
"session": {
"code": "ABC123",
"storyTitle": "New story title"
}
}
Errors:
Leave a session.
Parameters:
Request Body:
{
"participantId": "participant-id"
}
Response (200):
{
"success": true,
"message": "Left session successfully"
}
Health check endpoint for Cloud Run.
Response (200):
{
"status": "ok",
"timestamp": "2024-01-01T00:00:00.000Z"
}
estimio uses HTTP polling for real-time updates (firewall-friendly). The client polls GET /api/sessions/:code every 2 seconds to receive session state updates.
estimio supports Jira webhooks for automated AI summary generation when story points are updated in Jira.
Webhook URL: https://www.estimio.ch/jira/webhook
Events: Issue Updated (when story points field changes)
Payload: Standard Jira webhook payload
Rate limits are enforced per IP or per user (for authenticated endpoints). When rate limit is exceeded:
CORS is configured to allow requests from:
https://www.estimio.chhttp://localhost:3000Last updated: January 2025
API Version: 1.0
Base URL: https://www.estimio.ch
We use cookies to enhance your experience. Essential cookies are required for the service to function. Analytics cookies help us improve the service by understanding how you use it. IP addresses are anonymized and we respect Do Not Track settings. Learn more