Skip to content

SDD Flow Simulation (API Only)

This article simulates the specification-driven development flow when requirements come from external API integration without involving UI/UX. Such requirements typically include: third-party system integration, partner APIs, webhook receivers, internal service-to-service communication, etc.

Participants

RoleResponsibilityPrimary Tools
PMRequirements definition, acceptance criteria, partner communicationOpenSpec proposal
BEAPI design, backend implementation reviewOpenAPI + Claude Code
ADMFlow orchestration, quality gates, cross-role coordinationOpenSpec + Claude Code
AgentSpec generation, code implementationClaude Code
QATest strategy, API testing, integration testingTest framework + Claude Code

Note: In the API-only flow, UX and FE roles do not participate. The flow is streamlined, focusing on API contract design and backend implementation.

Scenario

Feature Request: Provide a Partner Inventory Sync API that allows partner systems to query product inventory status in real-time and receive inventory change notifications.

Phase 1: Requirement Seed (PM)

Context

PM receives API integration requirements from partners or business units and creates a requirement seed document. External API requirements typically have explicit technical specifications.

PM (Alice): collects partner requirements and writes seed document

"Partner TechMart needs a real-time inventory sync API for their e-commerce platform. I've drafted the requirement seed."

markdown
<!-- requirements/partner-inventory-api.md -->
---
title: Partner Inventory Sync API
author: PM-Alice
created: 2026-04-15
status: seed
requester: TechMart Inc.
type: external-api
---

# Partner Inventory Sync API

## Business Context
Partner TechMart needs to sync our product inventory in real-time to avoid overselling and inventory inconsistencies. This is a core requirement for the Q2 partner program.

### Problem Statement
- TechMart currently syncs inventory via daily FTP file transfers, causing overselling issues due to poor timeliness
- Past 3 months: 47 order cancellations and 23 customer complaints due to inventory sync issues
- TechMart is our 3rd largest sales channel with ~$2.5M monthly sales

### Expected Benefits
- Eliminate overselling: Expected to reduce order cancellation rate from 2.3% to 0.1%
- Improve partner satisfaction: TechMart commits to 20% more product listings after API launch
- Establish standardized partner integration pattern: Can be quickly replicated for other partners

## Partner Information
- Company: TechMart Inc.
- Technical Contact: John Smith (john.smith@techmart.com)
- System Environment: Java 17, Spring Boot
- Expected Traffic: Peak ~500-800 queries per minute

## User Scenarios

### Scenario 1: Real-time Inventory Query
When TechMart's product page loads, their system calls our API to query current inventory quantity and displays "In Stock" or "Out of Stock" status to consumers.

### Scenario 2: Batch Inventory Sync
TechMart runs hourly scheduled tasks to batch query inventory status for all listed products (~5,000 items) and updates their internal database.

### Scenario 3: Real-time Inventory Change Notification
When our warehouse shipment causes a product's inventory to fall below safety threshold (10 units), the system sends Webhook notification to TechMart, who can immediately display "Almost sold out" message.

### Scenario 4: Out of Stock Notification
When product inventory reaches zero, system sends Webhook notification to TechMart, who automatically marks the product as "Temporarily out of stock".

### Scenario 5: Webhook Delivery Failure
TechMart's Webhook endpoint is temporarily unreachable. Our system automatically retries with exponential backoff, up to 5 attempts. If still failing, log the event and send alert email to TechMart's technical contact.

## Business Rules
- Inventory quantities are real-time data with update delay not exceeding 30 seconds
- Inventory status categories: in_stock (>10), low_stock (1-10), out_of_stock (0)
- Each partner is assigned a unique API Key
- Rate limits set by partner tier (TechMart is Premium: 1000 req/min)

## Acceptance Criteria
- [ ] API uses API Key authentication (Header: X-API-Key)
- [ ] Single query supports up to 100 products
- [ ] Response time < 200ms (P95)
- [ ] Webhook sent within 5 seconds of inventory change
- [ ] Webhook retry mechanism: exponential backoff, max 5 attempts
- [ ] Provide sandbox environment for integration testing
- [ ] Provide complete OpenAPI 3.0 specification document

