Skip to content

Tutorial: Create a New Contract

This tutorial shows how to create a new contract using the public API wrapper in People Cloud. The public endpoint forwards the request to the internal contract creation logic, preserving platform behaviour such as notifications and validations.


Step 1: Make a POST Request to create a Contract

Send a POST request to the following public API endpoint:

POST /api/v1/contracts/new

Authorization

This endpoint requires authentication. Use a Bearer token from an authenticated user.

Request Headers

Authorization: Bearer <your_token_here>
Accept: application/json
Content-Type: application/json

Request Body Structure

Below are the commonly used fields accepted by the contract creation endpoint. Many fields are optional but some (contract id, client/vendor/company info, start date or is_infinite, price) are typically required by your business rules.

  • the_contract_id: Public contract id string.
  • client_contract_id: Optional client-side id/reference.
  • status: Contract status. Must be one of the following values exactly:
  • "not started"
  • "ongoing"
  • "ended"
  • "unknown"

Any other value will be rejected with a 422 Validation error.

  • service_code: Internal service code identifier.
  • contract_start: ISO date of contract start (e.g. 2026-01-22).
  • contract_end: ISO date of contract end or empty if is_infinite.
  • is_infinite: Boolean, whether the contract is open-ended.
  • type: Contract billing type (e.g. hourly, fixed).
  • work_scope: Free text describing the scope of work.
  • notice_period: Text describing notice (e.g. 14 days).
  • allocation: Numeric or string allocation percent (e.g. 100).
  • max_hours: Maximum hours per period (integer).
  • client_price: Price charged to client (decimal/string).
  • vendor_price: Price paid to vendor/consultant (decimal/string).
  • vat: VAT percentage (float).
  • seller_id: Internal user id who is the seller.
  • hour_report: Reporting frequency (e.g. weekly).
  • invoicing_channel: How invoices are sent (e.g. email).
  • client_company_id: Required. Numeric ID of an existing client company in the database.
  • client_business_id: Company business id / VAT id (optional).
  • unit: Unit text (e.g. hours).
  • client_contact: Client contact name or email.
  • client_purchase_order: Purchase order string.
  • vendor_company_id: Required. Numeric ID of an existing vendor company in the database.
  • vendor_company_for_client: Vendor representation for client view (string or id).
  • vendor_contact: Vendor contact name/email.
  • notes: Free text notes.
  • selected_consultant: Object describing the consultant assigned to the contract. If present, the API will either update an existing consultant (when id provided) or create a new consultant when name is provided: { "id": null, "name": "Bob", "title": "Senior Developer" }.
  • consult_skills: Array of skill strings (e.g. ["PHP","Laravel","SQL"]) or a comma separated string; the public wrapper normalizes this.

Example JSON

{
  "the_contract_id":"CNTR-2026-0005",
  "client_contract_id":"CL-5555",
  "status":"ongoing",
  "service_code":"SVC-01",
  "contract_start":"2026-01-22",
  "contract_end":"",
  "is_infinite":true,
  "type":"hourly",
  "work_scope":"Development and consulting",
  "notice_period":"14 days",
  "allocation":100,
  "max_hours":160,
  "client_price":120.50,
  "vendor_price":95.00,
  "vat":24.0,
  "seller_id":3,
  "hour_report":"weekly",
  "invoicing_channel":"email",
  "client_company_id":2,
  "client_business_id":"FI12345678",
  "unit":"hours",
  "client_contact":"John Doe",
  "client_purchase_order":"PO-9876",
  "vendor_company_id":10,
  "vendor_company_for_client":45,
  "vendor_contact":"Vendor Contact Name",
  "notes":"Created via API - test contract",
  "selected_consultant":{"id":null,"name":"Bob","title":"Senior Developer"},
  "consult_skills":["PHP","Laravel","SQL"]
}

Step 2: Create the Contract (cURL example)

curl -X POST 'https://your-domain.com/api/v1/contracts/new' \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "the_contract_id":"CNTR-2026-0005",
    "client_contract_id":"CL-5555",
    "status":"ongoing",
    "service_code":"SVC-01",
    "contract_start":"2026-01-22",
    "contract_end":"",
    "is_infinite":true,
    "type":"hourly",
    "work_scope":"Development and consulting",
    "notice_period":"14 days",
    "allocation":100,
    "max_hours":160,
    "client_price":120.50,
    "vendor_price":95.00,
    "vat":24.0,
    "seller_id":3,
    "hour_report":"weekly",
    "invoicing_channel":"email",
    "client_company_id":2,
    "client_business_id":"FI12345678",
    "unit":"hours",
    "client_contact":"John Doe",
    "client_purchase_order":"PO-9876",
    "vendor_company_id":10,
    "vendor_company_for_client":45,
    "vendor_contact":"Vendor Contact Name",
    "notes":"Created via API - test contract",
    "selected_consultant":{"id":null,"name":"Bob","title":"Senior Developer"},
    "consult_skills":["PHP","Laravel","SQL"]
  }'

Step 3: Evaluate response

If successful, the API returns a JSON response with a success message. The public wrapper may return a short message such as {"message":"Contract created successfully"}.

Status Meaning Description
200 OK Contract created successfully
201 Created Contract created (alternate success code)
401 Unauthorized The API token is invalid or missing
422 Validation error One or more fields failed validation
500 Server error Unexpected server-side error

Notes & Tips

  • You must know the company IDs before making the request. client_company_id and vendor_company_id are required and must be numeric IDs of companies that already exist in the database. The API does not resolve or create companies by name — submitting an unknown ID will return a 422 error. Use the GET /api/v1/companies endpoint to look up available company IDs.
  • Provide selected_consultant when you want the API to create or update a consultant record and attach it to the contract.
  • If you provide only partial contract data when editing later, ensure selected_consultant or consult_skills are preserved to avoid clearing consultant fields (the public wrappers try to preserve existing consultant info when omitted).