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.
| Strategy | Required Manifest Fields | Description |
|---|---|---|
| 1. Asset UID + Documentation Template ⭐ | asset.uid, documentation.template | Recommended: let the platform resolve the correct documentation for the asset. |
| 2. External Asset Code + Documentation Template ⭐ | asset.externalIds.{source}, documentation.template | Recommended when your integration does not use Stonal asset UIDs. |
| 3. Asset + Documentation Template + Folder Template ⭐ | Strategy 1 or 2 + folder.template | Recommended when you want to target a specific folder type within the documentation. |
| 4. Documentation UID | documentation.uid | Use 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:
linkedAssetsbycodeare resolved relative to the parentasset.- If you send
linkedAssetswithout anasset, 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"]
}
}
3. Template Discovery (Recommended Workflow)
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.idasdocumentation.templatetemplate.folders[].idasfolder.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_FOUNDLINKED_ASSETS_NOT_FOUND:RU-001,PARK-002LINKED_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
/templatesAPI 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
8.1 Recommended approach
For this manifest example:
{
"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:
{
"documentation": {
"uid": "62c42614-31a8-43bb-a76f-8499c1b868e0"
}
}
We will use the same upload command with that manifest.