## Out of Scope (Not in This Release)
- Price sync API
- Order sync API
- Product info sync API
- Multi-warehouse inventory query (total inventory only)

PM (Alice): "I've submitted the seed for team review."

Key Point

External API requirements typically have explicit technical constraints and SLA requirements. PM needs to confirm these details with partners and clearly document them in the seed.

Phase 2: Seed Review Meeting (ADM + BE + QA)

Context

The API-only flow's seed review meeting is streamlined to ADM, BE, and QA participation. Focus is on API design feasibility and test strategy.

ADM (Frank): opens seed review meeting

"Team, let's begin the seed review for the partner inventory API. This is a pure API requirement, no UI involved."

BE (Bob):

"200ms P95 response time is challenging. Batch querying 100 products needs a caching strategy. Also, the Webhook retry mechanism needs clear definition."

QA (Eve):

"Need to confirm how Webhook idempotency will be verified. Also, what's the specific rate limit value?"

PM (Alice):

"I confirmed the rate limit with TechMart - they estimate maximum 1000 requests per minute. Webhook idempotency is implemented via event_id."

ADM (Frank): raises relationship with existing features

"Wait, we already have an internal inventory query API for the frontend. What's the relationship between this partner API and the existing API?"

BE (Bob):

"The existing internal API is /api/v1/products/{id}/stock - single item query, no batch capability, no authentication. We have several options:

  1. Extend existing API with batch and authentication
  2. Build separate partner API layer
  3. Refactor existing API to unify internal and external use"

PM (Alice):

"Considering partners have different SLA requirements and rate limits, I suggest option 2 - build a separate partner API layer. But the underlying inventory service can be shared."

ADM (Frank):

"In that case, we need to confirm: does the existing internal API need changes? Should we consider unifying them in the future? These might be out of scope."

QA (Eve):

"If the underlying inventory service is shared, performance testing needs to consider scenarios where internal and external APIs are used simultaneously."

ADM (Frank): summarizes meeting findings

"Good. Alice, please update the seed with rate limit, idempotency details, and the relationship with existing internal API. Bob, please evaluate the shared inventory service approach."

PM (Alice): updates seed based on meeting feedback

markdown
<!-- requirements/partner-inventory-api.md (updated after review) -->
---
title: Partner Inventory Sync API
author: PM-Alice
created: 2026-04-15
status: seed
reviewed: 2026-04-16
requester: TechMart Inc.
type: external-api
---

# Partner Inventory Sync API

## Business Context
Partner TechMart needs to sync our product inventory in real-time to avoid overselling and inventory inconsistencies.

### Problem Statement
- TechMart currently syncs inventory via daily FTP file transfers, causing overselling issues due to poor timeliness
- Past 3 months: 47 order cancellations and 23 customer complaints due to inventory sync issues
- TechMart is our 3rd largest sales channel with ~$2.5M monthly sales

### Expected Benefits
- Eliminate overselling: Expected to reduce order cancellation rate from 2.3% to 0.1%
- Improve partner satisfaction: TechMart commits to 20% more product listings after API launch
- Establish standardized partner integration pattern: Can be quickly replicated for other partners

## Partner Information
- Company: TechMart Inc.
- Technical Contact: John Smith (john.smith@techmart.com)
- System Environment: Java 17, Spring Boot
- Expected Traffic: Peak ~500-800 queries per minute

## User Scenarios

### Scenario 1: Real-time Inventory Query
When TechMart's product page loads, their system calls our API to query current inventory quantity and displays "In Stock" or "Out of Stock" status to consumers.

### Scenario 2: Batch Inventory Sync
TechMart runs hourly scheduled tasks to batch query inventory status for all listed products (~5,000 items) and updates their internal database.

### Scenario 3: Real-time Inventory Change Notification
When our warehouse shipment causes a product's inventory to fall below safety threshold (10 units), the system sends Webhook notification to TechMart, who can immediately display "Almost sold out" message.

### Scenario 4: Out of Stock Notification
When product inventory reaches zero, system sends Webhook notification to TechMart, who automatically marks the product as "Temporarily out of stock".

