Skip to main content

Upload a file

This guide covers the supported strategies for uploading documents to the Stonal platform. It details the main combinations you can use to tell the system where and how to place your document during upload.


Prerequisites

  • A valid OAuth access token (see Authentication)
  • Your organization code (used in the endpoint path)
  • A file to upload

1. Upload Strategies & Required Fields

Each strategy maps to a combination of manifest fields. Use the table below to identify which payload suits your scenario.

StrategyRequired Manifest FieldsDescription
1. Asset UID + Documentation Templateasset.uid, documentation.templateRecommended: let the platform resolve the correct documentation for the asset.
2. External Asset Code + Documentation Templateasset.externalIds.{source}, documentation.templateRecommended when your integration does not use Stonal asset UIDs.
3. Asset + Documentation Template + Folder TemplateStrategy 1 or 2 + folder.templateRecommended when you want to target a specific folder type within the documentation.
4. Documentation UIDdocumentation.uidUse this when you already know the existing documentation you want to upload into.

linkedAssets, tags.documentation and documentClass are optional enrichments that can be added on top of these strategies.


2. Manifest Example Payloads

Include only the fields you need for your chosen strategy.

2.1 By Asset UID + Documentation Template ⭐

{
"asset": {
"uid": "822d8c50-0deb-4dae-8def-c9f9eab7f5be"
},
"documentation": {
"template": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d"
}
}

2.2 By External Asset Code + Documentation Template ⭐

{
"asset": {
"externalIds": {
"code": "BUILDING_001"
}
},
"documentation": {
"template": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d"
}
}

2.3 By Asset + Documentation Template + Folder Template ⭐

{
"asset": {
"externalIds": {
"code": "BUILDING_001"
}
},
"documentation": {
"template": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d"
},
"folder": {
"template": "e8df7c2a-b5bb-41fa-8d1f-bea649e6d93d"
}
}

2.4 By Documentation UID

Use this when the documentation UID is already known, for example because you previously retrieved it from the asset documentations endpoint.

{
"documentation": {
"uid": "62c42614-31a8-43bb-a76f-8499c1b868e0"
}
}

2.5 Add linked assets

linkedAssets can be combined with the recommended template-based strategies.

{
"asset": {
"externalIds": {
"code": "BUILDING_001"
}
},
"documentation": {
"template": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d"
},
"linkedAssets": [
{ "code": "RU-001" },
{ "uid": "fac98b98-c8ba-47e7-b5a6-2bc5222ae402" }
]
}

Important notes:

  • linkedAssets by code are resolved relative to the parent asset.
  • If you send linkedAssets without an asset, linked assets may be ignored.
  • Use the list format shown above for new integrations.

2.6 Add documentation tags and a document class

Documentation tags are only associated if they already exist on the target documentation. The upload API does not create tags on the fly.

{
"asset": {
"uid": "822d8c50-0deb-4dae-8def-c9f9eab7f5be"
},
"documentation": {
"template": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d"
},
"documentClass": "123e4567-e89b-12d3-a456-426614174007",
"tags": {
"documentation": ["LEASE 2026", "SIGNED"]
}
}

Before using template-based strategies, discover available templates:

3.1 List available templates

curl -H "Authorization: Bearer {accessToken}" \
"https://api.stonal.io/document-storage/v1/organizations/{organizationCode}/templates?language=fr-FR"

Response:

{
"templates": [
{
"id": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d",
"name": "DOE",
"organizationCode": "STONAL",
"attachmentType": "BUILDING_GROUP"
}
]
}

3.2 Get template details with folders

curl -H "Authorization: Bearer {accessToken}" \
"https://api.stonal.io/document-storage/v1/organizations/{organizationCode}/templates/{templateId}?language=fr-FR"

Response:

{
"template": {
"id": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d",
"name": {
"fr-FR": "DOE"
},
"organizationCode": "STONAL",
"attachmentType": "BUILDING_GROUP",
"folders": [
{
"id": "e8df7c2a-b5bb-41fa-8d1f-bea649e6d93d",
"name": {
"fr-FR": "Documents généraux"
},
"parentId": null,
"documentClass": {
"identifier": "documentClassIdentifier",
"code": "DPE"
}
}
]
}
}

You can then use:

  • template.id as documentation.template
  • template.folders[].id as folder.template

3.3 Retrieve existing documentations for an asset

If you want to upload into an existing documentation, first retrieve the documentations attached to the asset:

curl -H "Authorization: Bearer {accessToken}" \
"https://api.stonal.io/document-storage/v1/organizations/{organizationCode}/assets/{assetId}/documentations"

Use the returned identifier as documentation.uid.

For the full retrieval workflow, see Retrieve documentations for an asset.


4. Single-Request API Call

Send both your manifest and file in one multipart/form-data POST:

curl -X POST \
"https://api.stonal.io/document-storage/v1/organizations/{organizationCode}/files/upload" \
-H "Authorization: Bearer {accessToken}" \
-F 'manifest=@manifest.json;type=application/json' \
-F 'file=@/path/to/your/file.pdf;type=application/pdf'

Replace placeholders with your actual values.


5. Response Format

200 OK with JSON:

{
"documentId": "123e4567-e89b-12d3-a456-426614174000",
"duplicateDocumentIds": []
}

The API may also return non-blocking warnings in the X-DOCUMENT-STORAGE-WARNING response header.

Examples:

  • LINKED_ASSETS_NOT_FOUND
  • LINKED_ASSETS_NOT_FOUND:RU-001,PARK-002
  • LINKED_ASSETS_SKIPPED_NO_PARENT

When is AI processing triggered?

In public upload flows, an AI request is sent when the uploaded file is attached to a documentation context.

The requested treatment then depends on the upload context:

  • if the file is uploaded only into a documentation, AI classification is requested
  • if a document class is provided, metadata extraction is requested
  • OCR is always requested as part of the AI request

In practice, template-based uploads remain the main public way to place the document in the right documentation before AI processing starts.


6. Error Handling

  • 400 Bad Request: Missing or invalid manifest fields, or invalid multipart request
  • 404 Not Found: Referenced asset, documentation, template folder, or matching documentation for the provided asset and documentation template was not found
  • 409 Conflict: Specified asset and documentation are not linked

Handle these responses gracefully in your integration.


7. Best Practices

  • Prioritize templates: This is the main public integration path and the most future-proof one.
  • Discover templates first: Use the /templates API to explore available options.
  • Prefer asset UIDs when possible: They remain the clearest identifiers.
  • Use documentation UID only when already known: Retrieve it first from the asset documentations endpoint.
  • Use linked assets only with a parent asset: Code-based linked assets are resolved relative to that parent.
  • Remember that documentation tags are not created automatically: Only existing documentation tags are associated.

For more details, see our API specification.


8. Complete Example

For this manifest example:

manifest.json
{
"asset": {
"externalIds": {
"code": "BUILDING_001"
}
},
"documentation": {
"template": "f90ee77d-b6cc-41fa-8d1f-bea649e6d93d"
},
"folder": {
"template": "e8df7c2a-b5bb-41fa-8d1f-bea649e6d93d"
},
"linkedAssets": [
{ "code": "RU-001" }
],
"tags": {
"documentation": ["DPE 2026"]
},
"documentClass": "123e4567-e89b-12d3-a456-426614174007"
}

We will use the following command to upload the file:

curl \
-X POST "https://api.stonal.io/document-storage/v1/organizations/{organizationCode}/files/upload" \
-H "Authorization: Bearer {accessToken}" \
-F 'manifest=@manifest.json;type=application/json' \
-F 'file=@sample.pdf;type=application/pdf'

8.2 Existing documentation already known

For this manifest example:

manifest.json
{
"documentation": {
"uid": "62c42614-31a8-43bb-a76f-8499c1b868e0"
}
}

We will use the same upload command with that manifest.