openapi: 3.0.3
info:
title: Refine Backlog API
description: |
AI-powered backlog refinement API. Transform raw, messy backlog items into structured,
actionable work items with titles, problem statements, acceptance criteria, effort estimates,
priorities, tags, and assumptions.
## Authentication
Free tier (5 items/request) requires no authentication.
Pro and Team tiers require a license key passed via the `x-license-key` header.
## Rate Limits
- **Free**: 5 items per request, rate-limited by IP
- **Pro** ($9/mo): 25 items per request
- **Team** ($29/mo): 50 items per request
version: "1.0.0"
contact:
url: https://refinebacklog.com
license:
name: Proprietary
servers:
- url: https://refinebacklog.com
description: Production
paths:
/api/refine:
get:
summary: API Info
description: Returns API description and usage instructions.
operationId: getApiInfo
responses:
"200":
description: API info
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Refine Backlog API
usage:
type: string
example: POST /api/refine with { items: string[], context?: string }
limit:
type: string
example: "5 items per request (free tier), 25 (Pro), 50 (Team)"
post:
summary: Refine Backlog Items
description: |
Accepts an array of raw backlog item strings and returns structured, refined work items.
Each item is enriched with a clean title, problem statement, acceptance criteria,
T-shirt size estimate, prioritized rating, tags, and optional clarifying assumptions.
operationId: refineItems
security:
- ApiKeyAuth: []
- {}
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RefineRequest"
example:
items:
- "fix the login bug"
- "users need to export their data"
- "make the dashboard faster"
context: "B2B project management SaaS for engineering teams"
responses:
"200":
description: Successfully refined backlog items
content:
application/json:
schema:
$ref: "#/components/schemas/RefineResponse"
example:
items:
- title: "Fix authentication failure on login with special characters in password"
problem: "Users with passwords containing special characters are unable to log in, causing account lockouts and support escalations."
acceptanceCriteria:
- "Users with passwords containing !@#$%^&*() can log in successfully"
- "Error messages are clear and actionable when login fails"
- "Existing sessions are not affected by the fix"
estimate: "S"
priority: "HIGH — causes account lockouts and direct user impact"
tags: ["bug", "auth"]
assumptions:
- "Assumes the issue is frontend input sanitization, not backend validation"
_meta:
requestId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
model: "claude-3-5-haiku-20241022"
inputTokens: 312
outputTokens: 489
costUsd: 0.000245
latencyMs: 2341
promptVersion: "1.0"
tier: "free"
"400":
description: Invalid request — missing or malformed items array
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: "No backlog items provided. Send { items: string[] }"
"429":
description: Rate limit exceeded
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: "Rate limit exceeded. Upgrade to Pro for higher limits."
"503":
description: AI service temporarily unavailable
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: "AI service temporarily unavailable"
/api/discover:
get:
summary: Discovery Gate API Info
description: Returns Discovery Gate API description and usage instructions.
operationId: getDiscoverApiInfo
responses:
"200":
description: API info
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Discovery Gate API
usage:
type: string
example: POST /api/discover with { item: string, context?: string }
post:
summary: Classify Backlog Item Discovery Risk
description: |
Classifies a single backlog item's discovery risk before refinement. Returns SKIP,
LIGHT_DISCOVERY, or FULL_DISCOVERY with ranked questions and hidden assumptions.
Use this as a quality gate BEFORE calling /api/refine to ensure the item is
ready to build. AI coding agents make it 10x faster to build the wrong thing —
this endpoint helps you build the right thing.
**Free tier**: Returns classification + rationale + 1 question + 1 assumption.
**Pro/Team tier**: Full output with all questions and assumptions.
operationId: discoverItem
security:
- ApiKeyAuth: []
- {}
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DiscoverRequest"
example:
item: "Improve the dashboard so users can see their data better"
context: "B2B project management SaaS for engineering teams"
responses:
"200":
description: Discovery classification result
content:
application/json:
schema:
$ref: "#/components/schemas/DiscoverResponse"
example:
classification: "FULL_DISCOVERY"
confidence: 0.89
rationale: "Vague verb 'improve' with no measurable outcome defined. 'Better' is unmeasurable and the target user is undefined."
primary_signal: "'improve' and 'better' with no metric or target user"
questions:
- rank: 1
question: "What specific data do users currently struggle to find in the dashboard?"
category: "user_job"
why_it_matters: "Without knowing what's broken, we might add the wrong visualizations"
fastest_validation: "support ticket review"
assumptions:
- statement: "We assume that users are failing to find data they need, not that the data is missing"
type: "desirability"
risk: "high"
simple_test: "Review 5 support tickets or user session recordings for dashboard confusion patterns"
_meta:
requestId: "b2c3d4e5-f6a7-8901-bcde-f12345678901"
model: "claude-haiku-4-5"
inputTokens: 428
outputTokens: 612
costUsd: 0.000354
latencyMs: 1876
tier: "free"
"400":
description: Invalid request — missing or empty item
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: "No backlog item provided. Send { item: string }"
"429":
description: Rate limit exceeded
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: "Daily discovery limit reached on the free tier (3 requests/day). Upgrade to Pro for unlimited requests at $9/month."
upgrade: "https://refinebacklog.com/pricing"
"503":
description: AI service temporarily unavailable
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
example:
error: "AI service temporarily unavailable"
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: x-license-key
description: |
License key for Pro or Team tier access.
Obtain at https://refinebacklog.com/pricing
Free tier (5 items/request) works without a key.
schemas:
RefineRequest:
type: object
required:
- items
properties:
items:
type: array
items:
type: string
minItems: 1
maxItems: 50
description: |
Array of raw backlog item strings to refine.
Max items depends on tier: 5 (free), 25 (Pro), 50 (Team).
example:
- "fix the login bug"
- "users need to be able to export their data"
context:
type: string
description: |
Optional project context to improve the quality and relevance of refinements.
Example: "B2B SaaS CRM for enterprise sales teams" or "Mobile fitness app for casual runners".
example: "B2B project management SaaS for engineering teams"
useUserStories:
type: boolean
default: false
description: |
When true, formats titles as user stories:
"As a [user], I want [goal], so that [benefit]"
useGherkin:
type: boolean
default: false
description: |
When true, formats acceptance criteria using Gherkin syntax:
Given [context], When [action], Then [outcome]
RefineResponse:
type: object
properties:
items:
type: array
items:
$ref: "#/components/schemas/RefinedItem"
_meta:
$ref: "#/components/schemas/ResponseMeta"
RefinedItem:
type: object
required:
- title
- problem
- acceptanceCriteria
- estimate
- priority
- tags
properties:
title:
type: string
description: Clean, actionable title for the backlog item
example: "Fix authentication failure on login with special characters in password"
problem:
type: string
description: Why this matters — concise problem statement (1-2 sentences)
example: "Users with passwords containing special characters are unable to log in."
acceptanceCriteria:
type: array
items:
type: string
minItems: 2
maxItems: 4
description: 2-4 testable acceptance criteria
example:
- "Users with passwords containing !@#$%^&*() can log in successfully"
- "Error messages are clear and actionable when login fails"
estimate:
type: string
enum: [XS, S, M, L, XL]
description: |
T-shirt size effort estimate:
- XS: Less than 1 day
- S: 1-2 days
- M: 3-5 days
- L: 1-2 weeks
- XL: 2+ weeks
example: "S"
priority:
type: string
description: |
Priority level with rationale. Format: "LEVEL — rationale"
Levels: HIGH, MEDIUM, LOW
example: "HIGH — causes account lockouts and direct user impact"
tags:
type: array
items:
type: string
minItems: 1
maxItems: 3
description: 1-3 suggested labels/categories
example: ["bug", "auth"]
assumptions:
type: array
items:
type: string
description: |
Optional. Open questions or assumptions that should be clarified
before implementation. Only included when genuinely ambiguous.
example:
- "Assumes the issue is frontend input sanitization, not backend validation"
ResponseMeta:
type: object
properties:
requestId:
type: string
format: uuid
description: Unique identifier for this request
model:
type: string
description: AI model used for refinement
example: "claude-3-5-haiku-20241022"
inputTokens:
type: integer
description: Number of input tokens consumed
outputTokens:
type: integer
description: Number of output tokens generated
costUsd:
type: number
format: float
description: Estimated cost in USD for this request
latencyMs:
type: integer
description: Request processing time in milliseconds
promptVersion:
type: string
description: Version of the refinement prompt used
example: "1.0"
tier:
type: string
enum: [free, pro, team]
description: Tier used for this request
DiscoverRequest:
type: object
required:
- item
properties:
item:
type: string
description: Single backlog item text (title + description if available)
example: "Improve the dashboard so users can see their data better"
context:
type: string
description: |
Optional project context to improve classification accuracy.
example: "B2B project management SaaS for engineering teams"
DiscoverResponse:
type: object
properties:
classification:
type: string
enum: [SKIP, LIGHT_DISCOVERY, FULL_DISCOVERY]
description: |
Discovery risk classification:
- SKIP: Item is clear enough to go straight to refinement
- LIGHT_DISCOVERY: Needs 1-2 quick clarifications before refining
- FULL_DISCOVERY: Needs real discovery work before any spec is written
confidence:
type: number
format: float
minimum: 0
maximum: 1
description: Model confidence in the classification (0-1)
rationale:
type: string
description: 1-2 sentences explaining the classification
primary_signal:
type: string
description: The key text pattern that drove the classification decision
questions:
type: array
items:
$ref: "#/components/schemas/DiscoveryQuestion"
description: |
Ranked questions to answer before building.
Free tier: max 1 question. Pro/Team: full set.
assumptions:
type: array
items:
$ref: "#/components/schemas/DiscoveryAssumption"
description: |
Hidden assumptions that must be validated.
Free tier: max 1 assumption. Pro/Team: full set.
_meta:
$ref: "#/components/schemas/ResponseMeta"
DiscoveryQuestion:
type: object
required:
- rank
- question
- category
- why_it_matters
- fastest_validation
properties:
rank:
type: integer
description: Priority rank of this question (1 = most important)
question:
type: string
description: The specific question to answer, referencing the item text
category:
type: string
enum: [outcome, user_job, assumption, feasibility, risk, acceptance_criteria]
description: Category of discovery question
why_it_matters:
type: string
description: One sentence on the failure mode if this question goes unanswered
fastest_validation:
type: string
description: Fastest way to answer this question
example: "1 user conversation"
DiscoveryAssumption:
type: object
required:
- statement
- type
- risk
- simple_test
properties:
statement:
type: string
description: "We assume that [specific belief that must be true]"
example: "We assume that users are failing to find data they need, not that the data is missing"
type:
type: string
enum: [desirability, viability, feasibility]
description: Type of assumption
risk:
type: string
enum: [low, medium, high]
description: Risk level if this assumption is wrong
simple_test:
type: string
description: One sentence on how to validate this assumption quickly
ErrorResponse:
type: object
properties:
error:
type: string
description: Human-readable error message