### Scenario 5: Webhook Delivery Failure
TechMart's Webhook endpoint is temporarily unreachable. Our system automatically retries with exponential backoff, up to 5 attempts. If still failing, log the event and send alert email to TechMart's technical contact.

## Business Rules
- Inventory quantities are real-time data with update delay not exceeding 30 seconds
- Inventory status categories: in_stock (>10), low_stock (1-10), out_of_stock (0)
- Each partner is assigned a unique API Key
- Rate limits set by partner tier (TechMart is Premium: 1000 req/min)
- Webhook idempotency ensured via event_id

## Acceptance Criteria
- [ ] API uses API Key authentication (Header: X-API-Key)
- [ ] Single query supports up to 100 products
- [ ] Response time < 200ms (P95)
- [ ] Webhook sent within 5 seconds of inventory change
- [ ] Rate limit: 1000 requests/min per API Key
- [ ] Webhook idempotency via event_id
- [ ] Webhook failure retry: exponential backoff, max 5 attempts
- [ ] Provide sandbox environment for integration testing

## Relationship with Existing Features
- Existing feature: Internal inventory query API (`/api/v1/products/{id}/stock`, single query, no auth)
- Decision: Build separate partner API layer, share underlying inventory service
- Out-of-scope consideration: May unify internal and external APIs in future

## Out of Scope (Not in This Release)
- Price sync API
- Order sync API
- Product info sync API
- Multi-warehouse inventory query (total inventory only)

## Open Questions (for refinement)
- Cache strategy selection (Redis vs. local cache)
- Webhook signature verification mechanism
- Performance impact assessment of shared inventory service

Key Point

API-only flow reviews focus more on technical feasibility, performance requirements, and test strategy. ADM ensures the team considers relationship with existing APIs, deciding whether to extend, build separately, or refactor for unification. BE and QA input is crucial for API design.

Phase 2 Artifacts:

ArtifactLocationOwner
Updated seed documentrequirements/partner-inventory-api.mdPM

Phase 3: Proposal Generation & Review (PM + ADM + BE + QA)

Context

PM uses the seed as input to generate a proposal. Team reviews line by line and modifies in real-time.

3.1 PM Generates Proposal

PM (Alice): opens Claude Code

bash
claude "Based on requirements/partner-inventory-api.md seed document,
use /openspec:proposal to generate a formal proposal"

Agent: generates proposal draft

markdown
<!-- openspec/changes/partner-inventory-api/proposal.md -->
---
id: partner-inventory-api
title: Partner Inventory Sync API
status: draft
owner: PM-Alice
created: 2026-04-16
type: external-api
---

# Partner Inventory Sync API

## Overview
Provide inventory sync API for partners, including query endpoints and Webhook notification mechanism.

## Change Scope

### Backend Changes
| File | Change Type | Description |
|------|-------------|-------------|
| `services/partner-api/` | New | Partner API service |
| `api/partner-inventory.yaml` | New | OpenAPI specification |
| `services/webhook/` | Modify | Add inventory change events |

### Infrastructure Changes
| Item | Change Type | Description |
|------|-------------|-------------|
| Redis cache | New | Inventory query cache layer |
| API Gateway | Modify | Add rate limiting rules |

## Acceptance Criteria
(Inherited from seed document)

3.2 Team Line-by-Line Proposal Review

ADM (Frank): opens proposal review meeting, projects proposal content

"Team, let's review the proposal line by line. We'll have Agent make changes in real-time."

ADM (Frank): "Let's start with the 'Overview' section..."

PM (Alice):

"Overview needs to include partner name and business value."

ADM (Frank): asks Agent to modify in real-time

bash
claude "Update proposal overview, add:
- Partner: TechMart Inc.
- Business value: Q2 partner program core requirement, expected 15% order growth"

ADM (Frank): "Moving to 'Change Scope'..."

BE (Bob):

"Caching strategy should use Redis Cluster, need to add architectural decision notes. Also, Webhook service needs signature verification mechanism."

ADM (Frank): asks Agent to modify in real-time

bash
claude "Update proposal:
1. Add Redis Cluster architectural decision to infrastructure changes
2. Add HMAC-SHA256 signature verification mechanism for Webhook service"

QA (Eve):

