POST /employers/{employerId}/uploads

Initiate an upload of a Contribution or Enrolment file. Returns a pre-signed URL where the file should be sent via PUT request. We recommend using the AWS S3 client SDK to perform the upload.

Path parameters

  • employerId string(uuid) Required

    Penfold employer UUID

application/json

Body Required

  • filename string Required

    The filename of the upload.

  • purpose string Required

    The purpose of the file upload. If "contribution", both contributions and enrolments will be processed. If "enrolment", only enrolments will be processed.

    Values are contribution or enrolment.

Responses

  • 200 application/json

    Successfully initiated the upload.

    Hide response attributes Show response attributes object
    • id string Required

      ID of the upload.

    • employerId string | null

      ID of the employer the upload was made for.

    • putDestinationUrl string | null Required

      Destination URL where the actual file should be sent, using a PUT request. Only present when status is AwaitingFile. We recommend using the AWS S3 client SDK to perform the upload.

    • createdAt string(date-time) Required

      Datetime the upload was created.

    • updatedAt string(date-time) Required

      Datetime the upload was last updated.

    • processingStarted string(date-time) | null Required

      Datetime of when processing of the file began.

    • processingEnded string(date-time) | null Required

      Datetime of when processing of the file ended, or null if it has not ended.

    • processingTime number | null Required

      The number of seconds it took to process the file end-to-end (if applicable).

    • totalErrors number Required

      The number of errors produced in processing the file. Zero if there are none or processing is not finished. Use the {uploadId}/errors endpoint to retrieve detailed information.

    • contributionsCreated number Required

      The number of contributions created during processing. Zero if processing is not finished.

    • contributionsUnprocessed number

      The number of contributions that failed to be created during processing. Zero if processing is not finished.

    • contributionsAlreadyExisted number Required

      The number of contributions that already existed prior to processing and were skipped. Zero if processing is not finished.

    • employerContributions number Required

      The total of employer contributions created for the upload, excluding those that already existed. Zero if processing is not finished.

    • employeeContributions number Required

      The total of employee contributions created for the upload, excluding those that already existed. Zero if processing is not finished.

    • totalContributions number Required

      The total of all contributions created for the upload, excluding those that already existed. Zero if processing is not finished.

    • filename string | null Required

      The filename of the uploaded file (if applicable).

    • status string Required

      The status of the upload. Error indicates the file was not able to be processed. PartiallyProcessed indicates that some but not all contributions or enrolments were created.

      Values are AwaitingFile, ReceivedFile, Processing, Processed, Error, Timeout, or PartiallyProcessed.

  • 400 application/json

    Request body failed validation

    Hide response attributes Show response attributes object
    • error string Required

      A descriptive error message.

    • validationErrors array[object]
      Hide validationErrors attributes Show validationErrors attributes object
      • field string Required

        The name of the field that failed validation.

      • message string Required

        A descriptive error message.

  • 401 application/json

    Missing or invalid authentication token

    Hide response attribute Show response attribute object
    • error string Required
  • 404 application/json

    Resource not found

    Hide response attribute Show response attribute object
    • error string Required
  • 500 application/json

    Internal server error

    Hide response attribute Show response attribute object
    • error string Required
POST /employers/{employerId}/uploads
curl \
 --request POST 'https://partner-api.getpenfold.com/v1/employers/{employerId}/uploads' \
 --header "Authorization: Bearer $ACCESS_TOKEN" \
 --header "Content-Type: application/json" \
 --data '{"filename":"papdis.csv","purpose":"contribution"}'
Request examples
{
  "filename": "papdis.csv",
  "purpose": "contribution"
}
Response examples (200)
{
  "id": "string",
  "employerId": "string",
  "putDestinationUrl": "string",
  "createdAt": "2026-05-04T09:42:00Z",
  "updatedAt": "2026-05-04T09:42:00Z",
  "processingStarted": "2023-03-01T11:00:00Z",
  "processingEnded": "2023-03-01T12:00:00Z",
  "processingTime": 47,
  "totalErrors": 10,
  "contributionsCreated": 5,
  "contributionsUnprocessed": 0,
  "contributionsAlreadyExisted": 0,
  "employerContributions": 500.34,
  "employeeContributions": 734.11,
  "totalContributions": 1234.45,
  "filename": "papdis.csv",
  "status": "Processed"
}
Response examples (400)
{
  "error": "validation failed",
  "validationErrors": [
    {
      "field": "companyNumber",
      "message": "companyNumber is required"
    },
    {
      "field": "primaryContactEmail",
      "message": "must be a valid email address"
    }
  ]
}
Response examples (401)
{
  "error": "unauthorized"
}
Response examples (404)
{
  "error": "not found"
}
Response examples (500)
{
  "error": "internal server error"
}