FieldstubDocs › Budget code errors

Every Procore budget code error on a change event line item

If you are posting change event line items into Procore and getting a 400 about a budget code, there are only four errors you can be looking at, and each one means something different. This page has all of them with the exact response body.

The more important half is at the bottom: two malformed budget codes do not error at all. They return 200, the line item is created, and the money lands on a code nobody reviews. If your integration is quiet and your costs are wrong, that is what happened.

Last updated 2026-08-29 · Every row posted against a live Procore sandbox on 2026-08-29, change event 447023 · Read as markdown

The full matrix#

One valid control and five ways to get it wrong, all posted to POST /rest/v1.0/change_events/{id}/line_items?project_id={project_id}.

What you send as budget_codeStatusResponse
{ "id": 1870754 } (a real WBS code)200Created, filed correctly. This is the only form that works.
{ "id": 99999999 }400{"errors":{"base":["Wbs Code with ID 99999999 not found"]}}
{ "id": "not-a-number" }400{"errors":{"params":{"budget_code":{"id":["must be an integer"]}}}}
field omitted entirely400{"errors":{"params":{"budget_code":["is missing"]}}}
{ "segment_items": [...] }200Created, filed blank. No error, no warning.
{} (empty object)200Created, filed blank. No error, no warning.
Read the last two rows again. Procore rejects a budget code that is absent and a budget code whose id is wrong, but accepts a budget code that is empty or shaped differently. The validation checks that the field is there and that an id, if present, resolves. It does not check that you actually named a code.

What each error means#

budget_code: ["is missing"]: you omitted the field. Line items will not be created without it, which is the one place Procore is strict. A bare cost_code_id gets the same error, because a cost code is not a budget code.

budget_code: {id: ["must be an integer"]}: you sent a string. Usually a code read out of a spreadsheet or a query parameter that never got cast.

base: ["Wbs Code with ID 99999999 not found"]: the most useful error Procore returns, because it is the only place in the whole exchange that names the entity out loud. The field is called budget_code and it wants a WBS code id. Those are the same thing under two names, and the error is where you find out.

That last one is also what you get if you post a budget line item id, which is a different object with its own ids. It looks like a plausible number and it is not the right one.

The two that do not error#

Both of these were created successfully and both landed on the project blank WBS code, id 1870469, flat_code: "":

"budget_code": { "segment_items": [ { "segment_id": 1, "segment_item_id": 2 } ] }
"budget_code": { }

The segment_items form is the one people reach for, because it mirrors how the work breakdown structure is actually shaped and it is what the WBS endpoints hand you. It is accepted and thrown away.

The empty object is worse, because it is what a serialiser produces when the code you meant to attach was null. Nothing in your code is obviously broken. Nothing in the response says anything is wrong. The line item exists, the amount is right, and the cost is filed where nobody looks.

An integration built on either form passes its own tests. It writes clean 200s in production for months, and the first person to notice is whoever reconciles the budget.

A cost table from the Fieldstub review queue. Five rows of labor, equipment and materials, each showing the named WBS code it will be filed against rather than a blank one: 03-300.L Cast-in-Place Concrete Labor, 03-300.E Equipment, 03-300.M Materials. The rows total $2,112.00 above a line reading "Where each line will be filed in Procore."
The reason a person is in this loop at all. A line with no code cannot be approved by accident, because the API it is going to will take one without complaining.

And the other half of that: a line the router could not place does not quietly go anywhere.

A ticket in the Fieldstub review queue with one labor line showing "Not routed (do not file)" in its budget code column while the equipment and materials lines carry real codes. A warning below reads "1 line not on a budget code. Procore will accept a blank code with no warning. Tick the box if you really mean to file them blank," with an unticked checkbox labelled "File blank anyway".
The blank code is still reachable, because sometimes it is genuinely what somebody means. It just cannot happen without a person ticking a box that says so.

How to get a real WBS code id#

List them for the project:

GET /rest/v1.0/projects/{project_id}/work_breakdown_structure/wbs_codes

Each has an id and a flat_code that reads as cost code plus cost type letter, like 01-000.E. The letters are Labor, Materials, Equipment, Other. Post the id, not the flat_code.

The catch, and it is the one that makes this hard rather than tedious: a WBS code only exists for a cost code and cost type combination that is already in the budget. Extra work is unplanned by definition, so the code you need is routinely the one that does not exist yet. Procore budget codes and the blank code trap covers what to do about that.

Checking whether it already happened to you#

Read your line items back and look at the budget code you got, not the one you sent:

GET /rest/v1.0/change_events/{id}/line_items?project_id={project_id}

Any line where budget_code.flat_code is an empty string is filed blank. If you are seeing your own project blank code id repeated across line items that were meant to be different, that is this bug and not a data problem.

Assert on the response, not the status. A test that checks for 200 passes on both of the broken forms. A test that checks the returned budget_code.id matches the one you sent catches it the first time.

Questions

What does "Wbs Code with ID not found" mean in Procore?

The id you sent in budget_code does not match any WBS code on that project. Procore calls the same object a budget code in the field name and a WBS code in the error. List them at /rest/v1.0/projects/{project_id}/work_breakdown_structure/wbs_codes and post the id from there.

Why is Procore saying budget_code is missing when I sent a cost code?

A cost code is not a budget code. Line items need a WBS code id, which represents a cost code and cost type combination that exists in the project budget. Sending cost_code_id returns the same missing error.

Why did my change event line item get a blank budget code with no error?

You sent either the segment_items form or an empty object. Both return 200, create the line item, and file it on the project blank WBS code. Verified against a Procore sandbox on 29 August 2026.

Does Procore validate that a budget code was actually chosen?

No. It validates that the field is present and that an id, if you send one, resolves to a real WBS code. An empty object satisfies both checks and means nothing, so it passes.

Put a code on one job and see what comes back.

Fieldstub turns a phone and a QR code into a signed Change Event in Procore. The field needs no login and no seat.

Start free