API documentation
Technical documentation for integrating with Endre.
Endre API provides project-related data for authenticated users. This API is RESTful and supports standard HTTP methods like GET, POST, and PATCH.
All endpoints can be tested here: https://public-api.endre.app/docs
Authentication
Get Access Token
POST /token
Obtain a Bearer token using username and password.
-
Input: OAuth2 credentials (
username,password) -
Output: JWT access token (
access_token,token_type)
Use the returned token in the Authorization header for all subsequent requests: Authorization: Bearer <token>
Includes
The /cases endpoints support an include query parameter to embed related data directly in each case object:
?include=cost_items,tags,production_codes,invoices,external_references,relations
Multiple includes can be specified as a comma-separated list.
Example: ?include=cost_items,tags
Organizations
Fetch Organizations
GET /v1/organizations
Fetch organizations for the authenticated user.
Response
-
Id(UUID) -
Name(string)
Fetch Specific Organization
GET /v1/organizations/{organization_id}
Fetch a specific organization.
Input
organization_id(UUID)
Response
-
Id(UUID) -
Name(string)
Projects
Fetch User Projects
GET /v1/projects
Retrieve the list of projects the authenticated user has access to.
Response
-
List of projects with:
-
Id(UUID): Unique project identifier -
Name(string):[ProjectNumber] - [ProjectName] -
ProjectName(string): Project name -
ProjectNumber(string): Project number -
OrganizationId(UUID): Organization identifier -
IsFinished(boolean): Indicates if the project is finished
-
Empty Case Returns a 404 error if no projects are available.
Create Project
POST /v1/projects
Create a new project within the specified organization. Your organization will automatically be linked to the project with the specified role.
Parameters
-
project_name(string, required): Project name -
organization_id(UUID, required): Organization identifier (from/v1/organizations) -
email(string, optional): Project administrator email -
project_number(string, optional): Project number -
role(string, optional): Role in the project —Contractor,Subcontractor,Builder(default:Contractor)
Fetch Project Details
GET /v1/projects/{project_id}
Retrieve details for a specific project.
Input
project_id(UUID)
Response
-
Id(UUID) -
Name(string):[ProjectNumber] - [ProjectName] -
ProjectName(string) -
ProjectNumber(string) -
OrganizationId(UUID) -
IsFinished(boolean)
Access Validation Returns 403 if user lacks access.
Update Project
PATCH /v1/projects/{project_id}
Update a project's basic properties.
Input
project_id(UUID)
Request Body
-
project_name(string, optional) -
project_number(string, optional) -
is_finished(boolean, optional):true= finished,false= not finished
Fetch Project Amounts
GET /v1/projects/{project_id}/amounts
Retrieve aggregated amounts by month.
Input
-
project_id(UUID) -
start_date(optional, yyyy-mm-dd) -
end_date(optional, yyyy-mm-dd) -
case_types(optional, repeat param:?case_types=1&case_types=2):-
1 = Notice
-
2 = Claim
-
3 = Change Order
-
4 = Price Request
-
5 = Technical Clarification
-
6 = Builder Message
-
7 = Contract
-
Response
-
ProjectId(UUID) -
Year(int) -
Month(int) -
CaseType(string) -
TotalAmount(decimal) -
TotalAcceptedAmount(decimal) -
TotalDeclinedAmount(decimal) -
TotalNotHandledAmount(decimal)
Fetch Project Tags
GET /v1/projects/{project_id}/tags
Fetch project-level tags.
Response
Text(string)
Create Project Tag
POST /v1/projects/{project_id}/tags
Create a new tag on the caller's project organization.
Request Body
text(string, required)
Response
-
message(string) -
tag_id(UUID) -
text(string)
Project Organizations
Fetch Project Organizations
GET /v1/projects/{project_id}/organizations
Retrieve all organizations on a project.
Response
-
Id(UUID): Project organization ID -
Name(string) -
OrganizationNumber(string) -
Role(string):Contractor,Subcontractor, orBuilder -
OrganizationId(UUID)
Add Organization to Project
POST /v1/projects/{project_id}/organizations
Add an organization to a project. If the organization (matched by name and optional org number) does not exist, it will be created.
Parameters
-
organization_name(string, required) -
role(string, required):Contractor,Subcontractor, orBuilder -
organization_number(string, optional)
Response
-
message(string) -
organization:-
Id(UUID): Project organization ID -
OrganizationId(UUID) -
Name(string) -
Role(string)
-
Fetch Specific Project Organization
GET /v1/projects/{project_id}/organizations/{project_organization_id}
Retrieve a specific organization on a project.
Input
-
project_id(UUID) -
project_organization_id(UUID)
Response
-
Id(UUID) -
Name(string) -
OrganizationNumber(string) -
Role(string) -
OrganizationId(UUID)
Update Project Organization
PATCH /v1/projects/{project_id}/organizations/{project_organization_id}
Update the role of an organization on a project.
Parameters
role(string, required):Contractor,Subcontractor, orBuilder
Response
-
message(string) -
organization:-
Id(UUID): Project organization ID -
Role(string)
-
Project Organization Users
List Organization Users
GET /v1/projects/{project_id}/organizations/{organization_id}/users
Fetch all users belonging to a specific project organization.
Response
-
Id(UUID) -
Mail(string) -
DisplayName(string)
Add User to Organization
POST /v1/projects/{project_id}/organizations/{organization_id}/users
Add a user (by email) to a project organization. If no user with the given email exists, one will be created — they will then need to register upon first login.
Parameters
mail(string, required): User email address
Response
-
message(string) -
user_id(UUID) -
mail(string)
Cases
Fetch Cases for a Project
GET /v1/projects/{project_id}/cases
Retrieve cases (change logs) for a project.
Use the include parameter to embed related data directly in each case object. Multiple includes can be specified as a comma-separated list.
Parameters
include(optional):cost_items,tags,production_codes,invoices,external_references,relations
Response Each case includes:
-
Id(UUID) -
CaseNumber(string) -
Title(string) -
Sender(string) -
SenderId(UUID) -
Receiver(string) -
ReceiverId(UUID) -
CounterPartRole(string) -
Type(string): Notice, Claim, Change Order, Price Request, Technical Clarification, Builder Message, Contract -
Status(string): New, In Progress, Accepted, Rejected, Priced, Draft, etc. -
DueDate(datetime) -
Version(int) -
Description(HTML string) -
CreatedDate(datetime) -
ModifiedDate(datetime) -
CreatedBy(string) -
ExtensionOfTimeDays(int) -
AcceptedExtensionOfTimeDays(int) -
TotalAmount(decimal) -
AcceptedAmount(decimal) -
DeclinedAmount(decimal) -
NotHandledAmount(decimal) -
EstimatedAmount(decimal) -
InvoicedAmount(decimal) -
IsArchived(boolean) -
RelatedCases(UUID[]) -
Url(string)
Access Validation Returns 403 if unauthorized.
Fetch Case Details
GET /v1/projects/{project_id}/cases/{case_id}
Retrieve detailed information for a specific case.
Use the include parameter to embed related data directly in the case object.
Input
-
project_id(UUID) -
case_id(UUID) -
include(optional):cost_items,tags,production_codes,invoices,external_references,relations
Response Same fields as the list response above.
Fetch Cost Items
GET /v1/projects/{project_id}/cases/{case_id}/cost-items
Retrieve cost items for a specific case. Surcharge logic is applied based on the user's organization role.
Response
-
Id(UUID) -
PostNr(string) -
Description(string) -
Company(string) -
Unit(string) -
Volume(decimal) -
UnitPrice(decimal) -
Surcharge(decimal) -
Sum(decimal) -
Status(string): Unprocessed, Accepted, Declined, No Price, New Price Requested -
IsEstimate(boolean) -
ProductionCode(string) -
RowIndex(int) -
DerivedFrom(UUID[]): Source cost item IDs this item was copied or imported from
Fetch Tags for a Case
GET /v1/projects/{project_id}/cases/{case_id}/tags
Response
Text(string)
Fetch Production Codes
GET /v1/projects/{project_id}/cases/{case_id}/prod-codes
Response
Code(string)
Fetch Invoices
GET /v1/projects/{project_id}/cases/{case_id}/invoices
Response
-
Id(UUID) -
InvoiceNumber(string) -
CaseNumber(string) -
Amount(decimal) -
InvoiceDate(datetime) -
DueDate(datetime) -
PayDate(datetime) -
PaidAmount(decimal) -
OutstandingAmount(decimal) -
PlannedInvoiceAmount(decimal) -
PlannedInvoiceDate(datetime) -
Comment(string) -
Status(string):planned,sent,paid,overdue,cancelled
Create Invoice
POST /v1/projects/{project_id}/cases/{case_id}/invoices
Create an invoice on a case.
Request Body (all fields optional)
-
InvoiceNumber(string) -
InvoiceDate(datetime) -
DueDate(datetime) -
PayDate(datetime) -
Amount(decimal) -
PaidAmount(decimal) -
OutstandingAmount(decimal) -
PlannedInvoiceAmount(decimal) -
PlannedInvoiceDate(datetime) -
Comment(string) -
Status(string):planned,sent,paid,overdue,cancelled
Response Returns the created invoice object.
Update Invoice
PATCH /v1/projects/{project_id}/cases/{case_id}/invoices/{invoice_id}
Patch fields on an existing invoice. Only the keys supplied in the body are updated.
Input
invoice_id(UUID)
Request Body Same optional fields as Create Invoice above.
Response Returns the updated invoice object.
Download Case PDF
GET /v1/projects/{project_id}/cases/{case_id}/pdf
Download the case rendered as a single PDF (no ZIP wrapping, no embedded attachments).
Input
-
project_id(UUID) -
case_id(UUID)
Response Streams the PDF binary.
List Attachments
GET /v1/projects/{project_id}/cases/{case_id}/attachments
Returns metadata for every attachment on the case across all versions.
Response
-
Id(UUID) -
Name(string) -
Description(string) -
FileType(string) -
AttachmentType(string) -
CreatedDate(datetime) -
ChangeVersionId(UUID) -
Version(int)
Download Attachment
GET /v1/projects/{project_id}/cases/{case_id}/attachments/{attachment_id}
Streams a single attachment binary with its original MIME type.
Input
attachment_id(UUID)
Response Streams the file binary.
Fetch External References
GET /v1/projects/{project_id}/cases/{case_id}/external-references
Response
-
Name(string) -
Url(string) -
Description(string) -
Version(integer)
Fetch Relations
GET /v1/projects/{project_id}/cases/{case_id}/relations
Response
-
CaseNumber(string) -
Type(string): Relation type — relates to, replaced by, replaces, etc.
Contracts
List Project Contracts
GET /v1/projects/{project_id}/contracts
Fetch all contracts for a specific project.
Response
-
Id(UUID) -
Name(string) -
Description(string) -
PartOneProjectOrganizationId(UUID): The ordering party -
PartTwoProjectOrganizationId(UUID): The executing party -
Value(decimal)
Create Contract
POST /v1/projects/{project_id}/contracts
Create a new contract for a project. Part one is the ordering party and part two is the executing party.
Request Body
-
name(string, required) -
description(string, optional) -
part_one_project_organization_id(UUID, optional) -
part_two_project_organization_id(UUID, optional) -
value(decimal, optional)
Response
-
message(string) -
contract:Id,Name,Description,PartOneProjectOrganizationId,PartTwoProjectOrganizationId,Value
Update Contract
PATCH /v1/projects/{project_id}/contracts/{contract_id}
Update a contract's fields. Only provided fields are updated.
Input
contract_id(UUID)
Request Body Same optional fields as Create Contract above.
Response
-
message(string) -
Updated contract object.
List Contract Cost Items
GET /v1/projects/{project_id}/contracts/{contract_id}/cost-items
Fetch all cost items for a specific contract.
Response
-
Id(UUID) -
Description(string) -
Unit(string) -
Volume(decimal) -
UnitPrice(decimal) -
Sum(decimal)
Create Contract Cost Item
POST /v1/projects/{project_id}/contracts/{contract_id}/cost-items
Create a new cost item linked to a specific contract.
Request Body (all fields optional)
-
description(string) -
unit(string) -
volume(decimal) -
unit_price(decimal)
Response
-
message(string) -
contract_cost_item:Id,Description,Unit,Volume,UnitPrice,Sum
List Contract Files
GET /v1/projects/{project_id}/contracts/{contract_id}/files
Fetch all files attached to a contract.
Response
-
Id(UUID) -
FileName(string) -
Description(string) -
FileSize(integer) -
ContentType(string) -
ContainerName(string) -
FilePath(string) -
ContractId(UUID) -
ProjectId(UUID)
Upload File to Contract
POST /v1/projects/{project_id}/contracts/{contract_id}/files
Upload a file and attach it to a contract. Request must use multipart/form-data.
Request Body
-
file(binary, required) -
description(string, optional)
Response
-
message(string) -
file_asset:Id,FileName,Description,FileSize,ContentType
Authorization
All endpoints require a valid JWT Bearer token obtained via the /token endpoint.