"Need to add a test strategy section, including performance testing and integration testing plans. Also, since we're sharing the underlying inventory service, performance testing should include concurrent internal and external API scenarios."

ADM (Frank): "There's one more key point: the relationship with existing internal API."

BE (Bob):

"We decided to build a separate partner API layer but share the underlying inventory service. The proposal needs to explain this architectural decision and the impact on existing internal API."

PM (Alice):

"The existing internal API doesn't need changes right now. But long-term, we may unify internal and external APIs. This should be listed as an out-of-scope future consideration."

ADM (Frank): "Good, let's record all of this."

ADM (Frank): asks Agent to modify in real-time

bash
claude "Update proposal:
1. Add test strategy section:
   - Performance testing: Verify 200ms P95 response time
   - Concurrency testing: Internal and external API simultaneous use scenarios
   - Integration testing: Webhook end-to-end verification
   - Sandbox environment: Isolated test dataset
2. Add Relationship with Existing Features section:
   - Existing feature: Internal inventory query API (no changes)
   - Architectural decision: Separate partner API layer, shared underlying inventory service
   - Out-of-scope future consideration: May unify internal and external APIs"

Agent: updates all specifications

ADM (Frank): "Proposal update complete. Everyone confirm the final version..."

Key Point

API-only proposal review focuses on architectural decisions, performance guarantees, and test strategy. Review must confirm relationship with existing APIs: whether to extend, build separately, or share underlying services. Out-of-scope future considerations should also be recorded for future planning.

Phase 3 Artifacts:

ArtifactLocationOwner
OpenSpec proposalopenspec/changes/partner-inventory-api/proposal.mdPM + Agent

Phase 4: API First Design (BE + Agent + Team Review)

Context

This is the core phase of the API-only flow. BE designs the complete OpenAPI specification, including authentication, error handling, and Webhook specs.

4.1 BE Generates API Spec

BE (Bob): opens Claude Code

bash
claude "Based on openspec/changes/partner-inventory-api/proposal.md,
create complete OpenAPI 3.0 specification including:
- GET /partner/v1/inventory (batch query)
- POST /partner/v1/webhooks (register Webhook)
- DELETE /partner/v1/webhooks/{id} (unregister)
- Webhook payload specification
- Authentication and rate limiting documentation
- Error response definitions"

Agent: generates OpenAPI specification

yaml
# specs/api/partner-inventory-api.yaml
openapi: 3.0.3
info:
  title: Partner Inventory API
  version: 1.0.0
  description: |
    Partner Inventory Sync API

    ## Authentication
    All requests require `X-API-Key` header

    ## Rate Limiting
    - 1000 requests/min per API Key
    - Exceeding limit returns 429 Too Many Requests

    ## Webhook Signature
    Webhook requests include `X-Signature` header using HMAC-SHA256

servers:
  - url: https://api.example.com
    description: Production
  - url: https://sandbox-api.example.com
    description: Sandbox

security:
  - ApiKeyAuth: []

paths:
  /partner/v1/inventory:
    post:
      summary: Batch query inventory
      operationId: batchGetInventory
      description: Query inventory status for multiple products, up to 100 products
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - product_ids
              properties:
                product_ids:
                  type: array
                  items:
                    type: string
                  maxItems: 100
                  example: ["SKU001", "SKU002", "SKU003"]
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InventoryResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /partner/v1/webhooks:
    post:
      summary: Register Webhook
      operationId: registerWebhook
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookRegistration'
      responses:
        '201':
          description: Registration successful
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookResponse'

  /partner/v1/webhooks/{webhookId}:
    delete:
      summary: Unregister Webhook
      operationId: unregisterWebhook
      parameters:
        - name: webhookId
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: Unregistered successfully

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

  schemas:
    InventoryResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/InventoryItem'
        timestamp:
          type: string
          format: date-time

    InventoryItem:
      type: object
      properties:
        product_id:
          type: string
        quantity:
          type: integer
        status:
          type: string
          enum: [in_stock, low_stock, out_of_stock]
        updated_at:
          type: string
          format: date-time

    WebhookRegistration:
      type: object
      required:
        - url
        - events
      properties:
        url:
          type: string
          format: uri
        events:
          type: array
          items:
            type: string
            enum: [inventory.updated, inventory.low_stock, inventory.out_of_stock]
        secret:
          type: string
          description: Secret key for signature verification

    WebhookPayload:
      type: object
      properties:
        event_id:
          type: string
          format: uuid
          description: Idempotency identifier
        event_type:
          type: string
        timestamp:
          type: string
          format: date-time
        data:
          $ref: '#/components/schemas/InventoryItem'

  responses:
    BadRequest:
      description: Invalid request format
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Authentication failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    RateLimited:
      description: Rate limit exceeded
      headers:
        Retry-After:
          schema:
            type: integer
          description: Recommended retry wait time in seconds
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    Error:
      type: object
      properties:
        code:
          type: string
        message:
          type: string
        request_id:
          type: string

