Project Funding

Edited

Title

Project Funding Upload API (V3) is used for creating bulk entries of project funding items.

Description

The Project Funding API allows programmatic upload and management of project funding records in Fluid. It supports uploading bulk project funding entries via a RESTful JSON API.

Project funding items represent the allocated budget for a project, optionally broken down by fiscal year and expense category. Each record stores the funding amount in local currency, default currency (converted), and restated currency (if configured). When fiscal year is omitted, the record is treated as a Life-to-Date (full project) funding entry.

Required Permission

The following Fluid roles are required to use this API:

Role

Description

Financial Administrator (or App Admin)

Required to create or update project funding. The Show Project Financials feature must be active and the user must hold Financial Administrator or AppAdmin. Users without this combination receive a 403 Forbidden response.

User

Base role required for all API access.

Endpoints

Method

URL

Content-Type

POST

{rooturl}/rest/api/projectfunding/bulk

application/json

Request Body

Each request is treated as the complete funding snapshot for every project it contains. On submission, existing rows for those projects are replaced by the rows in the payload.

For accurate, predictable results:

  • Send each project's full funding in one request — include every fiscal year, expense category, and the full-project (Life-to-Date) entry. Anything omitted will be removed.

  • Use the bulk endpoint (POST /rest/api/projectfunding/bulk) — it is sized to hold a project's complete funding history in a single call.

  • Combine multiple projects in one request when convenient. Each project is processed independently, so unrelated projects are unaffected.

Tip: Treat each call as "this is the complete funding picture for project X", not "add these rows to project X".

Example

Single bulk request containing the full funding set for MM1000 (three FY rows + one Life-to-Date row):

[
  {
    "fields": {
      "projectRef": "MM1000",
      "fiscalYear": 2024,
      "expenseCategory": "Resource Cost",
      "amount": 50000
    }
  },
  {
    "fields": {
      "projectRef": "MM1000",
      "fiscalYear": 2024,
      "expenseCategory": "Non-resource Cost",
      "amount": 20000
    }
  },
  {
    "fields": {
      "projectRef": "MM1000",
      "fiscalYear": 2025,
      "expenseCategory": "Resource Cost",
      "amount": 70000
    }
  },
  {
    "fields": {
      "projectRef": "MM1000",
      "expenseCategory": "Resource Cost",
      "amount": 120000
    }
  }
]

If MM1000 is split across two calls, the second call's payload becomes the new state for MM1000 — rows sent in the first call are no longer retained.

Type

JSON array for bulk create.

Full Field Reference

Field

Type

Required?

Description

projectRef

string

Conditional

External reference of the project (e.g., "MM1000"). At least one of projectRef, projectId, or projectGuid is required.

projectId

integer

Conditional

Integer principal ID of the project. At least one of projectRef, projectId, or projectGuid is required.

projectGuid

string

Conditional

GUID of the project (e.g., "873a0b87-f71c-43a0-b45a-25a1152b6ff1"). At least one of projectRef, projectId, or projectGuid is required.

fiscalYear

integer

No

The fiscal year for this funding entry (e.g., 2024). If omitted or null, the record is treated as a Life-to-Date / full project funding entry.

expenseCategory

string

No

The expense category for the funding (e.g., "Non-resource Cost"). If provided, must match a valid expense category configured in Fluid.

localCurrencyCode

string

No

ISO currency code for the local currency (e.g., "USD", "GBP"). If omitted, defaults to the system default currency.

amount

decimal

Yes

The total funding amount in local currency. A value of 0 will delete the matching fiscal year funding record.

capex

decimal

No

Capital expenditure portion of the funding in local currency. If both capex and opex are 0, the full amount is applied to opex.

opex

decimal

No

Operating expenditure portion of the funding in local currency. If both capex and opex are 0, the full amount is applied to opex.

Custom Properties

NOTE: Custom properties are currently not supported for project funding records via this API.

Example Requests

Bulk Create Request

POST {rooturl}/rest/api/projectfunding/bulk
Content-Type: application/json

