ParakeetoDocumentation
On this page

estimate_project

What it answers

Run the Scope Predictor estimator for a described project: hours per task category fitted to the comparable projects you name (projectNames, at most 10, by Project Name from list_project_entries), the likely range, how similar each of the account's projects is to the brief, the account's ABR target and, when a range is given and the owner may see payroll, Direct Delivery Margin. targetAgi is required. Same calculation and figures as the Scope Predictor page for the same inputs. It estimates only: nothing is saved (list_saved_estimates and get_saved_estimate read what people saved). Direct Delivery Margin is derived from compensation: it is returned only when the current connection owner has People (payroll) grid view on this account, otherwise it is omitted with a compensation-withheld caveat; when it cannot be computed it says why in reasons. Numbers are decimal strings. Read parakeeto://methodology for shared response conventions and INVALID_ARGUMENT guidance.

Read-only.

Arguments

Argument Type Required Default Allowed values
account string (uuid) no — —
includeDefinitions boolean no true —
projectNames array of string yes — maxItems: 10
targetAgi string yes — pattern ^-?\d+(?:\.\d+)?$
overrides map of string to string no — —
brief object no — —
brief.serviceLine string no — maxLength: 200
brief.product string no — maxLength: 200
brief.client string no — maxLength: 200
brief.durationDays string no — pattern ^-?\d+(?:\.\d+)?$
range object no — —
range.from string yes — pattern ^\d{4}-\d{2}-\d{2}$
range.to string yes — pattern ^\d{4}-\d{2}-\d{2}$

Returned fields

The result is an envelope: ok: true with data, or ok: false with error. Error codes: MODEL_CALCULATOR_ACCESS_REQUIRED, PAYROLL_GRID_MISSING, PAYROLL_GRID_REQUIRED, PROJECT_GRID_REQUIRED, EXPENSE_GRID_REQUIRED, PAYROLL_ENTRY_REFERENCE_STALE, ACCOUNT_NOT_FOUND, ACCOUNT_CONFIGURATION_MISSING, NO_IMPORTED_TIME, NOTHING_IMPORTED, ACCOUNT_REQUIRED, NO_REACHABLE_ACCOUNTS, FEATURE_NOT_ENTITLED, PERMISSION_DENIED, CALCULATION_FAILED, INTERNAL_ERROR, INVALID_ARGUMENT.

  • data: object
    • data.account: string (uuid)
    • data.targetAgi: string (pattern ^-?\d+(?:\.\d+)?$)
    • data.comparables: array of object
      • data.comparables[].project: string
      • data.comparables[].client: string or null, optional
      • data.comparables[].product: string or null, optional
      • data.comparables[].serviceLine: string or null, optional
      • data.comparables[].status: string or null, optional
      • data.comparables[].agi: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.comparables[].plannedHours: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.comparables[].actualHours: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.comparables[].plannedAbr: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.comparables[].actualAbr: string or null, optional (pattern ^-?\d+(?:\.\d+)?$)
      • data.comparables[].startDate: string or null, optional
      • data.comparables[].firstUsedDate: string or null, optional
      • data.comparables[].endDate: string or null, optional
      • data.comparables[].lastUsedDate: string or null, optional
    • data.taskCategories: array of string
    • data.actuals: array of object
      • data.actuals[].project: string
      • data.actuals[].overallHours: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.actuals[].taskCategories: map of string to string
        • data.actuals[].taskCategories.*: string (pattern ^-?\d+(?:\.\d+)?$)
    • data.plans: array of object
      • data.plans[]: same shape as data.actuals[]
    • data.regressions: array of object
      • data.regressions[].taskCategory: string
      • data.regressions[].slope: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.regressions[].intercept: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.regressions[].predictedHours: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.regressions[].determinedHours: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.regressions[].overridden: boolean
    • data.totalDeterminedHours: string (pattern ^-?\d+(?:\.\d+)?$)
    • data.estimatedAbr: string (pattern ^-?\d+(?:\.\d+)?$)
    • data.likelyRange: object
      • data.likelyRange.status: string ("available", "approximate", "unavailable")
      • data.likelyRange.usableComparables: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.likelyRange.excludedComparables: array of object
        • data.likelyRange.excludedComparables[].project: string
        • data.likelyRange.excludedComparables[].agi: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.excludedComparables[].reason: string ("non-positive-agi")
      • data.likelyRange.reason: string or null
      • data.likelyRange.categories: array of object
        • data.likelyRange.categories[].taskCategory: string
        • data.likelyRange.categories[].low: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.categories[].middle: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.categories[].high: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.categories[].comparablesUsed: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.likelyRange.total: object or null
        • data.likelyRange.total.low: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.total.middle: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.total.high: string (pattern ^-?\d+(?:\.\d+)?$)
        • data.likelyRange.total.comparablesUsed: string (pattern ^-?\d+(?:\.\d+)?$)
    • data.similarity: object
      • data.similarity.pointsPossible: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.similarity.projects: array of object
        • data.similarity.projects[].project: string
        • data.similarity.projects[].score: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.similarity.closest: array of object
        • data.similarity.closest[]: same shape as data.similarity.projects[]
    • data.abrTarget: object or null
      • data.abrTarget.value: string (pattern ^-?\d+(?:\.\d+)?$)
      • data.abrTarget.months: array of string
    • data.directDeliveryMargin: object, optional
      • One of:
        • Variant 1 (status is "available"):
          • data.directDeliveryMargin.status: string ("available")
          • data.directDeliveryMargin.value: string (pattern ^-?\d+(?:\.\d+)?$)
          • data.directDeliveryMargin.directDeliveryCosts: string (pattern ^-?\d+(?:\.\d+)?$)
          • data.directDeliveryMargin.targetAgi: string (pattern ^-?\d+(?:\.\d+)?$)
          • data.directDeliveryMargin.costWindow: object
            • data.directDeliveryMargin.costWindow.startDate: string (pattern ^\d{4}-\d{2}-\d{2}$)
            • data.directDeliveryMargin.costWindow.endDate: string (pattern ^\d{4}-\d{2}-\d{2}$)
          • data.directDeliveryMargin.categories: array of object
            • data.directDeliveryMargin.categories[].taskCategory: string
            • data.directDeliveryMargin.categories[].estimatedHours: string (pattern ^-?\d+(?:\.\d+)?$)
            • data.directDeliveryMargin.categories[].hoursSource: string ("override", "median")
            • data.directDeliveryMargin.categories[].costPerDeliveryHour: string (pattern ^-?\d+(?:\.\d+)?$)
            • data.directDeliveryMargin.categories[].directDeliveryCost: string (pattern ^-?\d+(?:\.\d+)?$)
        • Variant 2 (status is "unavailable"):
          • data.directDeliveryMargin.status: string ("unavailable")
          • data.directDeliveryMargin.reasons: array of string
          • data.directDeliveryMargin.categoriesWithoutCostPerDeliveryHour: array of string
          • data.directDeliveryMargin.categoriesWithoutEstimatedHours: array of string
    • data.definitions: map of string to string, optional
      • data.definitions.*: string
    • data.caveats: array of object
      • data.caveats[].code: string
      • data.caveats[].message: string