4.2 Submit to API Management Platform

BE (Bob): submits API spec

bash
git add specs/api/partner-inventory-api.yaml
git commit -m "feat(api): add partner inventory API specification"
git push origin feature/partner-inventory-api

4.3 Team Line-by-Line API Spec Review

ADM (Frank): opens API review meeting, projects API spec

"Team, let's review the partner inventory API spec line by line."

ADM (Frank): "Let's start with authentication and rate limiting documentation..."

PM (Alice):

"Documentation is clear. But we need to add the API Key application process."

ADM (Frank): asks Agent to modify in real-time

bash
claude "Add API Key application process to info.description"

ADM (Frank): "Moving to batch query endpoint..."

QA (Eve):

"The maxItems: 100 validation error message needs definition. What's returned when exceeding 100 products?"

ADM (Frank): asks Agent to modify in real-time

bash
claude "Add example to BadRequest response,
explaining error message format when exceeding 100 products"

BE (Bob):

"Webhook payload is missing retry_count field. Partners need to know which retry attempt this is."

ADM (Frank): asks Agent to modify in real-time

bash
claude "Add retry_count field to WebhookPayload,
type: integer, description: retry count, 0 means first send"

Agent: updates all specifications

ADM (Frank): "API spec update complete. Everyone confirm..."

BE (Bob): confirms and merges

bash
git commit -m "feat(api): finalize partner inventory API after review"
git push && gh pr merge --squash

Key Point

External API specs need special attention to authentication mechanisms, error handling, and rate limiting documentation. These are crucial for partner integration.

Phase 4 Artifacts:

ArtifactLocationOwner
OpenAPI specificationspecs/api/partner-inventory-api.yamlBE + Agent

Phase 5: Implementation (Agent + BE Review)

Context

API-only flow has only backend implementation, no frontend. Focus is on API implementation conforming to specs and performance requirements.

5.1 Backend Implementation

ADM (Frank): "Bob, API spec is approved. Please guide the Agent for implementation."

BE (Bob): opens Claude Code

bash
claude "Based on openspec/changes/partner-inventory-api/proposal.md
and specs/api/partner-inventory-api.yaml
use /openspec:apply to implement backend API"

Agent: generates backend implementation

typescript
// services/partner-api/inventory.controller.ts
import { Controller, Post, Body, UseGuards } from '@nestjs/common';
import { ApiKeyGuard } from '@/guards/api-key.guard';
import { RateLimitGuard } from '@/guards/rate-limit.guard';
import { InventoryService } from './inventory.service';
import { BatchInventoryDto } from './dto/batch-inventory.dto';

@Controller('partner/v1')
@UseGuards(ApiKeyGuard, RateLimitGuard)
export class InventoryController {
  constructor(private readonly inventoryService: InventoryService) {}

  @Post('inventory')
  async batchGetInventory(@Body() dto: BatchInventoryDto) {
    if (dto.product_ids.length > 100) {
      throw new BadRequestException({
        code: 'BATCH_SIZE_EXCEEDED',
        message: 'Maximum 100 products per request',
      });
    }

    const items = await this.inventoryService.batchGet(dto.product_ids);

    return {
      items,
      timestamp: new Date().toISOString(),
    };
  }
}
typescript
// services/partner-api/inventory.service.ts
import { Injectable } from '@nestjs/common';
import { RedisService } from '@/services/redis.service';
import { InventoryRepository } from './inventory.repository';

