Files API
Confidential. Do not share without explicit permission.
Introduction
The RSL Platform Files API describes the shared objects and patterns RSL Platform APIs use to create, validate and retrieve structured file resources. RSL Platform APIs compose these objects into endpoint-specific request and response schemas, adding any resource-specific fields required by the endpoint.
File flows
The Files API is built around a small set of shared objects that work together across upload and download workflows.
Upload flow
- The client creates an
uploadobject that manages the upload and validation workflow of a file to create afileobject. - The API returns the
uploadobject and the client uploads a file to the temporary presigned upload URL provided in theupload.fileobject. - The client polls the
uploadobject until the file has been uploaded and validated successfully to create a file object. - If the upload failed, the client downloads a file containing a
resultobject from theuploadobject to identify the reason for failure.
Download flow
- The client requests a
fileobject for a file resource. - The API returns a
fileobject describing the file metadata and temporary presigned URL. - The client downloads the file from the
fileobject's URL.
The Upload object
An Upload object manages the upload and validation workflow used to create a file object. The object tracks the state of the upload job, provides the result metadata for the workflow, and includes a nested file object that describes the file being created and provides the temporary presigned URL the client uses to upload the file bytes with an HTTP PUT request.
Attributes
| Name | Type | Description |
|---|---|---|
id | string | Unique identifier for the upload job. |
status | enum | Current status of the upload job. |
created | timestamp | UTC Unix timestamp when the upload job was created. |
updated | timestamp | UTC Unix timestamp when the upload job was last updated. null until the job state changes after creation. |
completed | timestamp | UTC Unix timestamp when processing completed. null until the job reaches a terminal state. |
result_url | string | Temporary presigned URL used to download the JSON result file when the job reaches a terminal state. null until the result is available. |
result_url_expires | timestamp | UTC Unix timestamp when the result download URL expires. null when result_url is null. |
result_sha256 | string | SHA-256 hash of the JSON file returned by result_url, hex-encoded. null when result_url is null. |
file | file object | File object for the file being created by the upload job. This object includes the file metadata and the temporary presigned URL the client uses to upload the file bytes with an HTTP PUT request. |
Status values
The upload.status field indicates the current state of the upload and validation workflow.
| Status | Description |
|---|---|
ready | Upload job created and ready to receive the file. |
uploading | File is being received. |
processing | File is being validated and processed. |
succeeded | File was successfully processed. |
failed | File was rejected or could not be processed. |
A job enters uploading after upload of the file begins and remains in that state until the file has been fully received. When a job reaches a terminal state, succeeded or failed, result_url references a temporary presigned URL to a file containing a result object for that job.
Create an Upload
POST /{workflow}Accepts a file object that specifies the metadata for the file being uploaded.
Body parameters
| Name | Type | Required | Description |
|---|---|---|---|
file | file object | Yes | File object containing the metadata for the file being uploaded. |
File parameters
Only these fields can be set on the request file object.
| Name | Type | Required | Description |
|---|---|---|---|
format | enum | No | File format. If omitted, defaults to csv. |
schema_version | string | Yes | Schema version used to validate and interpret the uploaded file. |
compression | enum | No | Compression applied to the uploaded file. If omitted, defaults to none. |
size | integer | Yes | File size in bytes. The uploaded file must match this value. |
sha256 | string | Yes | SHA-256 hash of the file, hex-encoded. The uploaded file must match this value. |
validate_only | boolean | No | If true, the file is for validation only and must not be processed. If omitted, defaults to false. |
Response fields
| Name | Type | Description |
|---|---|---|
upload | upload object | Upload object for the upload workflow. |
Example request
{
"file": {
"format": "csv",
"schema_version": "1.0",
"compression": "gzip",
"size": 2096128,
"sha256": "d26b94ae60e4554c7333034960d2146f3801f42a7516a566a014a2f1e6d9c3b7",
"validate_only": false
}
}Example response
{
"upload": {
"id": "job_9aK2mQ7xT4vN8pR3cW6yZ1bD",
"status": "ready",
"created": 1760000000,
"updated": null,
"completed": null,
"result_url": null,
"result_url_expires": null,
"result_sha256": null,
"file": {
"id": "file_f7Lp2Vx9qM4nT8rC3wK6yH1d",
"created": 1760000000,
"format": "csv",
"schema_version": "1.0",
"compression": "gzip",
"size": 2096128,
"sha256": "d26b94ae60e4554c7333034960d2146f3801f42a7516a566a014a2f1e6d9c3b7",
"url": "https://files.rslcollective.org/file_f7Lp2Vx9qM4nT8rC3wK6yH1d",
"url_expires": 1760086400,
"validate_only": false
}
}
}Result file
An upload result file describes the outcome of a file upload and validation workflow. It is returned via upload.result_url when the upload job reaches a terminal state, succeeded or failed.
The result file is JSON, uses Content-Type: application/json, and contains a top-level result object that describes the outcome of the upload workflow.
Uploaded files are processed row by row. During processing, the platform may encounter file-level or row-level errors. Some errors abort processing immediately and cause the job to fail. Some row-level errors cause the affected row to be skipped and processing to continue.
RSL Platform APIs use the shared file-level and row-level error codes defined in this section wherever applicable, and may define additional file-level or row-level error codes for workflow-specific business rules.
Attributes
| Name | Type | Description |
|---|---|---|
id | string | Unique identifier for the job associated with this result. |
status | enum | Processing outcome, either succeeded or failed. |
rows_processed | integer | Number of rows successfully processed. |
rows_skipped | integer | Number of rows skipped during processing. |
error_code | string | Top-level file-level processing failure code. Present when status = failed. |
errors | array of objects | Row-level processing errors. Omitted when no row-level errors were identified. |
File-level error codes
The following file-level error_code values may be returned by upload job processing workflows:
| Error code | Meaning |
|---|---|
validation_failed | One or more rows failed validation and processing did not complete successfully. |
upload_incomplete | The uploaded file was incomplete or could not be fully received. |
job_expired | The upload job expired before upload or processing completed. |
file_hash_mismatch | The uploaded file did not match the supplied sha256 value. |
file_size_mismatch | The uploaded file size did not match the supplied size value. |
unsupported_schema_version | The supplied schema_version is not supported for this upload workflow. |
unsupported_format | The supplied format is not supported for this upload workflow. |
unsupported_compression | The supplied compression is not supported for this upload workflow. |
invalid_file_format | The uploaded file could not be parsed as the declared format. |
invalid_encoding | The uploaded file is not valid in the required character encoding. |
missing_header_row | The uploaded file does not contain the required header row. |
invalid_header | The header row is malformed or could not be interpreted. |
missing_required_column | One or more required columns are missing from the header row. |
unknown_column | The uploaded file contains one or more unsupported columns. |
duplicate_column | The uploaded file contains the same column more than once in the header row. |
empty_file | The uploaded file contains no data rows. |
file_too_large | The uploaded file exceeds the maximum allowed file size for the workflow. |
row_limit_exceeded | The uploaded file exceeds the maximum allowed row count for the workflow. |
processing_failed | The upload could not be processed due to an internal error. |
Row-level error codes
When present, the errors array contains row-level processing errors. Each error object contains:
| Name | Type | Description |
|---|---|---|
row_number | integer | 1-based row number in the uploaded file, excluding the header row. |
column | string | Column name associated with the error, when applicable. |
error_code | string | Machine-readable row-level error code. |
error_description | string | Human-readable description of the row-level error. |
Row-level error codes
The following row-level error_code values may be returned by upload job processing workflows:
| Error code | Meaning |
|---|---|
missing_required_field | A required field is missing or empty. |
missing_conditional_field | A field required by another field value is missing. |
invalid_value | A field contains a syntactically invalid value that does not fit a more specific shared error code. |
invalid_pattern | A field does not match the required pattern. |
invalid_integer | A field must be an integer but is not a valid integer. |
invalid_decimal | A field must be a decimal but is not a valid decimal. |
invalid_timestamp | A field must be a valid timestamp but is not. |
invalid_date | A field must be a valid date but is not. |
invalid_enum_value | A field must be one of a defined set of values but is not. |
invalid_url | A field must be a valid URL but is not. |
invalid_boolean | A field must be a valid boolean value but is not. |
invalid_currency_code | A field must be a valid ISO 4217 currency code but is not. |
invalid_country_code | A field must be a valid country code but is not. |
value_too_long | A field exceeds the maximum allowed length. |
value_too_short | A field is shorter than the minimum allowed length. |
value_out_of_range | A numeric or date value falls outside the allowed range. |
forbidden_character | A field contains one or more disallowed characters. |
field_count_mismatch | The row has too many or too few fields compared with the header row. |
duplicate_row | The row duplicates another row in the file according to the workflow's row uniqueness rules. |
duplicate_key | A field or field combination that must be unique appears more than once in the file. |
unknown_reference | A field references an unknown identifier in a domain-defined reference set. |
Success example
{
"result": {
"id": "job_9aK2mQ7xT4vN8pR3cW6yZ1bD",
"status": "succeeded",
"rows_processed": 48291,
"rows_skipped": 1,
"errors": [
{
"row_number": 3249,
"column": "scope_url",
"error_code": "invalid_url",
"error_description": "scope_url must be a valid URL."
}
]
}
}Failure example
{
"result": {
"id": "job_9aK2mQ7xT4vN8pR3cW6yZ1bD",
"status": "failed",
"error_code": "validation_failed",
"rows_processed": 14,
"rows_skipped": 0,
"errors": [
{
"row_number": 14,
"column": "publisher_id",
"error_code": "missing_required_field",
"error_description": "publisher_id is required."
}
]
}
}The File object
A File object represents a CSV file and includes its metadata and transfer information. File objects are used to upload, manage, and download CSV files through RSL Platform APIs.
Files must use UTF-8 encoded CSV with a header row, following RFC 4180.
Attributes
| Name | Type | Description |
|---|---|---|
id | string | Unique identifier for the file. |
created | timestamp | UTC Unix timestamp when the file was ingested. |
format | enum | File format. Value must be csv. |
schema_version | string | Version of the file schema used to validate and interpret the file. |
compression | enum | Compression applied to the file, either gzip or none. |
size | integer | File size in bytes. |
sha256 | string | SHA-256 hash of the file, hex-encoded. |
url | string | Temporary presigned URL used to transfer the file. null when no URL is currently available. |
url_expires | timestamp | UTC Unix timestamp when the URL expires. null when url is null. |
validate_only | boolean | If true, the file is for validation only and must not be processed. |
Schema versioning
The schema_version field identifies the schema version used to validate and interpret the file. File schema versions are versioned independently of the API URL version and independently of other file types used by the same API.
Schema versions are expressed as dot-separated numeric version strings in the form MAJOR.MINOR, for example 1.0, 1.1, or 2.0.
Retrieve a file
GET /{workflow}/{id}Returns a file object for the requested file.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Identifier of the file to retrieve. |
Response fields
| Name | Type | Description |
|---|---|---|
file | file object | File object for the requested file. |
Example response
{
"file": {
"id": "file_f7Lp2Vx9qM4nT8rC3wK6yH1d",
"created": 1774224000,
"format": "csv",
"schema_version": "1.0",
"compression": "gzip",
"size": 1048576,
"sha256": "d26b94ae60e4554c7333034960d2146f3801f42a7516a566a014a2f1e6d9c3b7",
"url": "https://files.rslcollective.org/file_f7Lp2Vx9qM4nT8rC3wK6yH1d.csv.gz",
"url_expires": 1760086400,
"validate_only": false
}
}File transfers
Interrupted transfers
If a file upload or download is interrupted, the client should retry the same URL while the URL remains valid. When a file is being downloaded, temporary file URLs support HTTP byte range requests, so clients can resume interrupted downloads without restarting the transfer.
If the URL has expired, the client must create a new job or retrieve a new file object through the applicable API endpoint.
Serial uploads
A file object creation workflow allows only one non-terminal job at a time. If the client tries to create a new job while another job for the same workflow is still in ready, uploading, or processing, the API returns 409 Conflict and the following error response:
{
"error": "upload_job_in_progress",
"error_description": "An upload job is already in progress."
}After the current job reaches succeeded or failed, or after it expires, the client can create a new job for that workflow.
Job expiration
Non-terminal jobs expire automatically if they do not reach a terminal state within the time limit defined by upload.file.url_expires. After a job expires or reaches a terminal state, the client may create a new job.
Temporary URLs
The files API uses temporary presigned URLs for uploading and downloading files. These URLs provide time-limited access to a specific file, expire at the time indicated by the corresponding expiration timestamp, and may be refreshed by calling the applicable API endpoint again while the file remains available.
Clients upload file bytes to upload URLs with PUT and retrieve file or result URLs with GET. Upload requests and file download responses use Content-Type: text/csv, even when the file is gzip-compressed.
Temporary upload and download URLs remain valid for at least the minimum interval defined by the applicable API specification.
File metadata
Clients must use the metadata returned by the API as the authoritative description of the file. This includes:
file.formatfile.compressionfile.sizefile.sha256upload.result_sha256
Clients should not rely on HTTP Content-Type or Content-Encoding headers returned by a temporary download URL as the authoritative indicator of file format or compression.
File security
All API requests and file transfers must be made over HTTPS, and calls made over plain HTTP will fail. Files exchanged through RSL Platform APIs are encrypted at rest using server-side encryption with cloud-managed keys.
Appendix: Machine-readable shared schemas
This appendix defines the shared OpenAPI schema fragments used by RSL Platform APIs for file transfer and asynchronous processing workflows.
OpenAPI definition
components:
schemas:
FileInput:
type: object
required: [schema_version, size, sha256]
properties:
format:
type: string
enum: [csv]
default: csv
schema_version:
type: string
compression:
type: string
enum: [gzip, none]
default: none
size:
type: integer
minimum: 0
sha256:
type: string
pattern: "^[A-Fa-f0-9]{64}$"
validate_only:
type: boolean
default: false
Upload:
type: object
required:
- id
- status
- created
- updated
- completed
- result_url
- result_url_expires
- result_sha256
- file
properties:
id:
type: string
status:
type: string
enum: [ready, uploading, processing, succeeded, failed]
created:
type: integer
updated:
type: integer
nullable: true
completed:
type: integer
nullable: true
result_url:
type: string
format: uri
nullable: true
result_url_expires:
type: integer
nullable: true
result_sha256:
type: string
pattern: "^[A-Fa-f0-9]{64}$"
nullable: true
file:
$ref: "#/components/schemas/File"
UploadResponse:
type: object
required: [upload]
properties:
upload:
$ref: "#/components/schemas/Upload"
File:
type: object
required:
- id
- created
- format
- schema_version
- compression
- size
- sha256
- url
- url_expires
- validate_only
properties:
id:
type: string
created:
type: integer
format:
type: string
enum: [csv]
schema_version:
type: string
compression:
type: string
enum: [gzip, none]
size:
type: integer
minimum: 0
sha256:
type: string
pattern: "^[A-Fa-f0-9]{64}$"
url:
type: string
format: uri
nullable: true
url_expires:
type: integer
nullable: true
validate_only:
type: boolean
default: false
FileResponse:
type: object
required: [file]
properties:
file:
$ref: "#/components/schemas/File"
Result:
oneOf:
- $ref: "#/components/schemas/ResultSuccess"
- $ref: "#/components/schemas/ResultFailure"
ResultResponse:
type: object
required: [result]
properties:
result:
$ref: "#/components/schemas/Result"
ResultSuccess:
type: object
required: [id, status, rows_processed, rows_skipped]
properties:
id:
type: string
status:
type: string
enum: [succeeded]
rows_processed:
type: integer
minimum: 0
rows_skipped:
type: integer
minimum: 0
errors:
type: array
items:
$ref: "#/components/schemas/ResultRowError"
ResultFailure:
type: object
required: [id, status, error_code, rows_processed, rows_skipped]
properties:
id:
type: string
status:
type: string
enum: [failed]
error_code:
type: string
enum:
- validation_failed
- upload_incomplete
- job_expired
- file_hash_mismatch
- file_size_mismatch
- unsupported_schema_version
- unsupported_format
- unsupported_compression
- invalid_file_format
- invalid_encoding
- missing_header_row
- invalid_header
- missing_required_column
- unknown_column
- duplicate_column
- empty_file
- file_too_large
- row_limit_exceeded
- processing_failed
rows_processed:
type: integer
minimum: 0
rows_skipped:
type: integer
minimum: 0
errors:
type: array
items:
$ref: "#/components/schemas/ResultRowError"
ResultRowError:
type: object
required: [row_number, error_code]
properties:
row_number:
type: integer
minimum: 1
column:
type: string
error_code:
type: string
description: >
Machine-readable row-level error code. Values include shared row error codes
and workflow-specific row error codes defined by the applicable API.
error_description:
type: string
Error:
type: object
required: [error, error_description]
properties:
error:
type: string
error_description:
type: stringError catalog
This catalog defines the machine-readable error codes used by this specification. API error responses use the generic Error schema defined in the OpenAPI definition.
catalog_type: rsl.files_api.error_catalog
catalog_version: 1.0.0-beta
file_errors:
- code: validation_failed
category: file
retryable: false
description: One or more rows failed validation and processing did not complete successfully.
- code: upload_incomplete
category: file
retryable: true
description: The uploaded file was incomplete or could not be fully received.
- code: job_expired
category: file
retryable: true
description: The upload job expired before upload or processing completed.
- code: file_hash_mismatch
category: file
retryable: false
description: The uploaded file did not match the supplied sha256 value.
- code: file_size_mismatch
category: file
retryable: false
description: The uploaded file size did not match the supplied size value.
- code: unsupported_schema_version
category: file
retryable: false
description: The supplied schema_version is not supported for this upload workflow.
- code: unsupported_format
category: file
retryable: false
description: The supplied format is not supported for this upload workflow.
- code: unsupported_compression
category: file
retryable: false
description: The supplied compression is not supported for this upload workflow.
- code: invalid_file_format
category: file
retryable: false
description: The uploaded file file is not valid RFC 4180 CSV.
- code: invalid_encoding
category: file
retryable: false
description: The uploaded file is not valid UTF-8.
- code: missing_header_row
category: file
retryable: false
description: The uploaded file does not contain the required header row.
- code: invalid_header
category: file
retryable: false
description: The header row is malformed or could not be interpreted.
- code: missing_required_column
category: file
retryable: false
description: One or more required columns are missing from the header row.
- code: unknown_column
category: file
retryable: false
description: The uploaded file contains one or more unsupported columns.
- code: duplicate_column
category: file
retryable: false
description: The uploaded file contains the same column more than once in the header row.
- code: empty_file
category: file
retryable: false
description: The uploaded file contains no data rows.
- code: file_too_large
category: file
retryable: false
description: The uploaded file exceeds the maximum allowed file size for the workflow.
- code: row_limit_exceeded
category: file
retryable: false
description: The uploaded file exceeds the maximum allowed row count for the workflow.
- code: processing_failed
category: file
retryable: true
description: The upload could not be processed due to an internal error.
row_errors:
- code: missing_required_field
category: row
retryable: false
description: A required field is missing or empty.
- code: missing_conditional_field
category: row
retryable: false
description: A field required by another field value is missing.
- code: invalid_value
category: row
retryable: false
description: A field contains a syntactically invalid value that does not fit a more specific shared error code.
- code: invalid_pattern
category: row
retryable: false
description: A field does not match the required pattern.
- code: invalid_integer
category: row
retryable: false
description: A field must be an integer but is not a valid integer.
- code: invalid_decimal
category: row
retryable: false
description: A field must be a decimal but is not a valid decimal.
- code: invalid_timestamp
category: row
retryable: false
description: A field must be a valid timestamp but is not.
- code: invalid_date
category: row
retryable: false
description: A field must be a valid date but is not.
- code: invalid_enum_value
category: row
retryable: false
description: A field must be one of a defined set of values but is not.
- code: invalid_url
category: row
retryable: false
description: A field must be a valid URL but is not.
- code: invalid_boolean
category: row
retryable: false
description: A field must be a valid boolean value but is not.
- code: invalid_currency_code
category: row
retryable: false
description: A field must be a valid ISO 4217 currency code but is not.
- code: invalid_country_code
category: row
retryable: false
description: A field must be a valid country code but is not.
- code: value_too_long
category: row
retryable: false
description: A field exceeds the maximum allowed length.
- code: value_too_short
category: row
retryable: false
description: A field is shorter than the minimum allowed length.
- code: value_out_of_range
category: row
retryable: false
description: A numeric or date value falls outside the allowed range.
- code: forbidden_character
category: row
retryable: false
description: A field contains one or more disallowed characters.
- code: field_count_mismatch
category: row
retryable: false
description: The row has too many or too few fields compared with the header row.
- code: duplicate_row
category: row
retryable: false
description: The row duplicates another row in the file according to the workflow's row uniqueness rules.
- code: duplicate_key
category: row
retryable: false
description: A field or field combination that must be unique appears more than once in the file.
- code: unknown_reference
category: row
retryable: false
description: A field references an unknown identifier in a domain-defined reference set.
api_errors:
- code: upload_job_in_progress
category: api
description: A non-terminal upload job is already in progress for the workflow.Changelog
- 2026-03-30: Initial draft.