[
  {
    "Fields": {
      "ProjectRef": "MM1000",
      "FiscalYear": 2024,
      "ExpenseCategory": "Non-resource Cost",
      "Amount": 50000.00
    }
  },
  {
    "Fields": {
      "ProjectRef": "MM1000",
      "FiscalYear": 2025,
      "ExpenseCategory": "Non-resource Cost",
      "Amount": 60000.00
    }
  },
  {
    "Fields": {
      "ProjectRef": "HD1000",
      "FiscalYear": 2024,
      "ExpenseCategory": "Resource Cost",
      "Amount": 80000.00,
      "Capex": 20000.00,
      "Opex": 60000.00
    }
  }
]

Response

Bulk Create Response

Returns a BulkProjectFundingResponseModel with:

Field

Type

Description

Status

string

Overall status: "success" (all valid), "partial" (some valid), or "failed" (none valid).

TotalCount

integer

Total number of records submitted.

ValidCount

integer

Number of records successfully processed.

InvalidCount

integer

Number of records that failed validation or processing.

CorrelationId

string

Unique correlation ID for tracking this request.

Results

array

Per-row results, ordered by RowIndex. Each entry contains Fields.Id, Fields.IsValid, Fields.Status, Fields.RowIndex, and Fields.ValidationMessages.

Example Bulk Response (Partial Success)

{
  "Status": "partial",
  "TotalCount": 3,
  "ValidCount": 2,
  "InvalidCount": 1,
  "CorrelationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "Results": [
    {
      "Fields": {        
        "IsValid": true,
        "Status": "valid",
        "RowIndex": 1,
        "ValidationMessages": []
      }
    },
    {
      "Fields": {
        "IsValid": true,
        "Status": "valid",
        "RowIndex": 2,
        "ValidationMessages": []
      }
    },
    {
      "Fields": {
        "IsValid": false,
        "Status": "invalid",
        "RowIndex": 3,
        "ValidationMessages": [
          "This row was skipped as no projects could be found with ProjectRef specified in the file."
        ]
      }
    }
  ]
}

Validation Rules

  1. Project Identifier: At least one of ProjectRef, ProjectId, or ProjectGuid must be provided. The project must exist in the Fluid database.

  2. Amount: The Amount field is required. A value of 0 will remove the existing fiscal year funding record for that project and expense category combination.

  3. ExpenseCategory: Optional. The original Excel-upload loader treated this as optional, and the V3 API preserves that behaviour for parity.

  4. Currency Code: Optional. Currency Code is defaulted to the system currency when not provided, and it is ignored when no Secondary Currency is defined in Fluid system.

  5. FiscalYear: Optional. If omitted or null, the record is treated as a Life-to-Date / full project funding entry.

  6. Capex and Opex: Both optional. If neither is provided (or both are 0), the full Amount is applied to Opex.

  7. Duplicate Handling: If a record already exists for the same project, fiscal year, and expense category, it will be updated (else a new record will be created). The entire set of records for a given project + fiscal year combination is replaced on each upload.

  8. Full Year Auto-Generation: If fiscal year records exist but no explicit Life-to-Date record is provided, a full year summary record is automatically generated by summing all fiscal year records per project and expense category.

HTTP Status Codes

Code

Description

200 OK

Request processed. Check Status in the response for "success", "partial", or "failed".

400 Bad Request

The request body is malformed or missing required fields.

401 Unauthorized

The caller is not authenticated.

403 Forbidden

The Show Project Financials feature must be active and the user must hold Financial Administrator or AppAdmin. Users without this combination receive a 403 Forbidden response.

429 Too Many Requests

Rate limit exceeded. See RateLimit-* response headers.

500 Internal Server Error

An unexpected error occurred during processing.

Rate Limits

Endpoint

Requests

Window

POST {rooturl}/rest/api/projectfunding/bulk

100

10 seconds

Was this article helpful?

Sorry about that! Care to tell us more?

Thanks for the feedback!

There was an issue submitting your feedback
Please check your connection and try again.