@Injectable()
export class InventoryService {
  private readonly CACHE_TTL = 30; // 30 seconds

  constructor(
    private readonly redis: RedisService,
    private readonly repository: InventoryRepository,
  ) {}

  async batchGet(productIds: string[]) {
    const cached = await this.redis.mget(
      productIds.map(id => `inventory:${id}`)
    );

    const missingIds = productIds.filter((_, i) => !cached[i]);

    if (missingIds.length > 0) {
      const fresh = await this.repository.findByIds(missingIds);

      // Cache the fresh data
      const pipeline = this.redis.pipeline();
      fresh.forEach(item => {
        pipeline.setex(
          `inventory:${item.product_id}`,
          this.CACHE_TTL,
          JSON.stringify(item)
        );
      });
      await pipeline.exec();
    }

    return this.mergeResults(productIds, cached, missingIds);
  }
}

5.2 BE Review

BE (Bob): reviews Agent's generated code

"Let me check the implementation... API parameter validation is correct, caching logic uses Redis pipeline for batch optimization, meets performance requirements. But I notice there's no Circuit Breaker pattern - we need fallback handling when Redis is unavailable."

BE (Bob): asks Agent to add

bash
claude "Add Circuit Breaker pattern,
fallback to direct database query when Redis unavailable,
and add health check endpoint"

BE (Bob): "Core implementation conforms to API spec. Approved for merge after Circuit Breaker addition."

Key Point

API-only implementation review focuses on performance optimization, error handling, and reliability design. External APIs require higher stability standards.

Phase 5 Artifacts:

ArtifactLocationOwner
Backend codeservices/partner-api/Agent + BE

Phase 6: Testing (QA + Agent)

Context

API-only flow testing focuses on API contract testing, performance testing, and integration testing.

6.1 QA Requests Agent to Generate Tests

ADM (Frank): "Eve, implementation is complete. Please generate API tests."

QA (Eve): opens Claude Code

bash
claude "Based on specs/api/partner-inventory-api.yaml
generate the following tests:
1. API contract tests (verify responses match OpenAPI spec)
2. Performance tests (verify 200ms P95)
3. Webhook integration tests"

Agent: generates test cases

typescript
// tests/api/partner-inventory.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Partner Inventory API', () => {
  const API_KEY = process.env.TEST_API_KEY;
  const BASE_URL = process.env.API_BASE_URL;

  test('batch inventory query returns correct format', async ({ request }) => {
    const response = await request.post(`${BASE_URL}/partner/v1/inventory`, {
      headers: { 'X-API-Key': API_KEY },
      data: { product_ids: ['SKU001', 'SKU002'] },
    });

    expect(response.status()).toBe(200);

    const body = await response.json();
    expect(body).toHaveProperty('items');
    expect(body).toHaveProperty('timestamp');
    expect(body.items[0]).toHaveProperty('product_id');
    expect(body.items[0]).toHaveProperty('quantity');
    expect(body.items[0]).toHaveProperty('status');
  });

  test('rejects requests exceeding 100 products', async ({ request }) => {
    const productIds = Array.from({ length: 101 }, (_, i) => `SKU${i}`);

    const response = await request.post(`${BASE_URL}/partner/v1/inventory`, {
      headers: { 'X-API-Key': API_KEY },
      data: { product_ids: productIds },
    });

    expect(response.status()).toBe(400);

    const body = await response.json();
    expect(body.code).toBe('BATCH_SIZE_EXCEEDED');
  });

  test('returns 401 without API key', async ({ request }) => {
    const response = await request.post(`${BASE_URL}/partner/v1/inventory`, {
      data: { product_ids: ['SKU001'] },
    });

    expect(response.status()).toBe(401);
  });

  test('returns 429 when rate limited', async ({ request }) => {
    // Send requests until rate limited
    const requests = Array.from({ length: 1100 }, () =>
      request.post(`${BASE_URL}/partner/v1/inventory`, {
        headers: { 'X-API-Key': API_KEY },
        data: { product_ids: ['SKU001'] },
      })
    );

    const responses = await Promise.all(requests);
    const rateLimited = responses.filter(r => r.status() === 429);

    expect(rateLimited.length).toBeGreaterThan(0);
  });
});
typescript
// tests/performance/inventory-load.spec.ts
import { check } from 'k6';
import http from 'k6/http';

