Project External References
A project external reference is one allowed value for one of the external reference fields on a project or work order. Together they form per-company lists — the valid external project numbers for a company, the valid sub project numbers for a project, and so on.
They matter because they are enforced. When a company has values configured for a type, Ditio rejects project and work order writes carrying anything else, so keeping these lists in step with your ERP is what keeps your integration writing successfully.
All endpoints use the ditioapiv3 scope — see
Which scope for which host.
Examples use the environment variables from Environments and default to the test environment.
Reference types
Section titled “Reference types”externalRefType is one of five values (matched case-insensitively):
| Type | What it governs |
|---|---|
ExternalProjectNumber | Valid values for a project’s externalProjectNumber |
ExternalSubProjectNumber | Valid sub project numbers within one project |
ProcessCode | Process codes available on a project’s work orders |
WBSCode | Work breakdown structure codes |
ExternalDim02 | Values for the second external dimension |
The object
Section titled “The object”| Field | Type | Notes |
|---|---|---|
id | string | Ditio id. Omit when creating; required when updating |
externalRefType | string | Required. One of the five types above |
externalRefValue | string | Required. The value itself — this is what gets matched |
projNumber | string | Required for ExternalSubProjectNumber and ProcessCode. Scopes the value to one project — but the two types expect different numbers, see the note below |
name | string | Display name shown next to the value |
groupName | string | Optional grouping for long lists |
disabled | bool | Hides the value from the pickers in Ditio’s own UI. It does not stop the API accepting it — see Disable and enable |
invoiceable | bool | Marks hours booked to a work order carrying this code as invoiceable |
structureId | string | Optional. Narrows which references are offered on a project |
companyId | string | Optional on create — see Company scoping |
financialEndDate | datetime | Optional, and not inert on ExternalProjectNumber — see Financial end date |
All values of a type
Section titled “All values of a type”curl -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/type/ExternalProjectNumber"This is the list a project write is validated against. Call it first when a write fails — if your value is not in the response, that is why.
Sub project numbers for one project
Section titled “Sub project numbers for one project”curl -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/type/ExternalSubProjectNumber/project/40001"The path segment is the project’s externalProjectNumber, per the note above.
A single reference
Section titled “A single reference”# By Ditio idcurl -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/{id}"
# By valuecurl -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/type/ExternalProjectNumber/externalRef/40001"
# By value within a projectcurl -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/type/ExternalSubProjectNumber/project/40001/externalRef/40001-01"Structure ids
Section titled “Structure ids”curl -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/structure-ids/type/WBSCode"Returns the distinct non-empty structureId values in use for a type.
Create
Section titled “Create”curl -X POST "$DITIO_API_BASE/api/project-external-reference" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{ "externalRefType": "ExternalProjectNumber", "externalRefValue": "40001", "name": "Example project" }'Sub project numbers additionally need projNumber:
curl -X POST "$DITIO_API_BASE/api/project-external-reference" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{ "externalRefType": "ExternalSubProjectNumber", "externalRefValue": "40001-01", "projNumber": "40001", "name": "Groundworks" }'Posting a body that carries an id updates that reference instead of creating a
new one.
Update
Section titled “Update”curl -X PUT "$DITIO_API_BASE/api/project-external-reference/{id}" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{ "id": "{id}", "externalRefType": "ExternalProjectNumber", "externalRefValue": "40001", "name": "Example project (updated)" }'PUT replaces the whole document — every field you omit is cleared,
including invoiceable, structureId, groupName, disabled and
financialEndDate. Read the reference first and send it back in full with your
changes applied, or you will silently reset the fields you left out. Clearing
invoiceable stops hours on that code being marked invoiceable, and clearing
financialEndDate has the side effect described below.
You cannot change an existing reference’s externalRefType; that is rejected.
Its owning company is also fixed at creation and cannot be moved.
Disable and enable
Section titled “Disable and enable”curl -X PUT -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/disable/{id}"
curl -X PUT -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/enable/{id}"disabled is a presentation flag for Ditio’s own UI. It marks the value as
disabled in the pickers so people stop choosing it by hand, and the read
endpoints keep returning it so historical data still resolves to a name.
It does not stop the value being written. The validation that rejects
external project and sub project numbers compares against the whole list without
looking at disabled, so an integration can keep posting a disabled value
indefinitely and it will be accepted. If you need a value to stop being written
through the API, removing it is currently the only way — see the constraints on
Delete.
Delete
Section titled “Delete”curl -X DELETE -H "Authorization: Bearer $TOKEN" \ "$DITIO_API_BASE/api/project-external-reference/{id}"For ExternalProjectNumber, ExternalSubProjectNumber and ProcessCode this
is rejected with 403 while the value is still in use on any project or work
order, naming how many use it. Clear the value from those records first.
WBSCode and ExternalDim02 have no such guard and are deleted immediately;
existing references to them keep the raw value but stop resolving to a name.
Company scoping
Section titled “Company scoping”Reads return the references available in your company context, and creates land on the company that owns the list:
- If you send a
companyId, it must be part of your own company structure. - A parent company id, or a project company id, is stored against the parent company — the lists live at parent level and are shared by its project companies.
- A subsidiary company id is kept as sent.
- If you omit
companyId, your own company is used.
This is worth knowing when your integration authenticates as a project company: values you create are visible across that parent’s project companies, and values you read may have been created against the parent rather than the company you authenticated as.
When a write is rejected
Section titled “When a write is rejected”Both messages are returned with 400 Bad Request:
| Message | Meaning |
|---|---|
Extern prosjektnummer <value> er ikke en gyldig. Velg fra listen | The project’s externalProjectNumber is not in the company’s ExternalProjectNumber list |
Delprosjektnummer <value> er ikke en gyldig. Velg fra listen | The work order’s sub project number is not in the list configured for the project’s external project number |
Both fire only when the company has this validation enabled and has values configured for that type — a populated list alone does not mean writes are checked. Where they do apply, both treat an empty value as invalid, so the field is effectively required.
List the relevant type first. If your value is not in the response, that is why
the write failed, and creating it is the fix. Note that disabled is never the
reason — disabled values still pass validation.
Financial end date
Section titled “Financial end date”Setting financialEndDate on an ExternalProjectNumber reference is not just
metadata on the reference. Ditio finds every project in the company structure
whose externalProjectNumber matches the value and writes that same date onto
each of them.
This happens on create and on any update that changes the value — including
clearing it, which writes an empty date onto every matching project. Combined
with PUT being a full replace, an update that simply omits financialEndDate
will do exactly that.
Treat it as a bulk update of the matching projects rather than a property of the list entry, and leave it unset unless you intend that.
Related
Section titled “Related”- Projects (Integration API) — where
externalProjectNumberis set and validated - Work Orders (Integration API) — sub project number validation
- Projects & Resources (read-only) — on-demand project and work order lookups