Menu

DevelopersREST API

Projects API

List and retrieve AutoRFP.ai projects, update a project's custom fields, and list a project's requirements with the REST API.

Projects are the bids you manage in AutoRFP.ai. Use these endpoints to list and retrieve projects, update a project’s custom fields, and list the requirements in a project.

Reading projects needs the projects:read scope. Updating custom fields needs projects:write, which is a write scope.

List projects#

get/v1/projects

Returns a paginated list of projects accessible via the API key.

Required scopeprojects:read

Query parameters

  • page[number]integer

    Page number (1-indexed)

    Default:1

    min 1

  • page[size]integer

    Items per page (1-100)

    Default:25

    1 to 100

  • filter[createdAfter]string (date-time)

    ISO 8601 datetime (e.g. "2025-01-01T00:00:00Z")

  • filter[createdBefore]string (date-time)

    ISO 8601 datetime (e.g. "2025-01-01T00:00:00Z")

  • filter[dueAfter]string (date-time)

    ISO 8601 datetime (e.g. "2025-01-01T00:00:00Z")

  • filter[dueBefore]string (date-time)

    ISO 8601 datetime (e.g. "2025-01-01T00:00:00Z")

  • filter[status]array of strings

    Comma-separated list of statuses (e.g. "inProgress,completed")

    One of:intakeinProgresscompletedshortlistedoverduelostwonstopped

Returns

Paginated list of projects

  • typeenumrequired

    One of:projects

  • idstringrequired
  • attributesobjectrequired
    Show child attributes
    • namestringrequired

      Project name

    • statusstringrequired

      Current project status

    • prospectNamestringrequired

      Name of the prospect or issuer

    • projectTypestring | nullrequired

      Project type (e.g. "rfp", "rfi")

    • createdAtstring | nullrequired

      ISO 8601 datetime when the project was created

    • dueDatestring | nullrequired

      ISO 8601 datetime when the project is due

    • externalIdsobjectrequired
      Show child attributes
      • salesforceIdstring | nullrequired

        Salesforce external ID

      • opportunityIdstring | nullrequired

        Salesforce opportunity ID

  • metaobjectrequired
    Show child attributes
    • pageobjectrequired
      Show child attributes
      • numbernumberrequired
      • sizenumberrequired
      • totalItemsnumberrequired
      • totalPagesnumberrequired
  • linksobjectrequired
    Show child attributes
    • selfstringrequired
    • firststringrequired
    • laststring | nullrequired
    • prevstring | nullrequired
    • nextstring | nullrequired

Errors

StatusMeaning
400Invalid query parameters
401Unauthorized
403Insufficient permissions
429Rate limit exceeded
500Internal server error

Request

curl -g "https://api.autorfp.ai/v1/projects?page[size]=25&filter[status]=intake" \
  -H "Authorization: Bearer $AUTORFP_API_KEY"

Response

Response

{
  "data": [
    {
      "type": "projects",
      "id": "8f14e45f",
      "attributes": {
        "name": "Acme RFP 2026",
        "status": "inProgress",
        "prospectName": "Acme Corp",
        "projectType": "rfp",
        "createdAt": "2026-03-02T09:30:00.000Z",
        "dueDate": "2026-03-02T09:30:00.000Z",
        "externalIds": {
          "salesforceId": "8f14e45f",
          "opportunityId": "8f14e45f"
        }
      }
    }
  ],
  "meta": {
    "page": {
      "number": 1,
      "size": 1,
      "totalItems": 1,
      "totalPages": 1
    }
  },
  "links": {
    "self": "https://api.autorfp.ai/v1/projects?page[number]=1&page[size]=25",
    "first": "https://api.autorfp.ai/v1/projects?page[number]=1&page[size]=25",
    "last": "https://api.autorfp.ai/v1/projects?page[number]=1&page[size]=25",
    "prev": "https://api.autorfp.ai/v1/projects?page[number]=1&page[size]=25",
    "next": "https://api.autorfp.ai/v1/projects?page[number]=2&page[size]=25"
  }
}

Get a project#

get/v1/projects/{projectId}

Returns one project: header fields, requirement summary counts, projectType, and custom field values. projectType matches GET /v1/projects list: value of the custom field with id project_type when present; otherwise null. customFields lists current values on the project. An empty array usually means none are configured; in rare cases it can briefly appear empty even when fields exist, confirm with GET /v1/organisation and retry if needed. Requires projects:read. Rate limit: 100 requests / 60 seconds.

