turash/docs/api/proposals.md
Damir Mukimov 000eab4740
Major repository reorganization and missing backend endpoints implementation
Repository Structure:
- Move files from cluttered root directory into organized structure
- Create archive/ for archived data and scraper results
- Create bugulma/ for the complete application (frontend + backend)
- Create data/ for sample datasets and reference materials
- Create docs/ for comprehensive documentation structure
- Create scripts/ for utility scripts and API tools

Backend Implementation:
- Implement 3 missing backend endpoints identified in gap analysis:
  * GET /api/v1/organizations/{id}/matching/direct - Direct symbiosis matches
  * GET /api/v1/users/me/organizations - User organizations
  * POST /api/v1/proposals/{id}/status - Update proposal status
- Add complete proposal domain model, repository, and service layers
- Create database migration for proposals table
- Fix CLI server command registration issue

API Documentation:
- Add comprehensive proposals.md API documentation
- Update README.md with Users and Proposals API sections
- Document all request/response formats, error codes, and business rules

Code Quality:
- Follow existing Go backend architecture patterns
- Add proper error handling and validation
- Match frontend expected response schemas
- Maintain clean separation of concerns (handler -> service -> repository)
2025-11-25 06:01:16 +01:00

6.3 KiB

Proposals API

The Proposals API provides endpoints for managing symbiosis proposals between organizations. Proposals represent requests for resource exchange or collaboration opportunities.

Base URL

https://api.turash.com/api/v1

Endpoints

Get All Proposals

Retrieve all proposals with optional filtering.

Endpoint: GET /api/v1/proposals

Query Parameters:

  • status (optional): Filter by proposal status (pending, accepted, rejected)
  • from_org (optional): Filter by proposing organization ID
  • to_org (optional): Filter by target organization ID
  • limit (optional): Maximum number of results (default: 50)
  • offset (optional): Pagination offset (default: 0)

Response:

[
  {
    "id": "proposal-123",
    "from_org_id": "org-456",
    "to_org_id": "org-789",
    "resource_id": "resource-101",
    "resource_type": "input",
    "resource_name": "Organic Waste",
    "message": "We can provide organic waste for your composting needs",
    "status": "pending",
    "created_at": "2024-01-15T10:30:00Z"
  }
]

Get Proposal by ID

Retrieve a specific proposal by its ID.

Endpoint: GET /api/v1/proposals/{id}

Path Parameters:

  • id: Proposal ID

Response:

{
  "id": "proposal-123",
  "from_org_id": "org-456",
  "to_org_id": "org-789",
  "resource_id": "resource-101",
  "resource_type": "input",
  "resource_name": "Organic Waste",
  "message": "We can provide organic waste for your composting needs",
  "status": "pending",
  "created_at": "2024-01-15T10:30:00Z"
}

Error Responses:

  • 404 Not Found - Proposal not found

Get Proposals by Organization

Retrieve all proposals where an organization is either the sender or receiver.

Endpoint: GET /api/v1/organizations/{id}/proposals

Path Parameters:

  • id: Organization ID

Response:

{
  "incoming": [
    {
      "id": "proposal-123",
      "from_org_id": "org-456",
      "to_org_id": "org-789",
      "resource_id": "resource-101",
      "resource_type": "input",
      "resource_name": "Organic Waste",
      "message": "We can provide organic waste for your composting needs",
      "status": "pending",
      "created_at": "2024-01-15T10:30:00Z"
    }
  ],
  "outgoing": [
    {
      "id": "proposal-124",
      "from_org_id": "org-789",
      "to_org_id": "org-456",
      "resource_id": "resource-102",
      "resource_type": "output",
      "resource_name": "Heat Energy",
      "message": "Interested in your heat recovery system",
      "status": "accepted",
      "created_at": "2024-01-16T14:20:00Z"
    }
  ]
}

Create Proposal

Create a new symbiosis proposal.

Endpoint: POST /api/v1/proposals

Request Body:

{
  "from_org_id": "org-456",
  "to_org_id": "org-789",
  "resource_id": "resource-101",
  "resource_type": "input",
  "resource_name": "Organic Waste",
  "message": "We can provide organic waste for your composting needs"
}

Required Fields:

  • from_org_id: ID of the proposing organization
  • to_org_id: ID of the target organization
  • resource_id: ID of the resource flow being proposed
  • resource_type: Direction of the resource flow (input or output)
  • resource_name: Human-readable name of the resource

Optional Fields:

  • message: Additional message or proposal details

Response:

{
  "id": "proposal-123",
  "from_org_id": "org-456",
  "to_org_id": "org-789",
  "resource_id": "resource-101",
  "resource_type": "input",
  "resource_name": "Organic Waste",
  "message": "We can provide organic waste for your composting needs",
  "status": "pending",
  "created_at": "2024-01-15T10:30:00Z"
}

Error Responses:

  • 400 Bad Request - Invalid request data
  • 404 Not Found - Organization or resource not found

Update Proposal Status

Update the status of an existing proposal.

Endpoint: POST /api/v1/proposals/{id}/status

Path Parameters:

  • id: Proposal ID

Request Body:

{
  "status": "accepted"
}

Valid Status Values:

  • pending - Initial status, awaiting response
  • accepted - Proposal accepted by target organization
  • rejected - Proposal rejected by target organization

Response:

{
  "message": "Proposal status updated successfully"
}

Error Responses:

  • 400 Bad Request - Invalid status value
  • 404 Not Found - Proposal not found

Data Types

Proposal Status

type ProposalStatus = 'pending' | 'accepted' | 'rejected';

Proposal Object

interface Proposal {
  id: string;
  from_org_id: string;
  to_org_id: string;
  resource_id: string;
  resource_type: 'input' | 'output';
  resource_name: string;
  message?: string;
  status: ProposalStatus;
  created_at: string;
}

Business Rules

Proposal Lifecycle

  1. Creation: Proposals are created with pending status
  2. Response: Target organization can accept or reject the proposal
  3. Final State: Once accepted or rejected, status cannot be changed

Validation Rules

  • Organizations cannot propose to themselves
  • Resource must exist and be owned by the proposing organization
  • Resource type must match the direction being proposed
  • Message length limited to 500 characters

Permissions

Currently, all proposal operations are publicly accessible. Future implementations will include:

  • Authentication requirements
  • Authorization based on organization membership
  • Proposal creation limits per organization

Error Codes

Code Description
VALIDATION_ERROR Request data validation failed
PROPOSAL_NOT_FOUND Specified proposal does not exist
ORGANIZATION_NOT_FOUND Specified organization does not exist
RESOURCE_NOT_FOUND Specified resource does not exist
INVALID_STATUS_TRANSITION Attempted invalid status change
SELF_PROPOSAL_ERROR Organization cannot propose to itself

Rate Limits

  • Create Proposal: 10 per hour per organization
  • Update Status: 50 per hour per organization
  • Get Operations: 100 per hour per IP

WebSocket Events

The API emits WebSocket events for real-time proposal updates:

  • proposal_created: New proposal submitted
  • proposal_status_changed: Proposal status updated

Event Payload:

{
  "type": "proposal_status_changed",
  "proposal_id": "proposal-123",
  "old_status": "pending",
  "new_status": "accepted",
  "updated_by": "org-789",
  "timestamp": "2024-01-15T10:35:00Z"
}