On failure:

  • error: object
    • error.code: string ("MODEL_CALCULATOR_ACCESS_REQUIRED", "PAYROLL_GRID_MISSING", "PAYROLL_GRID_REQUIRED", "PROJECT_GRID_REQUIRED", "EXPENSE_GRID_REQUIRED", "PAYROLL_ENTRY_REFERENCE_STALE", "ACCOUNT_NOT_FOUND", "ACCOUNT_CONFIGURATION_MISSING", "NO_IMPORTED_TIME", "NOTHING_IMPORTED", "ACCOUNT_REQUIRED", "NO_REACHABLE_ACCOUNTS", "FEATURE_NOT_ENTITLED", "PERMISSION_DENIED", "CALCULATION_FAILED", "INTERNAL_ERROR", "INVALID_ARGUMENT")
    • error.argument: string, optional (minLength: 1)
    • error.message: string
    • error.accounts: array of object, optional
      • error.accounts[].id: string (uuid)
      • error.accounts[].name: string
    • error.payrollGrids: array of object, optional
      • error.payrollGrids[]: same shape as error.accounts[]
    • error.projectGrids: array of object, optional
      • error.projectGrids[]: same shape as error.accounts[]
    • error.expenseGrids: array of object, optional
      • error.expenseGrids[]: same shape as error.accounts[]
    • error.context: object, optional
      • error.context.account: object
        • Further fields: see the response.
      • error.context.imports: array of object
        • Further fields: see the response.
      • error.context.hasTimeEntries: boolean
      • error.context.reports: array of object
        • Further fields: see the response.

Definitions

Returned in definitions when includeDefinitions is true (the default). It is a map of string to string: each key names a field and each value is its definition text.

Caveats

Codes are not enumerated in the schema; read each code and message.

Read every caveat before interpreting a figure. See methodology on how to communicate caveats and data-quality conditions.

Example call

{
  "name": "estimate_project",
  "arguments": {
    "projectNames": [],
    "targetAgi": "50000",
    "range": {
      "from": "2026-01-01",
      "to": "2026-03-31"
    }
  }
}

Add account with an identifier from list_accounts; omit it only when the connection reaches exactly one account.

Questions and answers

What does estimate_project answer?

Run the Scope Predictor estimator for a described project: hours per task category fitted to the comparable projects you name (projectNames, at most 10, by Project Name from list_project_entries), the likely range, how similar each of the account's projects is to the brief, the account's ABR target and, when a range is given and the owner may see payroll, Direct Delivery Margin. targetAgi is required. Same calculation and figures as the Scope Predictor page for the same inputs. It estimates only: nothing is saved (list_saved_estimates and get_saved_estimate read what people saved). Direct Delivery Margin is derived from compensation: it is returned only when the current connection owner has People (payroll) grid view on this account, otherwise it is omitted with a compensation-withheld caveat; when it cannot be computed it says why in reasons. Numbers are decimal strings. Read parakeeto://methodology for shared response conventions and INVALID_ARGUMENT guidance.

Which arguments does estimate_project accept?

Argument Type Required Default Allowed values account string (uuid) no — — includeDefinitions boolean no true — projectNames array of string yes — maxItems: 10 targetAgi string yes — pattern ^-?\d+(?:\.\d+)?$ overrides map of string to string no — — brief object no — — brief.serviceLine string no — maxLength: 200 brief.product string no — maxLength: 200 brief.client string no — maxLength: 200 brief.durationDays string no — pattern ^-?\d+(?:\.\d+)?$ range object no — — range.from string yes — pattern ^\d{4}-\d{2}-\d{2}$ range.to string yes — pattern ^\d{4}-\d{2}-\d{2}$

What does estimate_project return?

The result is an envelope: ok: true with data, or ok: false with error.

Read as Markdown