Required scopeprojects:read

Path parameters

  • projectIdstringrequired

    Project id

Returns

Project detail (includes customFields and projectType)

  • typeenumrequired

    One of:projects

  • idstringrequired
  • attributesobjectrequired
    Show child attributes
    • namestringrequired

      Project name

    • issuerstringrequired

      Name of the issuing organisation

    • statusstringrequired

      Current project status

    • createdAtstringrequired

      ISO 8601 datetime when the project was created

    • dueDatestring | nullrequired

      ISO 8601 datetime when the project is due

    • projectTypestring | nullrequired

      Same as list: value of the custom field with id project_type when present on the project; otherwise null

    • customFieldsarray of objectsrequired

      Current custom field values on the project (empty when none are configured)

      Show child attributes
      • idstringrequired

        Field id (pass as id in PATCH /v1/projects/{projectId})

      • labelstringrequired

        Human-readable field label

      • typeenumrequired

        Field value type

        One of:textnumberdatedropdownmultiselectcheckbox

      • externalIdstring | nullrequired

        Optional CRM/external key (pass as externalId in PATCH)

      • optionsarray of objects

        Static options currently on the project snapshot. PATCH allowlists use the organisation template optionSource after refresh, prefer GET /v1/organisation for the live list.

        Show child attributes
        • valuestringrequired
        • labelstringrequired
      • optionSourceobject

        Dynamic option set on the project snapshot (e.g. users, usersAndTeams, teams). For known sets, PATCH values must be org members using user:<id> / team:<id> (bare id = legacy user).

        Show child attributes
        • typeenumrequired

          One of:dynamic

        • setstringrequired
      • valuestring | number | boolean | null

        Scalar value for text, number, date, dropdown, or checkbox. Dates are ISO 8601 with offset (e.g. 2024-01-15T00:00:00.000+00:00).

      • valuesarray of strings

        Multiselect values (clear with [])

    • summaryobjectrequired
      Show child attributes
      • requirementsCountnumberrequired

        Total number of requirements

      • approvedCountnumberrequired

        Number of approved requirements

      • submittedCountnumberrequired

        Number of requirements submitted for review

Errors

StatusMeaning
400Invalid project id
401Unauthorized
403Insufficient scope (requires projects:read)
404Project not found
429Rate limit exceeded
500Internal server error

Request

curl -g "https://api.autorfp.ai/v1/projects/8f14e45f" \
  -H "Authorization: Bearer $AUTORFP_API_KEY"

Response

Response

{
  "data": {
    "type": "projects",
    "id": "8f14e45f",
    "attributes": {
      "name": "Acme RFP 2026",
      "issuer": "Acme Corp",
      "status": "inProgress",
      "createdAt": "2026-03-02T09:30:00.000Z",
      "dueDate": "2026-03-02T09:30:00.000Z",
      "projectType": "rfp",
      "customFields": [
        {
          "id": "8f14e45f",
          "label": "Security",
          "type": "text",
          "externalId": "8f14e45f",
          "options": [
            {
              "value": "example",
              "label": "Security"
            }
          ],
          "optionSource": {
            "type": "dynamic",
            "set": "users"
          },
          "value": "example",
          "values": [
            "example"
          ]
        }
      ],
      "summary": {
        "requirementsCount": 1,
        "approvedCount": 1,
        "submittedCount": 1
      }
    }
  }
}

Update project custom fields#

patch/v1/projects/{projectId}

