Skip to main content
Communication

Documents

Upload, manage, and download polymorphic file attachments stored on OVH Swift object storage.

Base URL: /api/v1/documents

Auth required: Yes (auth:api) for all endpoints.

Documents are file attachments stored on OVH Swift object storage. They are polymorphic: they belong to any documentable entity (customer, prospect, customer file, information collection, host, etc.).


Model Properties

Property Type Required Description
id integer auto Unique identifier
user_id integer auto FK to users. Auto-set to the authenticated user on upload
documentable_type string Yes PHP class name of the owning entity (e.g. App\Customer, App\Prospect)
documentable_id integer Yes ID of the owning entity
file_name string auto Stored file name (auto-generated: random prefix + original name). Not settable directly
mime_type string auto MIME type of the uploaded file. Auto-detected from the file
file_description string No Human-readable description of the document
tags array No Array of tag strings for categorization
shared boolean No Whether the document is visible in the customer portal (default: false)
created_at datetime auto Creation timestamp
updated_at datetime auto Last update timestamp

Upload constraints: Accepted MIME types: jpeg, png, jpg, zip, pdf, ppt, pptx, xlx, xlsx, docx, doc, gif, webm, mp4, mpeg. Maximum file size: 500 MB.


GET /v1/documents

List all documents for a specific entity.

Query parameters:

Parameter Type Required Description
documentable_type string Yes PHP class name of the entity (e.g. App\Customer)
documentable_id integer Yes ID of the owning entity

Response 200: Array of document metadata objects (document_resource collection).

Examples:

curl -s -X GET "https://your-instance.bluerocktel.net/api/v1/documents?documentable_type=App%5CCustomer&documentable_id=42" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
import requests

response = requests.get(
    "https://your-instance.bluerocktel.net/api/v1/documents",
    params={"documentable_type": "App\\Customer", "documentable_id": 42},
    headers={"Authorization": f"Bearer {token}", "Accept": "application/json"},
)
documents = response.json()
use Illuminate\Support\Facades\Http;

$response = Http::withToken($token)
    ->acceptJson()
    ->get('https://your-instance.bluerocktel.net/api/v1/documents', [
        'documentable_type' => 'App\\Customer',
        'documentable_id' => 42,
    ]);

$documents = $response->json();
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/documents?documentable_type=App%5CCustomer&documentable_id=42",
  {
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
  }
);
const documents = await response.json();

POST /v1/documents

Upload a new document and attach it to an entity. The file is stored on all configured disks (Swift storage).

Query parameters:

Parameter Type Required Description
documentable_type string Yes PHP class name of the entity
documentable_id integer Yes ID of the owning entity

Body (multipart/form-data):

Field Type Required Description
file file Yes File to upload
file_description string No Description of the document
tags array No Tags for categorization
shared boolean No Whether document is shared
user_id integer No Uploader user ID (defaults to authenticated user)

Files are stored at documents/{account}/ with a randomized prefix.

Response 201: Created document metadata object. Response 422: Validation error.

Examples:

curl -s -X POST "https://your-instance.bluerocktel.net/api/v1/documents?documentable_type=App%5CCustomer&documentable_id=42" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -F "file=@/path/to/contract.pdf" \
  -F "file_description=Service contract 2026" \
  -F "shared=true"
import requests

with open("/path/to/contract.pdf", "rb") as f:
    response = requests.post(
        "https://your-instance.bluerocktel.net/api/v1/documents",
        params={"documentable_type": "App\\Customer", "documentable_id": 42},
        headers={"Authorization": f"Bearer {token}", "Accept": "application/json"},
        files={"file": ("contract.pdf", f, "application/pdf")},
        data={"file_description": "Service contract 2026", "shared": "true"},
    )
document = response.json()
$response = Http::withToken($token)
    ->acceptJson()
    ->attach('file', file_get_contents('/path/to/contract.pdf'), 'contract.pdf')
    ->post('https://your-instance.bluerocktel.net/api/v1/documents?documentable_type=App%5CCustomer&documentable_id=42', [
        'file_description' => 'Service contract 2026',
        'shared' => true,
    ]);

