Încărcare fișiere
Trei modalități de încărcare a fotografiilor, de la simplu la complex:
- URL în anunț — transmite linkurile direct la crearea anunțului
- Import după URL — încarcă fotografiile separat, apoi leagă-le la anunț
- Signed URL — pentru încărcare fișiere de pe client
URL în anunț (recomandat)
Cea mai simplă metodă — transmite URL-urile fotografiilor direct la crearea sau actualizarea anunțului. Se recomandă adăugarea externalFileId pentru urmărire:
{
"externalId": "apt-001",
"announcementStatus": "active",
"announcementType": "rent",
"propertyType": "residential",
"propertySecondaryType": "apartment",
"announcementValue": 500,
"files": [
{ "url": "https://placehold.co/1920x1080/jpg?text=Living", "externalFileId": "apt-001-photo-1" },
{ "url": "https://placehold.co/1920x1080/jpg?text=Dormitor", "externalFileId": "apt-001-photo-2" },
{ "url": "https://placehold.co/1920x1080/jpg?text=Bucătărie", "externalFileId": "apt-001-photo-3" }
]
}
Sistemul va încărca automat fotografiile, le va optimiza și le va lega la anunț. La retrimiterea aceluiași externalFileId, sistemul folosește fișierul deja încărcat, evitând duplicarea.
Import după URL
Folosește această metodă dacă vrei să încarci fotografiile în avans sau să le gestionezi separat de anunțuri.
Încarcă o fotografie
const response = await fetch('https://crm.rentix.md/api/v1/media/upload-from-url', {
method: 'POST',
headers: {
'Authorization': 'ApiKey YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://placehold.co/1920x1080/jpg?text=Living',
externalId: 'apt-001-photo-1'
})
});
const result = await response.json();
console.log(`Media ID: ${result.mediaId}, Status: ${result.status}`);
curl -X POST https://crm.rentix.md/api/v1/media/upload-from-url \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://placehold.co/1920x1080/jpg?text=Living",
"externalId": "apt-001-photo-1"
}'
$data = [
'url' => 'https://placehold.co/1920x1080/jpg?text=Living',
'externalId' => 'apt-001-photo-1'
];
$ch = curl_init('https://crm.rentix.md/api/v1/media/upload-from-url');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: ApiKey YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
{
"mediaId": 123,
"status": "pending",
"externalId": "apt-001-photo-1",
"jobId": 456
}
Statusul pending înseamnă că fișierul a fost pus în coadă pentru încărcare și optimizare. Câmpul jobId permite urmărirea statusului procesării.
Încărcare bulk
Pentru încărcarea mai multor fișiere, folosește endpoint-ul bulk cu operația upload-from-url:
const response = await fetch('https://crm.rentix.md/api/v1/media/bulk', {
method: 'POST',
headers: {
'Authorization': 'ApiKey YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
operations: [
{ op: 'upload-from-url', url: 'https://placehold.co/1920x1080/jpg?text=Photo+1', externalId: 'apt-001-photo-1' },
{ op: 'upload-from-url', url: 'https://placehold.co/1920x1080/jpg?text=Photo+2', externalId: 'apt-001-photo-2' },
{ op: 'upload-from-url', url: 'https://placehold.co/1920x1080/jpg?text=Photo+3', externalId: 'apt-001-photo-3' }
]
})
});
const result = await response.json();
console.log(`Încărcate: ${result.summary.succeeded} din ${result.summary.total}`);
curl -X POST https://crm.rentix.md/api/v1/media/bulk \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{ "op": "upload-from-url", "url": "https://placehold.co/1920x1080/jpg?text=Photo+1", "externalId": "apt-001-photo-1" },
{ "op": "upload-from-url", "url": "https://placehold.co/1920x1080/jpg?text=Photo+2", "externalId": "apt-001-photo-2" }
]
}'
$data = [
'operations' => [
['op' => 'upload-from-url', 'url' => 'https://placehold.co/1920x1080/jpg?text=Photo+1', 'externalId' => 'apt-001-photo-1'],
['op' => 'upload-from-url', 'url' => 'https://placehold.co/1920x1080/jpg?text=Photo+2', 'externalId' => 'apt-001-photo-2']
]
];
$ch = curl_init('https://crm.rentix.md/api/v1/media/bulk');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: ApiKey YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
{
"results": [
{ "op": "upload-from-url", "externalId": "apt-001-photo-1", "mediaId": 123, "success": true },
{ "op": "upload-from-url", "externalId": "apt-001-photo-2", "mediaId": 124, "success": true }
],
"summary": { "total": 2, "succeeded": 2, "failed": 0 }
}
Signed URL
Folosește această metodă pentru încărcarea fișierelor direct de pe client sau când fișierele nu sunt accesibile printr-un URL public.
Pasul 1. Solicită URL-ul pentru încărcare
const response = await fetch('https://crm.rentix.md/api/v1/media/request-upload-url', {
method: 'POST',
headers: {
'Authorization': 'ApiKey YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
files: [
{ fileName: 'living-room.jpg', size: 245000, contentType: 'image/jpeg', externalId: 'apt-001-photo-1' }
]
})
});
const result = await response.json();
console.log(`URL încărcare: ${result.upload[0].url}`);
curl -X POST https://crm.rentix.md/api/v1/media/request-upload-url \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"files": [
{ "fileName": "living-room.jpg", "size": 245000, "contentType": "image/jpeg", "externalId": "apt-001-photo-1" }
]
}'
$data = [
'files' => [
['fileName' => 'living-room.jpg', 'size' => 245000, 'contentType' => 'image/jpeg', 'externalId' => 'apt-001-photo-1']
]
];
$ch = curl_init('https://crm.rentix.md/api/v1/media/request-upload-url');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: ApiKey YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
{
"uuid": "abc123",
"upload": [
{
"url": "https://storage.googleapis.com/bucket/abc123_living-room.jpg?signature=...",
"generatedFileName": "abc123_living-room.jpg",
"externalId": "apt-001-photo-1"
}
]
}
Pasul 2. Încarcă fișierul
Trimite fișierul cu o cerere PUT la URL-ul primit:
curl -X PUT "https://storage.googleapis.com/bucket/abc123_living-room.jpg?signature=..." \
-H "Content-Type: image/jpeg" \
--data-binary @living-room.jpg
Pasul 3. Confirmă încărcarea
Folosește endpoint-ul bulk cu operația confirm-upload:
const response = await fetch('https://crm.rentix.md/api/v1/media/bulk', {
method: 'POST',
headers: {
'Authorization': 'ApiKey YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
operations: [
{
op: 'confirm-upload',
uuid: 'abc123',
generatedFileName: 'abc123_living-room.jpg',
externalId: 'apt-001-photo-1'
}
]
})
});
const result = await response.json();
console.log(`Confirmate: ${result.summary.succeeded} din ${result.summary.total}`);
curl -X POST https://crm.rentix.md/api/v1/media/bulk \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{
"op": "confirm-upload",
"uuid": "abc123",
"generatedFileName": "abc123_living-room.jpg",
"externalId": "apt-001-photo-1"
}
]
}'
$data = [
'operations' => [
[
'op' => 'confirm-upload',
'uuid' => 'abc123',
'generatedFileName' => 'abc123_living-room.jpg',
'externalId' => 'apt-001-photo-1'
]
]
];
$ch = curl_init('https://crm.rentix.md/api/v1/media/bulk');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: ApiKey YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);
Leagă fotografiile la anunț
După încărcare, leagă fotografiile la anunț. Sunt trei modalități de a indica fișierul:
După internal ID
{
"files": [
{ "id": 123 },
{ "id": 124 }
]
}
După external ID
{
"files": [
{ "externalFileId": "apt-001-photo-1" },
{ "externalFileId": "apt-001-photo-2" }
]
}
După URL (auto-import)
{
"files": [
{ "url": "https://placehold.co/1920x1080/jpg?text=Photo+1", "externalFileId": "apt-001-photo-1" },
{ "url": "https://placehold.co/1920x1080/jpg?text=Photo+2", "externalFileId": "apt-001-photo-2" }
]
}
Operații bulk cu media
Toate operațiile cu fișiere media pot fi efectuate prin endpoint-ul unic POST /media/bulk:
| Operație | Descriere |
|---|---|
upload-from-url | Încarcă fișier după URL |
confirm-upload | Confirmă încărcare prin signed URL |
link | Leagă external ID la fișier |
unlink | Dezleagă external ID |
delete | Șterge fișier |
Exemplu combinație operații
{
"operations": [
{ "op": "upload-from-url", "url": "https://example.com/new.jpg", "externalId": "new-photo" },
{ "op": "link", "mediaId": 123, "externalId": "old-photo-linked" },
{ "op": "delete", "externalId": "old-photo-to-remove" }
]
}
Gestionarea erorilor
O eroare într-o operație nu oprește celelalte. Verifică success pentru fiecare rezultat:
{
"results": [
{ "op": "upload-from-url", "externalId": "photo-1", "mediaId": 123, "success": true },
{
"op": "upload-from-url",
"externalId": "photo-2",
"mediaId": null,
"success": false,
"error": {
"statusCode": 400,
"body": {
"error": "Duplicate external ID",
"error_code": "DUPLICATE_EXTERNAL_ID"
}
}
}
],
"summary": { "total": 2, "succeeded": 1, "failed": 1 }
}
Erori frecvente
| Eroare | Cauză | Soluție |
|---|---|---|
Duplicate external ID | External ID este deja folosit | Folosește un ID unic pentru fiecare fișier |
Upload URL expired | Signed URL a expirat | Solicită un URL nou |
Invalid content type | Format fișier invalid | Folosește JPEG, PNG, WebP sau HEIC |
File too large | Fișier prea mare | Micșorează dimensiunea sau comprimă |