Updates custom project field values on one project. Request body is plain JSON (application/json), not a JSON:API envelope: { "customFields": [ { "id" and/or "externalId", "value" or "values" }, ... ] } (max 50). Match fields by id and/or externalId (case-insensitive, trimmed). If both are set and resolve to different fields, or the same field is patched twice, the request fails with 400 (field-invalid). Use value for text, number, date (ISO 8601 within 1970, 2100 UTC), dropdown, and checkbox; use values (string array) for multiselect. Null clears a scalar field; dropdown empty/whitespace clears to null; values: [] clears multiselect. Static dropdown/multiselect options must match the organisation-template option list after refresh (values are trimmed). Dynamic option sources users / usersAndTeams / teams require organisation membership: user:<id> or bare id for users, team:<id> for teams (usersAndTeams allows both). Deactivated users and unknown ids fail with field-invalid. Unknown dynamic set names still accept any non-empty string. customFields: [] is a no-op (no write, no template sync, no required check); the 200 response matches the current project. A non-empty request adds any organisation-template fields missing from the project; project-only fields are kept. On a non-empty request, optionSource for matched dropdown/multiselect fields refreshes from the organisation template (static or dynamic; values and required/manageOnly flags on existing project fields are not rewritten). Required fields: after applying patches, required fields on the project working set must be non-empty. Requiredness uses each field.required flag already on the project (or on newly cloned/appended template fields); existing project required flags are not updated from the organisation template. When the project had no custom fields yet (full template clone), every required template field must be filled. Otherwise only required fields that already existed on the project or are touched in this request are checked (newly appended untouched template fields are exempt this request). Empty means: text/dropdown null or ""; number/date null; checkbox not true; multiselect []. manageOnly is ignored by PATCH (no write-deny); required manageOnly fields still must be filled when in scope. Updates are atomic: any unknown, invalid, or missing-required field rejects the whole request with no write (unlike POST /v1/content/tags, which allows partial success). Multiple semantic failures return multiple top-level errors[] entries with code field-not-found, field-invalid, or field-required; each detail names the field (for example, "region: …"). Body/schema problems (missing customFields, unknown keys, caps, empty ids) return 400 without errors[].code. Non-empty patches when neither the organisation template nor the project has any fields return 422 with code custom-fields-not-configured. On success, returns the full project summary in the same shape as GET /v1/projects/{projectId}. Requires projects:write. Rate limit: 30 requests / 60 seconds.

Required scopeprojects:write

Path parameters

  • projectIdstringrequired

    Project id

Request body

  • customFieldsarray of objectsrequired

    Field value patches (max 50). Each entry needs id and/or externalId plus value or values. [] is a no-op: no write and no template sync; response matches GET.

    max 50 items

    Show child attributes
    • idstring

      Field id from GET /v1/organisation (or from the project customFields list)

      1 to 128 characters

    • externalIdstring

      External/CRM key for the field; may be used instead of or with id

      1 to 128 characters

    • valuestring | number | boolean | null

      Scalar value for text, number, date (ISO 8601), dropdown, or checkbox. Use null to clear. Dropdown empty/whitespace clears to null.

    • valuesarray of strings

      Multiselect values only (max 100). Use [] to clear. Do not send value for multiselect.

      max 100 itemseach max 512 characters

Returns

Full project summary after update (same shape as GET /v1/projects/{projectId})

  • typeenumrequired

    One of:projects

  • idstringrequired
  • attributesobjectrequired
    Show child attributes
    • namestringrequired

      Project name

    • issuerstringrequired

      Name of the issuing organisation

    • statusstringrequired

      Current project status

    • createdAtstringrequired

      ISO 8601 datetime when the project was created

    • dueDatestring | nullrequired

      ISO 8601 datetime when the project is due

    • projectTypestring | nullrequired

      Same as list: value of the custom field with id project_type when present on the project; otherwise null

    • customFieldsarray of objectsrequired

      Current custom field values on the project (empty when none are configured)

      Show child attributes
      • idstringrequired

        Field id (pass as id in PATCH /v1/projects/{projectId})

      • labelstringrequired

        Human-readable field label

      • typeenumrequired

        Field value type

        One of:textnumberdatedropdownmultiselectcheckbox

      • externalIdstring | nullrequired

        Optional CRM/external key (pass as externalId in PATCH)

      • optionsarray of objects

        Static options currently on the project snapshot. PATCH allowlists use the organisation template optionSource after refresh, prefer GET /v1/organisation for the live list.

        Show child attributes
        • valuestringrequired
        • labelstringrequired
      • optionSourceobject

        Dynamic option set on the project snapshot (e.g. users, usersAndTeams, teams). For known sets, PATCH values must be org members using user:<id> / team:<id> (bare id = legacy user).

        Show child attributes
        • typeenumrequired

          One of:dynamic

        • setstringrequired
      • valuestring | number | boolean | null

        Scalar value for text, number, date, dropdown, or checkbox. Dates are ISO 8601 with offset (e.g. 2024-01-15T00:00:00.000+00:00).

      • valuesarray of strings

        Multiselect values (clear with [])

    • summaryobjectrequired
      Show child attributes
      • requirementsCountnumberrequired

        Total number of requirements

      • approvedCountnumberrequired

        Number of approved requirements

      • submittedCountnumberrequired

        Number of requirements submitted for review