$document = $response->json();
const formData = new FormData();
formData.append("file", fileBlob, "contract.pdf");
formData.append("file_description", "Service contract 2026");
formData.append("shared", "true");

const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/documents?documentable_type=App%5CCustomer&documentable_id=42",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
    body: formData,
  }
);
const document = await response.json();

GET /v1/documents/{id}

Get a single document's metadata by ID.

URL parameters:

Parameter Type Description
id integer Document ID

Response 200: Document metadata (document_resource). Response 404: Not found.

Examples:

curl -s -X GET "https://your-instance.bluerocktel.net/api/v1/documents/55" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
import requests

response = requests.get(
    "https://your-instance.bluerocktel.net/api/v1/documents/55",
    headers={"Authorization": f"Bearer {token}", "Accept": "application/json"},
)
document = response.json()
$response = Http::withToken($token)
    ->acceptJson()
    ->get('https://your-instance.bluerocktel.net/api/v1/documents/55');

$document = $response->json();
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/documents/55",
  {
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
  }
);
const document = await response.json();

GET /v1/documents/{id}/content

Download the actual document file from Swift storage.

URL parameters:

Parameter Type Description
id integer Document ID

Response 200: File content with correct Content-Type header. Response 404: File not found on storage.

Examples:

curl -s -X GET "https://your-instance.bluerocktel.net/api/v1/documents/55/content" \
  -H "Authorization: Bearer $TOKEN" \
  -o downloaded-file.pdf
import requests

response = requests.get(
    "https://your-instance.bluerocktel.net/api/v1/documents/55/content",
    headers={"Authorization": f"Bearer {token}"},
)
with open("downloaded-file.pdf", "wb") as f:
    f.write(response.content)
$response = Http::withToken($token)
    ->get('https://your-instance.bluerocktel.net/api/v1/documents/55/content');

Storage::put('downloaded-file.pdf', $response->body());
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/documents/55/content",
  {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  }
);
const blob = await response.blob();

PUT /v1/documents/{id}

Update document metadata (description, shared status, tags). The file itself cannot be replaced.

URL parameters:

Parameter Type Description
id integer Document ID

Body (JSON): Validated via Document::attributes('update_body'):

Field Type Description
file_description string Updated description
shared boolean Updated shared status
tags array Updated tags

Response 201: Updated document metadata. Response 404: Not found.

Examples:

curl -s -X PUT "https://your-instance.bluerocktel.net/api/v1/documents/55" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"file_description": "Updated contract description", "shared": false}'
import requests

response = requests.put(
    "https://your-instance.bluerocktel.net/api/v1/documents/55",
    headers={"Authorization": f"Bearer {token}", "Accept": "application/json"},
    json={"file_description": "Updated contract description", "shared": False},
)
document = response.json()
$response = Http::withToken($token)
    ->acceptJson()
    ->put('https://your-instance.bluerocktel.net/api/v1/documents/55', [
        'file_description' => 'Updated contract description',
        'shared' => false,
    ]);

$document = $response->json();
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/documents/55",
  {
    method: "PUT",
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      file_description: "Updated contract description",
      shared: false,
    }),
  }
);
const document = await response.json();

DELETE /v1/documents/{id}

Delete a document record and remove the file from all storage disks.

URL parameters:

Parameter Type Description
id integer Document ID

Response 200: Success message. Response 404: Not found.

Examples:

curl -s -X DELETE "https://your-instance.bluerocktel.net/api/v1/documents/55" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: application/json"
import requests

response = requests.delete(
    "https://your-instance.bluerocktel.net/api/v1/documents/55",
    headers={"Authorization": f"Bearer {token}", "Accept": "application/json"},
)
$response = Http::withToken($token)
    ->acceptJson()
    ->delete('https://your-instance.bluerocktel.net/api/v1/documents/55');
const response = await fetch(
  "https://your-instance.bluerocktel.net/api/v1/documents/55",
  {
    method: "DELETE",
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
  }
);