Guide For Beginners: Add POST /api/v1/contract
Canonical path: docs/howto/0004-how-to-add-post-contract.html (moved from
docs/developer/0004-how-to-add-post-contract.html; the old URL redirects here).
This guide explains what to add, where to add it, and in what order.
The endpoint itself is not implemented here; this is an execution plan.
Goal and scope
Target endpoint:
POST /api/v1/contract
Expected result:
- API route exists,
- schemas and examples are defined,
- business logic is placed in service layer,
- validation and error contracts are aligned,
- tests/documentation/quality checks pass.
Prepare domain model and DB (if needed)
If contract requires new table/columns:
- Add/adjust ORM model in
app/models/core/(for examplecontract.py). - Project uses package-level imports for models (like
from app.models.core import *), make sure to register your new model inapp/models/core/__init__.py. - Generate migration:
make migration name=add_contract_table
- Apply migration:
make migrate
If DB schema does not change, skip migration steps.
Add repository layer
Create repository for persistence operations:
- File:
app/repositories/contract_repository.py
Typical methods:
create(...)get_by_...(...)(if dedup/business checks needed)
Repository rules:
- only data access,
- no HTTP exceptions,
- no FastAPI imports.
Add service layer (business logic)
Create service:
- File:
app/services/contract_service.py
Service responsibilities:
- apply business rules,
- call repository,
- raise business errors with stable
code/keywhen needed.
Error key convention for this entity:
- prefix with entity name, e.g.
CONTRACT_CREATE_* - code format should follow project convention for entity prefix: entity name + number, e.g.
CONTRACT_101.
Add request/response schemas
Create schemas:
- File:
app/schemas/contract.py
Define:
ContractCreateRequestContractCreateResponse
Schema rules:
- validation at API boundary,
- clear field descriptions,
- stable names for OpenAPI.
Add validation mapping for entity
Create validation mapper:
- File:
app/validation/contract.py
Include:
- field/type specific mapping to stable validation codes
- fallback rule for unmapped validation errors
Example naming:
CONTRACT_001,CONTRACT_002, ...- keys like
CONTRACT_CREATE_FIELD_REQUIRED
Then wire mapper in centralized validation entrypoint.
Current project can evolve with one of two options:
- route-based dispatch inside validation builder, or
- a small registry (
endpoint -> mapper) inapp/validation/__init__.py.
Add OpenAPI examples
Add examples:
app/openapi/examples/contracts.py(new)- update
app/openapi/examples/__init__.pyexports
Add:
- request body examples,
- business error examples,
- validation error examples.
Add API router
Create router:
- File:
app/api/v1/contract.py
Router should:
- define
APIRouter(prefix="/contract", tags=["Contract"]), - add
@router.post(""), - use request/response schemas,
- reference OpenAPI examples,
- declare explicit error
responses. - for critical write endpoint, document and enforce
Idempotency-Keybehavior.
Then include router in app:
- update
app/main.pywithapp.include_router(..., prefix="/api/v1").
Add tests
Create tests:
- File:
tests/api/v1/test_contract_create.py
Minimum scenarios:
- success (
201) - business failure (
400) - validation failure (
422) with expected entity-prefixed code/key - idempotent replay: same key + same payload returns same success result
- idempotency conflict: same key + different payload returns conflict
If DB changed, update test fixtures if needed:
tests/conftest.py
Update docs
Run docs sync:
make docs-fix
Run quality gates
Before commit:
make format-fixmake lint-checkmake type-checkmake testmake pre-commit-check
Before PR/deploy:
make verifymake release-check
Final checklist
- [ ] endpoint registered and visible in Swagger
- [ ] schemas and examples are complete
- [ ] business logic isolated in service
- [ ] repository handles persistence only
- [ ] validation mapping exists for
contract - [ ] error keys/codes use
CONTRACT_*prefix - [ ] tests for success + business + validation pass
- [ ] idempotency scenarios are covered for write endpoint
- [ ] docs synced
- [ ] quality gates pass
Page history
| Date | Change | Author |
|---|---|---|
| Added Page history section (repository baseline). | Ivan Boyarkin |