Errors

StatusMeaning
400Invalid body/schema (no errors[].code), or one or more field errors with code field-not-found / field-invalid / field-required (no fields written)
401Unauthorized
403Insufficient scope (requires projects:write)
404Project not found
422No custom fields configured on the organisation or project (code: custom-fields-not-configured)
429Rate limit exceeded
500Internal server error

Request

curl -g -X PATCH "https://api.autorfp.ai/v1/projects/8f14e45f" \
  -H "Authorization: Bearer $AUTORFP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "customFields": [
    {
      "id": "8f14e45f",
      "value": "example"
    }
  ]
}'

Response

Response

{
  "data": {
    "type": "projects",
    "id": "8f14e45f",
    "attributes": {
      "name": "Acme RFP 2026",
      "issuer": "Acme Corp",
      "status": "inProgress",
      "createdAt": "2026-03-02T09:30:00.000Z",
      "dueDate": "2026-03-02T09:30:00.000Z",
      "projectType": "rfp",
      "customFields": [
        {
          "id": "8f14e45f",
          "label": "Security",
          "type": "text",
          "externalId": "8f14e45f",
          "options": [
            {
              "value": "example",
              "label": "Security"
            }
          ],
          "optionSource": {
            "type": "dynamic",
            "set": "users"
          },
          "value": "example",
          "values": [
            "example"
          ]
        }
      ],
      "summary": {
        "requirementsCount": 1,
        "approvedCount": 1,
        "submittedCount": 1
      }
    }
  }
}

List project requirements#

get/v1/projects/{projectId}/requirements

Returns a paginated list of requirements within a project.

Required scopeprojects:read

Path parameters

  • projectIdstringrequired

Query parameters

  • page[number]integer

    Page number (1-indexed)

    Default:1

    min 1

  • page[size]integer

    Items per page (1-100)

    Default:25

    1 to 100

Returns

Paginated list of requirements

  • typeenumrequired

    One of:requirements

  • idstringrequired
  • attributesobjectrequired
    Show child attributes
    • statusstringrequired

      Requirement status (drafted, assigned, submittedForReview, approved)

    • editorTeamIdsarray of stringsrequired

      Team IDs derived from assigned editors

    • reviewerTeamIdsarray of stringsrequired

      Team IDs derived from assigned reviewers

    • editPercentagenumber | nullrequired

      Edit percentage as a 0-1 value, null if no metrics available

  • metaobjectrequired
    Show child attributes
    • pageobjectrequired
      Show child attributes
      • numbernumberrequired
      • sizenumberrequired
      • totalItemsnumberrequired
      • totalPagesnumberrequired
  • linksobjectrequired
    Show child attributes
    • selfstringrequired
    • firststringrequired
    • laststring | nullrequired
    • prevstring | nullrequired
    • nextstring | nullrequired

Errors

StatusMeaning
400Invalid query parameters
401Unauthorized
403Insufficient permissions
404Project not found
429Rate limit exceeded
500Internal server error

Request

curl -g "https://api.autorfp.ai/v1/projects/8f14e45f/requirements?page[size]=25" \
  -H "Authorization: Bearer $AUTORFP_API_KEY"

Response

Response

{
  "data": [
    {
      "type": "requirements",
      "id": "8f14e45f",
      "attributes": {
        "status": "inProgress",
        "editorTeamIds": [
          "8f14e45f"
        ],
        "reviewerTeamIds": [
          "8f14e45f"
        ],
        "editPercentage": 1
      }
    }
  ],
  "meta": {
    "page": {
      "number": 1,
      "size": 1,
      "totalItems": 1,
      "totalPages": 1
    }
  },
  "links": {
    "self": "https://api.autorfp.ai/v1/projects/8f14e45f/requirements?page[number]=1&page[size]=25",
    "first": "https://api.autorfp.ai/v1/projects/8f14e45f/requirements?page[number]=1&page[size]=25",
    "last": "https://api.autorfp.ai/v1/projects/8f14e45f/requirements?page[number]=1&page[size]=25",
    "prev": "https://api.autorfp.ai/v1/projects/8f14e45f/requirements?page[number]=1&page[size]=25",
    "next": "https://api.autorfp.ai/v1/projects/8f14e45f/requirements?page[number]=2&page[size]=25"
  }
}