export const options = {
  stages: [
    { duration: '30s', target: 100 },
    { duration: '1m', target: 100 },
    { duration: '30s', target: 0 },
  ],
  thresholds: {
    http_req_duration: ['p(95)<200'], // 200ms P95
  },
};

export default function () {
  const response = http.post(
    `${__ENV.API_BASE_URL}/partner/v1/inventory`,
    JSON.stringify({ product_ids: ['SKU001', 'SKU002', 'SKU003'] }),
    {
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': __ENV.API_KEY,
      },
    }
  );

  check(response, {
    'status is 200': (r) => r.status === 200,
    'response time < 200ms': (r) => r.timings.duration < 200,
  });
}

6.2 QA Executes Tests

QA (Eve): "Running API tests and performance tests..."

bash
# API contract tests
npx playwright test tests/api/partner-inventory.spec.ts

# Results
Running 4 tests using 1 worker
 batch inventory query returns correct format (0.8s)
 rejects requests exceeding 100 products (0.3s)
 returns 401 without API key (0.2s)
 returns 429 when rate limited (5.2s)

4 passed (6.5s)

# Performance tests
k6 run tests/performance/inventory-load.spec.ts

# Results
 http_req_duration.............: avg=45ms  p(95)=156ms
 checks.......................: 100.00%

QA (Eve): "All tests pass. P95 response time is 156ms, meeting the 200ms requirement."

Key Point

External API testing needs to verify contract conformance, performance SLAs, and error handling. Performance tests should run in production-like environments.

Phase 6 Artifacts:

ArtifactLocationOwner
API test casestests/api/partner-inventory.spec.tsAgent + QA
Performance test casestests/performance/inventory-load.spec.tsAgent + QA
Test reportsCI/CD SystemQA

Phase 7: Archive (PM + ADM + Agent)

Context

After successful deployment, the proposal is archived and API documentation is published to partners.

7.1 PM Requests Archive

PM (Alice): "API is deployed and passed all tests. Ready to archive and notify partner."

bash
claude "Partner Inventory API passed all tests and deployed,
use /openspec:archive to archive this change,
and generate partner integration documentation"

7.2 Agent Executes Archive

Agent: executes archive flow

bash
# Agent executes archive flow
1. Update proposal status to archived
2. Merge API spec to specs/ directory
3. Generate partner integration guide
4. Update CHANGELOG.md
5. Create git tag

ADM (Frank): "Archive complete. Alice, please send the integration documentation and sandbox credentials to TechMart."

PM (Alice): "Got it. I'll schedule an integration meeting with TechMart."

Phase 7 Artifacts:

ArtifactLocationOwner
Archived proposalopenspec/archive/partner-inventory-api/Agent
Merged specificationsspecs/ directoryAgent
Partner integration guidedocs/partner/Agent
CHANGELOG updateCHANGELOG.mdAgent

Complete Artifact List

PhaseArtifactLocationOwner
1Requirement seed documentrequirements/PM
2Updated seed documentrequirements/PM
3OpenSpec proposalopenspec/changes/PM + Agent
4OpenAPI specificationspecs/api/BE + Agent
5Backend codeservices/Agent + BE
6API test casestests/api/Agent + QA
6Performance test casestests/performance/Agent + QA
7Archived proposalopenspec/archive/Agent
7Partner integration guidedocs/partner/Agent
7Merged specificationsspecs/Agent

Flow Summary

Differences from Full SDD Flow

AspectFull SDD FlowAPI-Only Flow
Participating RolesPM, UX, BE, FE, ADM, QAPM, BE, ADM, QA
Number of Phases8 phases7 phases (skip UX design)
Design OutputsOpenAPI + UX specsOpenAPI only
Implementation ScopeBackend + FrontendBackend only
Testing FocusE2E + PerformanceAPI contract + Performance
Additional ConsiderationsUI/UX consistencyExternal integration, SLA, documentation