{"openapi":"3.0.3","info":{"title":"Folkyn API","version":"1.0.0","license":{"name":"Proprietary","url":"https://folkyn.com"},"description":"Team API key; responses in `data`, errors in `error` with `X-Request-Id`. Spec at `/api/v1/openapi.yaml` and `/api/v1/openapi.json` (no key). **60 requests/minute** per key on `/api/v1/*`."},"servers":[{"url":"https://api.folkyn.com","description":"Production"}],"tags":[{"name":"Specification","description":"OpenAPI document download (no authentication)"},{"name":"Project codes","description":"Team project codes"},{"name":"Team tags","description":"Team tags"},{"name":"Teams","description":"Organizational teams (team units) and member lists"},{"name":"Missions","description":"Team missions"},{"name":"Freelancers","description":"Team freelancers and invitations"},{"name":"Activity reports","description":"Activity reports (CRA)"},{"name":"Accounting","description":"Accounting entries"}],"security":[{"bearerAuth":[]},{"ApiKeyHeader":[]}],"paths":{"/api/v1/openapi.yaml":{"get":{"operationId":"getOpenApiYaml","summary":"Download OpenAPI specification (YAML)","description":"Returns the OpenAPI 3 document as YAML (no authentication).","tags":["Specification"],"security":[],"responses":{"200":{"description":"OpenAPI 3.0 document","content":{"text/yaml":{"schema":{"type":"string"}}}},"404":{"description":"Specification file missing on server","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Invalid or unreadable specification","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/openapi.json":{"get":{"operationId":"getOpenApiJson","summary":"Download OpenAPI specification (JSON)","description":"Returns the OpenAPI 3 document as JSON (no authentication; body is the spec root, not wrapped in `data`).","tags":["Specification"],"security":[],"responses":{"200":{"description":"OpenAPI 3.0 document as JSON object","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"404":{"description":"Specification file missing on server","content":{"text/plain":{"schema":{"type":"string"}}}},"500":{"description":"Invalid or unreadable specification","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/project-codes":{"get":{"operationId":"listProjectCodes","summary":"List Project Codes","description":"Lists team project codes for the API key's team.","tags":["Project codes"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedProjectCodes"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createProjectCode","summary":"Create Project Code","description":"Creates a team project code.","tags":["Project codes"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"external_id":{"type":"string","nullable":true}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProjectCodeCreated"}}}}}},"400":{"$ref":"#/components/responses/PublicError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/project-codes/{id}":{"get":{"operationId":"getProjectCode","summary":"Retrieve Project Code","description":"Retrieves one project code by id, including linked missions.","tags":["Project codes"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProjectCodeDetailPublic"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Project code not found for this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/team-tags":{"get":{"operationId":"listTeamTags","summary":"List Team Tags","description":"Lists team tags for the API key's team.","tags":["Team tags"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedTeamTags"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createTeamTag","summary":"Create Team Tag","description":"Creates a team tag.","tags":["Team tags"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TeamTagCreated"}}}}}},"400":{"$ref":"#/components/responses/PublicError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/team-tags/{id}":{"get":{"operationId":"getTeamTag","summary":"Retrieve Team Tag","description":"Retrieves team tag information by id.","tags":["Team tags"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TeamTagDetailPublic"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Team tag not found for this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/teams":{"get":{"operationId":"listTeams","summary":"List Teams","description":"Lists organizational teams (team units) for the API key's team.","tags":["Teams"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedTeams"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createTeam","summary":"Create Team","description":"Creates a new organizational team (team unit) for the API key's team. Use **`parent_id`** to create a child node (depth is derived from the parent). Omit **`parent_id`** to create a root node at depth 1.","tags":["Teams"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Team name (must be non-empty).","example":"Engineering"},"parent_id":{"type":"string","format":"uuid","nullable":true,"description":"Parent organizational team UUID. Omit to create a root node."},"external_id":{"type":"string","nullable":true,"maxLength":255,"description":"External reference for integrations (unique per team when set)."},"sort_order":{"type":"integer","minimum":0,"default":0,"description":"Sort order among siblings (ascending)."}}}}}},"responses":{"201":{"description":"Team created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TeamListItemPublic"}}}}}},"400":{"$ref":"#/components/responses/PublicError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/teams/{id}":{"get":{"operationId":"getTeam","summary":"Retrieve Team","description":"Retrieves organizational team information by id.","tags":["Teams"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TeamDetailPublic"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Team not found for this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/missions":{"get":{"operationId":"listMissions","summary":"List Missions","description":"Lists missions for the API key's team. All query parameters are optional.\n","tags":["Missions"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/MissionStatusFilter"},{"$ref":"#/components/parameters/MissionStartDateFrom"},{"$ref":"#/components/parameters/MissionEndDateFrom"},{"$ref":"#/components/parameters/MissionEndDateTo"},{"$ref":"#/components/parameters/MissionCreatedAtFrom"},{"$ref":"#/components/parameters/MissionCreatedAtTo"},{"$ref":"#/components/parameters/MissionProjectCodeIdFilter"},{"$ref":"#/components/parameters/MissionHasProjectCodeFilter"},{"$ref":"#/components/parameters/MissionHasPurchaseOrderFilter"},{"name":"freelancer_id","in":"query","description":"Restrict to missions assigned to this freelancer (UUID).","schema":{"type":"string","format":"uuid"}},{"name":"external_id","in":"query","description":"Restrict to the mission whose **`external_id`** matches exactly (your ERP / third-party reference set via **`PATCH /api/v1/missions/{id}`**).","schema":{"type":"string","example":"ERP-MISSION-2026-001"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedMissions"}}}}}},"400":{"description":"Validation (e.g. invalid **`created_at_*`** / **`end_date_*`** date or range, unknown **`status`** or **`has_*`** value,\nboth **`project_code_id`** and **`has_project_code`**, or **`project_code_id`** not found for the team).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createMission","summary":"Create Mission","description":"Creates a mission for the API key's team.\n\nFor `hourly`, `daily`, or `monthly`, send `rate_amount` > 0; for `deliverable`, send `deliverables` instead of `rate_amount`. Dates: **YYYY-MM-DD**.\n\n**Generate a services-agreement PDF** (`contract_type: services_agreement`, default) — `use_folkyn_template: true` + `team_signer_id`, then either:\n- **Default template:** `template_locale` = `fr` or `en`.\n- **Custom template:** `folkyn_template_id` = prestation template UUID.\n\n**Generate a master-agreement PDF** (`contract_type: master_agreement`): `master_agreement_template_id` + `master_agreement_valid_until` + `team_signer_id`. If the freelancer already has a framework agreement in progress or awaiting signature (same team, not expired), that agreement is **reused and linked** to the mission — no new PDF is generated and template fields are **ignored**. Send template fields only when no current framework agreement exists (e.g. first mission under master agreement, or previous agreement expired).\n\nFor services agreements only, omit template fields to create a mission without a generated document. Master-agreement missions require either a reusable framework agreement or `master_agreement_template_id` / uploaded `master_agreement_file`. Optional: `purchase_order`, `project_code_id`, `approver_id`. The freelance referent is set on the freelancer profile (`PATCH /api/v1/freelancers/{id}`), not on mission create.\n","tags":["Missions"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MissionCreateRequest"},"examples":{"services_agreement_folkyn_locale":{"summary":"Services agreement — Folkyn template by language","value":{"name":"Backend API — Q3","description":"API development and maintenance for the Q3 release.","mission_type":"daily","contract_type":"services_agreement","rate_amount":650,"start_date":"2026-07-01","end_date":"2026-12-31","freelancer_id":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","team_signer_id":"bbbbbbbb-cccc-4ddd-eeee-ffffffffffff","use_folkyn_template":true,"template_locale":"fr"}},"services_agreement_with_template":{"summary":"Services agreement — team template UUID","value":{"name":"Backend API — Q3","description":"API development and maintenance for the Q3 release.","mission_type":"daily","contract_type":"services_agreement","rate_amount":650,"start_date":"2026-07-01","end_date":"2026-12-31","freelancer_id":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","team_signer_id":"bbbbbbbb-cccc-4ddd-eeee-ffffffffffff","use_folkyn_template":true,"folkyn_template_id":"cccccccc-dddd-4eee-ffff-000000000001"}},"services_agreement_simple":{"summary":"Services agreement — no generated document","value":{"name":"Backend API — Q3","description":"API development and maintenance for the Q3 release.","mission_type":"daily","contract_type":"services_agreement","rate_amount":650,"start_date":"2026-07-01","end_date":"2026-12-31","freelancer_id":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","purchase_order":"PO-2026-001"}},"services_agreement_with_approver":{"summary":"Services agreement — pending admin approval before freelancer","value":{"name":"Backend API — Q3 (review)","description":"API development and maintenance for the Q3 release.","mission_type":"daily","contract_type":"services_agreement","rate_amount":650,"start_date":"2026-07-01","end_date":"2026-12-31","freelancer_id":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","approver_id":"bbbbbbbb-cccc-4ddd-eeee-ffffffffffff"}},"master_agreement":{"summary":"Master agreement with Folkyn template","value":{"name":"Framework — Jane Doe","description":"Framework agreement for consulting services.","mission_type":"daily","contract_type":"master_agreement","rate_amount":600,"start_date":"2026-07-01","end_date":"2026-12-31","freelancer_id":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee","team_signer_id":"bbbbbbbb-cccc-4ddd-eeee-ffffffffffff","master_agreement_template_id":"cccccccc-dddd-4eee-ffff-000000000001","master_agreement_valid_until":"2027-06-30"}}}}}},"responses":{"201":{"description":"Created — same object as GET /api/v1/missions/{id}","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MissionDetail"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Forbidden (e.g. subscription required)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/missions/{id}":{"get":{"operationId":"getMission","summary":"Retrieve Mission","description":"Retrieves mission information by id.","tags":["Missions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MissionDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"operationId":"patchMissionEnterprise","summary":"Update Mission Enterprise Fields","description":"Updates name, purchase_order, external_id, and/or project code for the API key's team mission.","tags":["Missions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MissionEnterprisePatchRequest"},"examples":{"project_code_name_and_external_id":{"summary":"Project code — name + optional ERP id (same object)","description":"**`name`** is always required inside **`project_code`**. Add **`external_id`** in that same object when you want Folkyn to match or create by **(team, external_id)**.\n","value":{"project_code":{"name":"ACME — renewal 2026","external_id":"ERP-PROJ-88421"}}},"project_code_name_only":{"summary":"Project code — display name only (no ERP id)","value":{"project_code":{"name":"Internal initiative"}}},"project_code_id_link":{"summary":"Link mission to an existing project code UUID","value":{"project_code_id":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee"}},"project_code_unlink":{"summary":"Remove project code from the mission","description":"**`project_code_id`: null** or **`\"\"`** unlinks. At runtime you may also send **`\"project_code\": null`**; this example uses **`project_code_id`** so it validates against the published schema.\n","value":{"project_code_id":null}},"rename_mission_only":{"summary":"Update mission title only","value":{"name":"Renamed mission title"}},"set_external_id":{"summary":"Set the mission external identifier","value":{"external_id":"ERP-MISSION-2026-001"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MissionDetail"}}}}}},"400":{"description":"Validation (unknown fields, empty name, both project code keys, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Mission not found for this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/missions/{id}/terminate":{"post":{"operationId":"terminateMission","summary":"Terminate Mission Early","description":"Early-terminates an **`in-progress`** mission at a given effective date (**`end_date`**, `YYYY-MM-DD`). If the date is today or in the past, the mission is terminated immediately (status `terminated`). If the date is in the future, the termination is scheduled and finalized automatically on that date. Same business rules as the Folkyn app.\n","tags":["Missions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MissionTerminateRequest"},"examples":{"terminate_today":{"summary":"Terminate immediately (today)","value":{"end_date":"2026-06-29","reason":"Client ended the engagement early."}},"schedule_future":{"summary":"Schedule termination on a future date","value":{"end_date":"2026-08-31"}}}}}},"responses":{"200":{"description":"Success — same object as GET /api/v1/missions/{id}","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/MissionDetail"}}}}}},"400":{"description":"Validation (missing/invalid end_date, mission not in-progress, already terminated/scheduled).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Mission not found for this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/freelancers":{"get":{"operationId":"listFreelancers","summary":"List Freelancers","description":"Lists freelancers for the API key's team.","tags":["Freelancers"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"name":"status","in":"query","description":"Comma-separated roster segment: `staffed`, `unstaffed`, `pending`, `archived`, or `all`. `staffed` = at least one active mission; `unstaffed` = active link without such mission; `pending` = invitation not accepted (`id` is a team invitation id); `archived` = archived link. Omit `status` to exclude `archived` and `pending`; use `all` for no filter.\n","schema":{"type":"string","example":"staffed,unstaffed"}},{"name":"tag_ids","in":"query","description":"Comma-separated tag UUIDs (AND — freelancer must have all listed tags).","schema":{"type":"string"}},{"name":"kyc_complete","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"master_agreement_active","in":"query","schema":{"type":"string","enum":["true","false"]}},{"name":"external_id","in":"query","description":"Filter by exact `external_id` (case-insensitive) — matches the team-set value or, when unset, the value derived from the freelancer's name.","schema":{"type":"string","example":"clementbalea"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedPartnerFreelancers"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/freelancers/invitations":{"post":{"operationId":"inviteFreelancer","summary":"Invite Freelancer","description":"Invites a freelancer by email.\n\nTrack pending invitations with `GET /api/v1/freelancers?status=pending`.\n","tags":["Freelancers"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FreelancerInvitationCreateRequest"},"example":{"email":"jane.doe@example.com","first_name":"Jane","last_name":"Doe","job_title":"Senior Developer","tag_ids":["aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee"],"invite_locale":"en"}}}},"responses":{"201":{"description":"Invitation created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/FreelancerInvitationCreated"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/freelancers/{id}":{"patch":{"operationId":"patchFreelancerTeamFields","summary":"Update Freelancer Team Fields","description":"Updates team-scoped freelancer fields.","tags":["Freelancers"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Freelancer profile UUID (not a pending invitation id)."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FreelancerPartnerPatchRequest"},"examples":{"external_id_and_note":{"summary":"External id and internal note","value":{"external_id":"ERP-F-88421","note":"Preferred for Q3 staffing"}},"tags_and_teams":{"summary":"Replace tags and teams","value":{"tag_ids":["aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee"],"team_ids":["bbbbbbbb-cccc-4ddd-eeee-ffffffffffff"]}},"job_title_and_referent":{"summary":"Job title and team referent","value":{"job_title":"Senior React Developer","referent_id":"cccccccc-dddd-4eee-ffff-000000000001"}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/FreelancerListItemPublic"}}}}}},"400":{"description":"Validation (unknown fields, invalid arrays, referent not in team, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Freelancer not found for this team","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/users":{"get":{"operationId":"listUsers","summary":"List Team Users","description":"Lists company users (team admins and members), including pending invitations.\n\nDefault `status` filter: `active,pending`. Other values: `expired`, `undeliverable`, or `all`.\n\nFor `status: active`, `id` is the profile UUID. For invitations, `id` is the invitation UUID.\n","tags":["Users"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"name":"status","in":"query","description":"Comma-separated segments — `active`, `pending`, `expired`, `undeliverable`, or `all`. Default `active,pending`.","schema":{"type":"string","example":"active,pending"}},{"name":"role","in":"query","description":"Filter by team role — `team-admin` or `team-member`. Omit for all roles.","schema":{"type":"string","enum":["team-admin","team-member"]}},{"name":"email","in":"query","description":"Filter by exact email address (case-insensitive). Matches both active members and invitations.","schema":{"type":"string","format":"email","example":"jane.doe@acme.com"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedPartnerUsers"}}}}}},"400":{"description":"Validation (unknown status or role)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/users/invitations":{"post":{"operationId":"inviteUser","summary":"Invite Team User","description":"Invites a team admin or member by email.\n\nTrack pending invitations with `GET /api/v1/users?status=pending`.\n","tags":["Users"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInvitationCreateRequest"},"example":{"email":"admin@example.com","first_name":"Alex","last_name":"Martin","role":"team-admin","job_title":"HR Manager","invite_locale":"fr"}}}},"responses":{"201":{"description":"Invitation created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/UserInvitationCreated"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/activity-reports":{"get":{"operationId":"listActivityReports","summary":"List Activity Reports","description":"Lists activity reports (CRA) for the API key's team.","tags":["Activity reports"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/ActivityReportStatusFilter"},{"name":"submission_date","in":"query","description":"Filter by day (YYYY-MM-DD).","schema":{"type":"string","format":"date","example":"2026-04-08"}},{"name":"mission_id","in":"query","description":"Mission UUID.","schema":{"type":"string","format":"uuid"}},{"name":"freelancer_id","in":"query","description":"Freelancer UUID.","schema":{"type":"string","format":"uuid"}},{"name":"period","in":"query","description":"Filter by CRA calendar month, same as stored **`report_month`** (`YYYY-MM`).\nCombines with other filters (logical AND).\n","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","example":"2026-04"}},{"$ref":"#/components/parameters/ActivityReportSort"},{"$ref":"#/components/parameters/ActivityReportSortDirection"}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedActivityReports"}}}}}},"400":{"$ref":"#/components/responses/PublicError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/activity-reports/{id}":{"get":{"operationId":"getActivityReport","summary":"Retrieve Activity Report","description":"Retrieves activity report information by id.","tags":["Activity reports"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ActivityReportDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/accounting/entries":{"get":{"operationId":"listAccountingEntries","summary":"List Accounting Entries","description":"Lists accounting entries for validated activity reports on the API key's team.\n\nEach item includes `invoice_number`, `file_name`, and a `freelancer` object.\nOptional **`sort`** / **`direction`** query params order the list (default **`created_at`** **`desc`**).\n","tags":["Accounting"],"parameters":[{"$ref":"#/components/parameters/Page"},{"$ref":"#/components/parameters/PerPage"},{"$ref":"#/components/parameters/AccountingEntrySort"},{"$ref":"#/components/parameters/AccountingEntrySortDirection"},{"name":"status","in":"query","schema":{"type":"string","enum":["paid","waiting_payment"]}},{"name":"type","in":"query","schema":{"type":"string","enum":["invoice","expenses"]}},{"name":"activity_report_id","in":"query","description":"Filter by CRA UUID (validated, in-team scope).","schema":{"type":"string","format":"uuid"}},{"name":"has_sent_to_accounting","in":"query","description":"Presence filter on whether the entry was sent to the accounting tool (**not a date range**). Case-insensitive accepted values: **`with`**, **`without`**, **`true`**, **`false`** (also **`1`** / **`0`**). **`with`** / **`true`**: **`sent_to_accounting_at`** is set (already sent). **`without`** / **`false`**: not sent yet (`null`). Returns **`400`** if the value is invalid.\n","schema":{"type":"string","enum":["with","without",true,false]}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PaginatedAccountingEntries"}}}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/accounting/entries/{id}":{"patch":{"operationId":"patchAccountingEntryMarkPaid","summary":"Mark Accounting Entry as Paid","description":"Marks the accounting entry as paid.","tags":["Accounting"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountingEntryMarkPaidRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","required":["entry"],"properties":{"entry":{"$ref":"#/components/schemas/AccountingEntryPublic"}}}}}}}},"400":{"description":"Validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/ForbiddenError"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Use `Authorization: Bearer <your_api_key>`"},"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-Api-Key"}},"parameters":{"Page":{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},"PerPage":{"name":"per_page","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},"MissionStatusFilter":{"name":"status","in":"query","description":"Comma-separated mission statuses (kebab-case, normalized to lowercase).\nFilters on the same values returned in the `status` field — see `MissionStatus`.\n\n**Allowed values:** `draft`, `pending-freelancer-review`, `pending-company-review`, `pending-freelancer-extension`, `in-progress`, `completed`, `early-terminated`, `cancelled`, `rejected`, `deleted`.\n\nAn unknown value returns `400`.\n","schema":{"type":"string"},"example":"in-progress,completed"},"MissionStartDateFrom":{"name":"start_date_from","in":"query","description":"Calendar **YYYY-MM-DD**. Returns missions whose `start_date` is on or after this day.","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"example":"2025-01-01"},"MissionCreatedAtFrom":{"name":"created_at_from","in":"query","description":"Inclusive lower bound on mission creation date. Calendar **YYYY-MM-DD** (UTC day start). Pairs with `created_at_to`.","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"example":"2025-06-01"},"MissionCreatedAtTo":{"name":"created_at_to","in":"query","description":"Inclusive upper bound on mission creation date. Calendar **YYYY-MM-DD** (UTC day end). Must be ≥ `created_at_from` when both are set.","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"example":"2025-06-30"},"MissionEndDateFrom":{"name":"end_date_from","in":"query","description":"Inclusive lower bound on the mission end date. Calendar **YYYY-MM-DD**. Pairs with `end_date_to`. Matches on the effective end date: `early_termination_date` when set, otherwise `end_date`.\n","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"example":"2025-07-01"},"MissionEndDateTo":{"name":"end_date_to","in":"query","description":"Inclusive upper bound on the mission end date. Calendar **YYYY-MM-DD**. Must be ≥ `end_date_from` when both are set. Matches on the effective end date: `early_termination_date` when set, otherwise `end_date`.\n","schema":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"example":"2025-07-31"},"MissionProjectCodeIdFilter":{"name":"project_code_id","in":"query","description":"Filter missions linked to this team project code (UUID from **`GET /api/v1/project-codes`**).\nMutually exclusive with **`has_project_code`**. Returns **`400`** if the id is not a valid UUID or does not belong to the API key's team.\n","schema":{"type":"string","format":"uuid"},"example":"aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee"},"MissionHasProjectCodeFilter":{"name":"has_project_code","in":"query","description":"Presence filter on **`project_code_id`**. Case-insensitive accepted values: **`with`**, **`without`**, **`true`**, **`false`** (also **`1`** / **`0`**).\n**`with`** / **`true`**: mission has a project code. **`without`** / **`false`**: no project code.\nMutually exclusive with **`project_code_id`**.\n","schema":{"type":"string","enum":["with","without","true","false","1","0"]},"example":"with"},"MissionHasPurchaseOrderFilter":{"name":"has_purchase_order","in":"query","description":"Presence filter on **`purchase_order`**. Same accepted values as **`has_project_code`**.\n**`with`** / **`true`**: non-empty purchase order (after trim). **`without`** / **`false`**: null, empty, or whitespace-only.\n","schema":{"type":"string","enum":["with","without","true","false","1","0"]},"example":"without"},"ActivityReportStatusFilter":{"name":"status","in":"query","description":"Comma-separated activity report statuses. Case-insensitive (normalized to uppercase).\n\n**Allowed values:** `PENDING`, `APPROVED`, `REJECTED`.\n\nResponse JSON uses a lowercase **`status`** field (`pending`, `approved`, `rejected`, `paid`) — see `ActivityReportDisplayStatus`.\n","schema":{"type":"string"},"example":"PENDING,APPROVED"},"ActivityReportSort":{"name":"sort","in":"query","description":"Sort field for the list (pairs with `direction`). Default `created_at`. `review_date` is an alias for `reviewed_at` (last review decision; null until reviewed).\n","schema":{"type":"string","enum":["created_at","reviewed_at","review_date"],"default":"created_at"}},"ActivityReportSortDirection":{"name":"direction","in":"query","description":"Sort direction. Case-insensitive. Omit for **`desc`**.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"AccountingEntrySort":{"name":"sort","in":"query","description":"Sort field for accounting entries (pairs with **`direction`**). Default **`created_at`**. **`payment_date`** aliases **`paid_at`**. **`sent_to_accounting`** and **`accounting_sent_at`** alias **`sent_to_accounting_at`**.\n","schema":{"type":"string","enum":["created_at","paid_at","payment_date","sent_to_accounting_at","sent_to_accounting","accounting_sent_at"],"default":"created_at"}},"AccountingEntrySortDirection":{"name":"direction","in":"query","description":"Sort direction for **`GET /api/v1/accounting/entries`**. Case-insensitive. Omit for **`desc`**.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}},"schemas":{"PartnerValidationErrorReason":{"type":"string","description":"Machine-readable validation subtype (HTTP 400) for create tag / project code.","enum":["invalid_json","required_field","duplicate_name"]},"PublicErrorDetails":{"type":"object","description":"Optional structured hints (validation, scope, rate limit).","additionalProperties":true,"properties":{"reason":{"$ref":"#/components/schemas/PartnerValidationErrorReason"},"field":{"type":"string","description":"JSON body field name when applicable (e.g. `name`).","example":"name"},"requiredScope":{"type":"string","description":"Required OAuth-like scope string when `code` is 403 (insufficient scope).","example":"tags:write"},"retryAfterSeconds":{"type":"integer","minimum":0,"description":"Hint when `code` is 429."}}},"PublicError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"integer","description":"Same as HTTP status; use `message` and `details` to narrow.","enum":[400,401,403,404,429,500],"example":401},"message":{"type":"string"},"request_id":{"type":"string","format":"uuid","description":"Correlates with the X-Request-Id response header."},"details":{"$ref":"#/components/schemas/PublicErrorDetails"}}}}},"PaginatedProjectCodes":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ProjectCode"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"PaginatedTeamTags":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TeamTag"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"PaginatedMissions":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MissionListItemPublic"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"PartnerFreelancerListStatus":{"type":"string","enum":["staffed","unstaffed","pending","archived"],"description":"Lifecycle status on each list item. `staffed` = active mission on team; `unstaffed` = active link, no such mission; `pending` = invitation not yet accepted; `archived` = archived link.\n"},"FreelancerTagPublic":{"type":"object","required":["id","name"],"description":"Team tag attached to the freelancer.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"FreelancerTeamPublic":{"type":"object","required":["id","name","depth","path","parent_id"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"depth":{"type":"integer","minimum":1,"maximum":3,"description":"Depth in the organizational tree (1 = root)."},"path":{"type":"string","description":"Ancestor path from root to this node (e.g. `Direction › Engineering › Backend`)."},"parent_id":{"type":"string","format":"uuid","nullable":true,"description":"Parent organizational team UUID; null for root nodes."}}},"FreelancerListItemPublic":{"type":"object","required":["id","email","external_id","job_title","note","referent","status","tags","teams","kyc_complete","master_agreement_active","created_at"],"properties":{"id":{"type":"string","format":"uuid","description":"Profile UUID, or invitation UUID when `status` is `pending`."},"email":{"type":"string"},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"external_id":{"type":"string","description":"External identifier for integrations. Uses the team-stored value when set; otherwise computed from lowercased `first_name` + `last_name` with spaces and Latin diacritics stripped (e.g. Clément Balea → `clementbalea`). German `ß` becomes `ss`. Empty string if both names are missing and no stored value.\n"},"job_title":{"type":"string","nullable":true},"note":{"type":"string","nullable":true,"description":"Internal team note on the freelancer; null if absent."},"referent":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/PartnerFreelancerReferentPublic"}],"description":"Team referent profile; null if none."},"status":{"$ref":"#/components/schemas/PartnerFreelancerListStatus"},"tags":{"type":"array","description":"Tags for this freelancer on the team (`tag_ids` query uses AND across listed UUIDs).","items":{"$ref":"#/components/schemas/FreelancerTagPublic"}},"teams":{"type":"array","description":"Organizational teams (team units) this freelancer belongs to.","items":{"$ref":"#/components/schemas/FreelancerTeamPublic"}},"kyc_complete":{"type":"boolean"},"master_agreement_active":{"type":"boolean","description":"Signed master agreement with a future `valid_until` date."},"created_at":{"type":"string","format":"date-time"}}},"PaginatedPartnerFreelancers":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/FreelancerListItemPublic"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"FreelancerPartnerPatchRequest":{"type":"object","description":"At least one field required. `tag_ids` and `team_ids` replace the full assignment for this team.\n`referent_id` can be reassigned to another team member but cannot be cleared.\n","minProperties":1,"properties":{"external_id":{"type":"string","nullable":true,"description":"Team-stored external identifier; null clears it."},"note":{"type":"string","nullable":true,"description":"Internal team note on the freelancer; null clears it."},"tag_ids":{"type":"array","description":"Team tag UUIDs to assign (replaces existing tags for this team).","items":{"type":"string","format":"uuid"}},"team_ids":{"type":"array","maxItems":1,"description":"Organizational team UUID to assign (replaces existing assignment for this team). At most one team per person. Send an empty array to clear.","items":{"type":"string","format":"uuid"}},"department_ids":{"type":"array","maxItems":1,"deprecated":true,"description":"Deprecated alias for `team_ids`. Use `team_ids` instead.","items":{"type":"string","format":"uuid"}},"job_title":{"type":"string","nullable":true,"description":"Job title on the team link."},"referent_id":{"type":"string","format":"uuid","description":"Team member profile UUID as referent; must belong to the API key's team. Cannot be cleared."}}},"FreelancerInvitationCreateRequest":{"type":"object","required":["email","first_name","last_name"],"properties":{"email":{"type":"string","format":"email"},"first_name":{"type":"string"},"last_name":{"type":"string"},"job_title":{"type":"string","description":"Optional job title stored on the invitation."},"referent_id":{"type":"string","format":"uuid","description":"Active team member profile UUID as referent."},"tag_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"team_ids":{"type":"array","maxItems":1,"description":"Organizational team UUID on the invitation. At most one team per person.","items":{"type":"string","format":"uuid"}},"invited_by_member_id":{"type":"string","format":"uuid","description":"Team member profile UUID shown as email sender; defaults to first active team-admin."},"invite_locale":{"type":"string","enum":["fr","en"],"description":"Locale for the invitation email (`fr` or `en`)."}}},"FreelancerInvitationCreated":{"type":"object","required":["invitation_id","email","status","email_sent","is_existing_freelancer"],"properties":{"invitation_id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"status":{"type":"string","enum":["pending"]},"email_sent":{"type":"boolean"},"is_existing_freelancer":{"type":"boolean","description":"True when the email belongs to an existing freelancer account on the platform."}}},"MissionCreateRequest":{"type":"object","required":["name","description","mission_type","start_date","end_date","freelancer_id"],"properties":{"name":{"type":"string"},"description":{"type":"string","description":"Mission objectives, deliverables, and working conditions."},"mission_type":{"$ref":"#/components/schemas/MissionBillingType"},"contract_type":{"type":"string","enum":["services_agreement","master_agreement"],"default":"services_agreement"},"rate_amount":{"type":"number","description":"Required for hourly, daily, and monthly missions (HT unit rate). Omit for deliverable missions."},"deliverables":{"type":"array","description":"Required when mission_type is deliverable.","items":{"type":"object","required":["name","quantity","amount_ht"],"properties":{"name":{"type":"string"},"quantity":{"type":"number"},"amount_ht":{"type":"number"}}}},"start_date":{"type":"string","format":"date","description":"YYYY-MM-DD"},"end_date":{"type":"string","format":"date","description":"YYYY-MM-DD"},"freelancer_id":{"type":"string","format":"uuid","description":"Active freelancer profile UUID on the team."},"team_signer_id":{"type":"string","format":"uuid","description":"Required when generating a contract from a template (`folkyn_template_id` or `master_agreement_template_id`). Active team member profile UUID as company signatory."},"purchase_order":{"type":"string"},"project_code_id":{"type":"string","format":"uuid"},"approver_id":{"type":"string","format":"uuid","description":"Active team-admin UUID — mission stays in `draft` until approved."},"use_folkyn_template":{"type":"boolean","description":"Set `true` to generate a services-agreement PDF from a DOCX template."},"template_locale":{"type":"string","enum":["fr","en"],"description":"Default prestation template language. Use instead of `folkyn_template_id` when you do not have the template UUID."},"folkyn_template_id":{"type":"string","format":"uuid","description":"Prestation template UUID. Alternative to `template_locale`."},"master_agreement_template_id":{"type":"string","format":"uuid","description":"Team DOCX template UUID (`master_agreement` only). Requires `team_signer_id` and `master_agreement_valid_until`. Ignored when the freelancer already has a current framework agreement (in progress or awaiting signature)."},"master_agreement_valid_until":{"type":"string","format":"date","description":"Framework agreement end date (YYYY-MM-DD). Required with `master_agreement_template_id`. Ignored when an existing framework agreement is reused."}}},"PaginatedPartnerUsers":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/UserListItemPublic"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"UserListItemPublic":{"type":"object","required":["id","email","role","status","tags","teams"],"properties":{"id":{"type":"string","format":"uuid","description":"Profile UUID when active; invitation UUID when pending/expired/undeliverable."},"email":{"type":"string","format":"email"},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"role":{"type":"string","enum":["team-admin","team-member"]},"job_title":{"type":"string","nullable":true},"status":{"type":"string","enum":["active","pending","expired","undeliverable"]},"tags":{"type":"array","items":{"$ref":"#/components/schemas/PartnerTagPublic"}},"teams":{"type":"array","description":"Organizational teams assigned to the user or invitation.","items":{"$ref":"#/components/schemas/PartnerTeamUnitPublic"}},"created_at":{"type":"string","format":"date-time","nullable":true}}},"PartnerTagPublic":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"PartnerTeamUnitPublic":{"type":"object","required":["id","name","depth","path","parent_id"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"depth":{"type":"integer","minimum":1,"maximum":3},"path":{"type":"string","description":"Ancestor path from root to this node."},"parent_id":{"type":"string","format":"uuid","nullable":true}}},"UserInvitationCreateRequest":{"type":"object","required":["email","first_name","last_name","role"],"properties":{"email":{"type":"string","format":"email"},"first_name":{"type":"string"},"last_name":{"type":"string"},"role":{"type":"string","enum":["team-admin","team-member"]},"job_title":{"type":"string"},"tag_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"team_ids":{"type":"array","maxItems":1,"description":"Organizational team UUID on the invitation. At most one team per person.","items":{"type":"string","format":"uuid"}},"invited_by_member_id":{"type":"string","format":"uuid","description":"Team member profile UUID shown as email sender; defaults to first active team-admin."},"invite_locale":{"type":"string","enum":["fr","en"]}}},"UserInvitationCreated":{"type":"object","required":["invitation_id","email","status","email_sent","role","resent"],"properties":{"invitation_id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"status":{"type":"string","enum":["pending"]},"email_sent":{"type":"boolean"},"role":{"type":"string","enum":["team-admin","team-member"]},"resent":{"type":"boolean","description":"True when an existing pending invitation was updated and the email was resent."}}},"PaginatedActivityReports":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ActivityReportListItemPublic"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"MissionBillingType":{"type":"string","description":"Billing model for the mission (Postgres enum `mission_type`). `hourly` / `daily` / `monthly` use **`rate_amount`** as the price per that unit in **`currency`**. `deliverable` missions bill via the **deliverables catalog** (quantities and line amounts); `rate_amount` may still be set as a reference but line totals come from catalog rows on mission detail.\n","enum":["hourly","daily","monthly","deliverable"]},"MissionStatus":{"type":"string","description":"Mission status. Derived from dates, pending documents, and pending addenda — the same value used for filtering (see the `status` query parameter).\n","enum":["draft","pending-freelancer-review","pending-company-review","pending-freelancer-extension","in-progress","completed","early-terminated","cancelled","rejected","deleted"]},"ActivityReportDisplayStatus":{"type":"string","description":"Normalized status in response JSON (lowercase). Values: `PENDING` → `pending`, `APPROVED` → `approved` or **`paid`** when invoicing or expenses are marked paid, `REJECTED` → `rejected`.\n","enum":["pending","approved","rejected","paid"]},"MissionListItemPublic":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"mission_type":{"$ref":"#/components/schemas/MissionBillingType"},"contract_kind":{"type":"string","description":"Contract channel: **`master_agreement`** = framework agreement path, **`services_agreement`** = standalone services agreement. Only these two values are returned.\n","enum":["master_agreement","services_agreement"]},"has_document":{"type":"boolean"},"currency":{"type":"string","description":"ISO 4217 alphabetic code (e.g. `EUR`, `USD`) as stored on the mission.","example":"EUR"},"rate_amount":{"type":"number","description":"Unit price in **`currency`** according to **`mission_type`**: per hour, per day, per month, or mission-level reference for deliverable missions (see `MissionBillingType`). Not a daily rate derived by dividing elsewhere — the unit is implied by `mission_type`.\n"},"client_rate_amount":{"type":"number","nullable":true,"description":"ESN teams only: unit price excl. VAT billed to the end client for the same unit as **`rate_amount`** (per hour, day, or month per **`mission_type`**). Null for non-ESN teams, deliverable missions, or when unset.\n"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"status":{"$ref":"#/components/schemas/MissionStatus"},"early_termination_date":{"type":"string","format":"date","nullable":true,"description":"Effective end date chosen when the mission was terminated early (**YYYY-MM-DD**). Null if the mission was never terminated early."},"terminated_by":{"type":"string","format":"uuid","nullable":true,"description":"UUID of the team user who terminated the mission early. Null if the mission was never terminated early."},"external_referent":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/ActivityReportExternalReferentPublic"}]},"purchase_order":{"type":"string","nullable":true},"external_id":{"type":"string","nullable":true,"description":"External identifier for the mission set by the team (e.g. an ERP or third-party system reference); null if unset."},"project_code_id":{"type":"string","format":"uuid","nullable":true},"project_code":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/ActivityReportMissionProjectCodePublic"}],"description":"Primary linked project code; null if the mission has none."},"project_codes":{"type":"array","description":"All project codes linked to the mission (`id`, `name`, `external_id`). Populated on **`GET /api/v1/missions`** and **`GET /api/v1/missions/{id}`**. Empty when the mission has no linked codes.\n","items":{"$ref":"#/components/schemas/ActivityReportMissionProjectCodePublic"}},"deliverables_catalog":{"type":"array","description":"Mission deliverables catalog. Empty on **`GET /api/v1/missions`**; filled on **`GET /api/v1/missions/{id}`**.\n","items":{"$ref":"#/components/schemas/MissionDeliverableCatalogItem"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"created_by":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/PartnerPerson"}]},"freelancer":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/MissionFreelancerPublic"}]},"team_signer":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/PartnerPerson"}]}}},"MissionEnterprisePatchRequest":{"type":"object","description":"At least one field required. Send only one of `project_code_id` or `project_code` when updating the project code (not both in the same request).\n","minProperties":1,"properties":{"name":{"type":"string","maxLength":255,"description":"Mission title."},"purchase_order":{"type":"string","nullable":true,"maxLength":255},"external_id":{"type":"string","nullable":true,"maxLength":255,"description":"External identifier for the mission (e.g. an ERP or third-party system reference). Send **`null`** or **`\"\"`** to clear it.\n"},"project_code_id":{"type":"string","format":"uuid","nullable":true,"description":"Link the mission to an existing team project code by **UUID** (the row must belong to the same team as the API key). Send **`null`** or **`\"\"`** to unlink the mission from any project code. Mutually exclusive with **`project_code`** in the same request.\n"},"project_code_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Replace the full list of project codes linked to the mission (requires the team setting for multiple codes). Send an empty array to unlink all codes. Mutually exclusive with **`project_code_id`** and **`project_code`**.\n"},"project_code":{"type":"object","description":"Create or reuse a team project code and link the mission in one request. Send **`null`** to unlink. Mutually exclusive with **`project_code_id`**. Field-level rules are on **`name`** and **`external_id`** below.\n","nullable":true,"allOf":[{"$ref":"#/components/schemas/MissionEnterprisePatchProjectCode"}]}}},"MissionEnterprisePatchProjectCode":{"type":"object","description":"Send **`name`** and, when needed, **`external_id`** together in the same JSON object (see request examples on **`PATCH /api/v1/missions/{id}`**).\n\n**Unlink** the mission from any project code by sending **`\"project_code\": null`** on the PATCH body (not by sending this object).\n\n**How the row is chosen**\n- **Non-empty `external_id` (after trim):** matched by `external_id` for your team. If found, reused; `name` may be updated unless another project code on the team already uses that `name` (`400`). If not found, a new project code is created.\n- **Empty or omitted `external_id`:** matched by `name` only; reuse if found, otherwise create.\n","properties":{"name":{"type":"string","maxLength":255,"description":"Required. Display name for the project code. When **`external_id`** is empty or whitespace-only after trim, Folkyn matches an existing row by this **`name`** for your team before creating one.\n"},"external_id":{"type":"string","nullable":true,"maxLength":255,"description":"Optional. Stable id from your ERP (max 255 characters; leading/trailing spaces are trimmed). When non-empty after trim, matched by `external_id` for your team first, then the rules above apply.\n"}},"required":["name"]},"MissionTerminateRequest":{"type":"object","description":"Early-terminate an **`in-progress`** mission. `end_date` is the effective end date.\nToday/past → immediate termination; future → scheduled and finalized on that date.\n","properties":{"end_date":{"type":"string","format":"date","description":"Effective end date (`YYYY-MM-DD`). Must be **>= today (UTC)**, **>= mission start date**, and **<= current mission end date**.\n"},"reason":{"type":"string","nullable":true,"description":"Optional free-text reason kept on the mission for your records."}},"required":["end_date"]},"MissionDetail":{"$ref":"#/components/schemas/MissionListItemPublic"},"MissionFreelancerPublic":{"type":"object","description":"Assigned freelancer. `referent` is the team member assigned as referent for this freelancer, when configured — not the external client referent on the mission.\n","properties":{"id":{"type":"string","format":"uuid"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"referent":{"type":"object","nullable":true,"description":"Team referent (id, name, email); null if none.","allOf":[{"$ref":"#/components/schemas/PartnerFreelancerReferentPublic"}]}}},"ProjectCode":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"external_id":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"mission_count":{"type":"integer"}}},"ProjectCodeCreated":{"type":"object","required":["id","name","external_id","created_at"],"description":"Payload returned by POST /api/v1/project-codes (no mission_count or updated_at).","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"external_id":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"TeamTag":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"user_count":{"type":"integer"},"freelancer_count":{"type":"integer"}}},"TeamTagCreated":{"type":"object","required":["id","name","created_at"],"description":"Payload returned by POST /api/v1/team-tags (no counts or updated_at).","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"PartnerProfileIdEmail":{"type":"object","required":["id","email"],"properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string"}}},"ProjectCodeMissionSummary":{"type":"object","required":["id","name","freelancer_id"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"freelancer_id":{"type":"string","format":"uuid","nullable":true,"description":"Assigned freelancer profile id; null when the mission has no freelancer."}}},"ProjectCodeDetailPublic":{"type":"object","required":["id","name","missions","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"external_id":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"missions":{"type":"array","items":{"$ref":"#/components/schemas/ProjectCodeMissionSummary"}}}},"TeamTagDetailPublic":{"type":"object","required":["id","name","freelancers","users","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"freelancers":{"type":"array","items":{"$ref":"#/components/schemas/PartnerProfileIdEmail"}},"users":{"type":"array","items":{"$ref":"#/components/schemas/PartnerProfileIdEmail"}}}},"TeamListItemPublic":{"type":"object","required":["id","name","depth","path","parent_id","external_id","sort_order","is_archived","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"depth":{"type":"integer","minimum":1,"maximum":3},"path":{"type":"string"},"parent_id":{"type":"string","format":"uuid","nullable":true},"external_id":{"type":"string","nullable":true},"sort_order":{"type":"integer","minimum":0},"is_archived":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"TeamDetailPublic":{"type":"object","required":["id","name","depth","path","parent_id","external_id","sort_order","is_archived","freelancers","users","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"depth":{"type":"integer","minimum":1,"maximum":3},"path":{"type":"string"},"parent_id":{"type":"string","format":"uuid","nullable":true},"external_id":{"type":"string","nullable":true},"sort_order":{"type":"integer","minimum":0},"is_archived":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"freelancers":{"type":"array","items":{"$ref":"#/components/schemas/PartnerProfileIdEmail"}},"users":{"type":"array","items":{"$ref":"#/components/schemas/PartnerProfileIdEmail"}}}},"PaginatedTeams":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/TeamListItemPublic"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"PartnerPerson":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"first_name":{"type":"string"},"last_name":{"type":"string"}}},"PartnerFreelancerReferentPublic":{"type":"object","description":"Team referent (id, first name, last name, email).","required":["id","first_name","last_name","email"],"properties":{"id":{"type":"string","format":"uuid"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"}}},"ActivityReportFreelancerPublic":{"type":"object","nullable":true,"description":"Assigned freelancer; null if missing. `referent` matches the team referent on mission payloads (see `MissionFreelancerPublic`).\n","properties":{"id":{"type":"string","format":"uuid"},"first_name":{"type":"string"},"last_name":{"type":"string"},"email":{"type":"string"},"external_id":{"type":"string","description":"External identifier for integrations. Uses the team-stored value when set; otherwise computed from lowercased `first_name` + `last_name` with spaces and Latin diacritics stripped (e.g. Clément Balea → `clementbalea`). German `ß` becomes `ss`. Empty string if both names are missing and no stored value.\n"},"siren":{"type":"string","nullable":true,"description":"Freelancer company SIREN (9 digits, no spaces); null when unset or fewer than 9 digits.\n"},"referent":{"type":"object","nullable":true,"description":"Team referent (id, name, email); null if none.","allOf":[{"$ref":"#/components/schemas/PartnerFreelancerReferentPublic"}]}}},"ActivityReportMissionProjectCodePublic":{"type":"object","required":["id","name","external_id"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"external_id":{"type":"string","nullable":true,"description":"Optional client / ERP reference for the project code."}}},"ProjectCodeAmountPublic":{"type":"object","required":["id","name","external_id","amount_excl_vat"],"description":"Project code with invoice amount excl. VAT (excludes expense refacturation).","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"external_id":{"type":"string","nullable":true},"amount_excl_vat":{"type":"number","description":"Invoice amount excl. VAT attributed to this project code for the activity report or invoice accounting entry."}}},"ActivityReportSupplementaryItemPublic":{"type":"object","required":["id","description","amount_excl_vat","project_code_id"],"properties":{"id":{"type":"string","format":"uuid"},"description":{"type":"string","nullable":true},"amount_excl_vat":{"type":"number"},"project_code_id":{"type":"string","format":"uuid","nullable":true,"description":"Project code billed on this supplementary line. Set when the mission has multiple project codes; otherwise `null`.\n"}}},"ActivityReportMissionPublic":{"type":"object","required":["id","name","mission_type","currency","rate_amount","purchase_order","project_code"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"mission_type":{"$ref":"#/components/schemas/MissionBillingType"},"currency":{"type":"string","description":"ISO 4217 currency code of the mission's amounts (e.g. `EUR`, `USD`). Defaults to `EUR`."},"rate_amount":{"type":"number","description":"Freelancer unit rate excl. VAT (in **`currency`**); unit follows **`mission_type`**."},"client_rate_amount":{"type":"number","nullable":true,"description":"ESN: unit rate excl. VAT resold to the end client (same currency and unit as **`rate_amount`**). Null when not applicable or unset.\n"},"purchase_order":{"type":"string","nullable":true,"description":"Purchase order number (bon de commande) on the mission, if set."},"project_code":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/ActivityReportMissionProjectCodePublic"}],"description":"Primary linked team project code; null if the mission has none. Use root **`project_codes`** on the activity report for the full list with amounts."}}},"ActivityReportExternalReferentPublic":{"type":"object","required":["id","email","company","siren","address","postal_code","city"],"description":"External client referent on the mission (id, email, company name, SIREN, address fields). Distinct from `freelancer.referent` (team referent).","properties":{"id":{"type":"string","format":"uuid","nullable":true,"description":"Client company UUID; null when unset."},"email":{"type":"string"},"company":{"type":"string"},"siren":{"type":"string","nullable":true,"pattern":"^[0-9]{9}$","description":"Client company SIREN (9 digits, no spaces); null when unset or fewer than 9 digits."},"address":{"type":"string","nullable":true,"description":"Street address line."},"postal_code":{"type":"string","nullable":true},"city":{"type":"string","nullable":true}}},"ActivityReportListItemPublic":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"mission":{"$ref":"#/components/schemas/ActivityReportMissionPublic"},"external_referent":{"type":"object","nullable":true,"allOf":[{"$ref":"#/components/schemas/ActivityReportExternalReferentPublic"}]},"report_month":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}$","description":"Month key as stored (**`YYYY-MM`**). **`report_period_start`** / **`report_period_end`** are RFC 3339 **`date-time`** strings with explicit offset, covering the **first civil day** through the **last civil day** of that month in **`report_period_time_zone`** (**`Europe/Paris`** — legal time, including DST). Safe to parse with standard `date-time` clients (`new Date(...)` in JavaScript). Null if **`report_month`** is missing or invalid.\n","example":"2024-03"},"report_period_time_zone":{"type":"string","enum":["Europe/Paris"],"description":"IANA time zone applied to **`report_period_start`** / **`report_period_end`** (always this value)."},"report_period_start":{"type":"string","format":"date-time","nullable":true,"description":"First instant of the first civil day of **`report_month`** in **`Europe/Paris`** (RFC 3339 with offset). Null if missing or invalid.\n","example":"2024-03-01T00:00:00.000+01:00"},"report_period_end":{"type":"string","format":"date-time","nullable":true,"description":"Last instant of the last civil day of **`report_month`** in **`Europe/Paris`** (handles February leap years and DST). Null if invalid.\n","example":"2024-03-31T23:59:59.999+02:00"},"submission_date":{"type":"string","format":"date-time","nullable":true},"status":{"$ref":"#/components/schemas/ActivityReportDisplayStatus"},"reviewed_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp of the last review decision (approve or reject). Null if never reviewed.\n"},"rejection_reason":{"type":"string","nullable":true},"freelancer":{"$ref":"#/components/schemas/ActivityReportFreelancerPublic"},"invoicing_is_paid":{"type":"boolean"},"expenses_is_paid":{"type":"boolean"},"invoice_amount_excl_vat":{"type":"number","description":"Invoice line amount excluding VAT."},"expense_amount_excl_vat":{"type":"number","description":"Expense line amount excluding VAT."},"project_codes":{"type":"array","description":"Invoice amount excl. VAT split by project code (same rules as invoice billing; excludes expense refacturation). One entry with the full **`invoice_amount_excl_vat`** when the mission has a single linked code; per-line split when multiple codes are linked. Empty when no project codes are linked.\n","items":{"$ref":"#/components/schemas/ProjectCodeAmountPublic"}},"supplementary_items":{"type":"array","description":"Supplementary billing lines. When the mission has multiple project codes, each line includes **`project_code_id`**.\n","items":{"$ref":"#/components/schemas/ActivityReportSupplementaryItemPublic"}},"created_at":{"type":"string","format":"date-time"},"accounting_entries":{"type":"array","description":"Accounting entry ids linked to this activity report (`invoice` / `expenses`). Empty until validated.","items":{"$ref":"#/components/schemas/ActivityReportAccountingStubPublic"}},"timesheets":{"type":"array","description":"All timesheet lines for this activity report (discriminated by `type`). Empty array if none.","items":{"$ref":"#/components/schemas/ActivityReportTimesheetLinePublic"}}}},"MissionDeliverableCatalogItem":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"quantity":{"type":"integer"},"amount_excl_vat":{"type":"number"},"order_index":{"type":"integer"}}},"ActivityReportTimesheetLinePublic":{"description":"Timesheet lines for the activity report. `type` discriminates the object shape.\nFor `hourly` and `daily` missions, the API returns one row per calendar day in `report_month`: days without declared time appear as zero-fill lines with `hours: 0` or `days: 0`, `description: null`, and a deterministic UUID in `id`. Declared days use their own `id`. Lines are sorted by `date`, then `id`. `monthly` / `deliverable` rows follow day-based lines.\n`description` is `null` when empty (never an empty string).\n","oneOf":[{"$ref":"#/components/schemas/ActivityReportTimesheetLineHourlyPublic"},{"$ref":"#/components/schemas/ActivityReportTimesheetLineDailyPublic"},{"$ref":"#/components/schemas/ActivityReportTimesheetLineMonthlyPublic"},{"$ref":"#/components/schemas/ActivityReportTimesheetLineDeliverablePublic"}],"discriminator":{"propertyName":"type","mapping":{"hourly":"#/components/schemas/ActivityReportTimesheetLineHourlyPublic","daily":"#/components/schemas/ActivityReportTimesheetLineDailyPublic","monthly":"#/components/schemas/ActivityReportTimesheetLineMonthlyPublic","deliverable":"#/components/schemas/ActivityReportTimesheetLineDeliverablePublic"}}},"ActivityReportTimesheetLineHourlyPublic":{"type":"object","required":["id","type","description"],"description":"Hours per calendar day. Missing days in the month are returned as zero-fill rows with `hours: 0`.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["hourly"]},"description":{"type":"string","nullable":true,"description":"Comment or line description on the CRA; null when empty."},"date":{"type":"string","format":"date","nullable":true,"description":"Activity day (YYYY-MM-DD)."},"hours":{"type":"number","nullable":true,"description":"Declared hours for this line; `0` on zero-fill days."},"project_code_id":{"type":"string","format":"uuid","nullable":true,"description":"Project code billed on this line. Present when the mission has multiple project codes; omitted or `null` for single-code missions.\n"}}},"ActivityReportTimesheetLineDailyPublic":{"type":"object","required":["id","type","description"],"description":"Days per calendar day. Missing days in the month are returned as zero-fill rows with `days: 0`.","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["daily"]},"description":{"type":"string","nullable":true,"description":"Line comment on the CRA; null when empty."},"date":{"type":"string","format":"date","nullable":true},"days":{"type":"number","nullable":true,"description":"Declared days for this line; `0` on zero-fill days."},"project_code_id":{"type":"string","format":"uuid","nullable":true,"description":"Project code billed on this line when the mission has multiple project codes."}}},"ActivityReportTimesheetLineMonthlyPublic":{"type":"object","required":["id","type","description"],"description":"Activity or billing line for a calendar month (quantities and totals live on the CRA / mission elsewhere).","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["monthly"]},"description":{"type":"string","nullable":true,"description":"Line comment on the CRA; null when empty."},"month":{"type":"string","nullable":true,"pattern":"^[0-9]{4}-[0-9]{2}$","description":"Month key YYYY-MM."},"project_code_id":{"type":"string","format":"uuid","nullable":true,"description":"Project code billed on this line when the mission has multiple project codes."}}},"ActivityReportTimesheetLineDeliverablePublic":{"type":"object","required":["id","type","description","comment"],"description":"One deliverable line. Structured payloads may return `comment` separately with `description` set to null (deliverable name in `deliverable`).\n","properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["deliverable"]},"description":{"type":"string","nullable":true,"description":"Optional label; null when only structured deliverable fields are present (use `deliverable` + `comment`)."},"comment":{"type":"string","nullable":true,"description":"Optional deliverable comment from the stored JSON (`comment` field); `null` when unset."},"deliverable":{"type":"string","nullable":true,"description":"Free-text name or label of the deliverable."},"date":{"type":"string","format":"date","nullable":true},"amount":{"type":"number","nullable":true},"project_code_id":{"type":"string","format":"uuid","nullable":true,"description":"Project code billed on this line when the mission has multiple project codes."}}},"ActivityReportAccountingStubPublic":{"type":"object","required":["id","type"],"properties":{"id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["invoice","expenses"]}}},"AccountingEntryPublic":{"type":"object","required":["id","activity_report_id","type","status","amount_excl_vat","vat_amount","amount_incl_vat","currency","invoice_number","file_name","freelancer","paid_at","sent_to_accounting_at","created_at","project_codes"],"properties":{"id":{"type":"string","format":"uuid"},"activity_report_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["invoice","expenses"]},"status":{"type":"string","enum":["waiting_payment","paid"]},"amount_excl_vat":{"type":"number"},"vat_amount":{"type":"number"},"amount_incl_vat":{"type":"number"},"currency":{"type":"string","description":"ISO 4217 currency code of the entry's amounts, fixed at entry creation (e.g. `EUR`, `USD`). Defaults to `EUR`."},"invoice_number":{"type":"string","nullable":true,"description":"Freelancer invoice number when **`type`** is **`invoice`**; null for **`expenses`** or if unset."},"file_name":{"type":"string","nullable":true,"description":"Uploaded invoice file name (`invoice`) or generated expense summary PDF name (`expenses`, `note-de-frais-{activity_report_id}.pdf`).\n"},"freelancer":{"$ref":"#/components/schemas/ActivityReportFreelancerPublic"},"paid_at":{"type":"string","format":"date-time","nullable":true},"sent_to_accounting_at":{"type":"string","format":"date-time","nullable":true,"description":"Timestamp when the entry was sent to the team accounting tool (email export). `null` if not yet sent.\n"},"created_at":{"type":"string","format":"date-time"},"project_codes":{"type":"array","description":"For **`type: invoice`**, invoice amount excl. VAT split by project code (same rules as activity reports). Empty for **`type: expenses`** entries.\n","items":{"$ref":"#/components/schemas/ProjectCodeAmountPublic"}}}},"PaginatedAccountingEntries":{"type":"object","required":["items","total","current_page","per_page"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AccountingEntryPublic"}},"total":{"type":"integer"},"current_page":{"type":"integer"},"per_page":{"type":"integer"}}},"AccountingEntryMarkPaidRequest":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["paid"],"description":"Must be **`paid`** (only marking as paid is supported via this API)."}}},"ActivityReportDetail":{"$ref":"#/components/schemas/ActivityReportListItemPublic"}},"responses":{"Unauthorized":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"ForbiddenError":{"description":"Insufficient scope or forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"RateLimited":{"description":"Too many requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"InternalError":{"description":"Server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}},"PublicError":{"description":"Client error (typically HTTP 400).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicError"}}}}}}}