Email, calendar & files
List, search, upload, download, organise and share files in a user's Google Drive or OneDrive, let users pick Drive files, and use them as post media.
Work with files in your users' Google Drive or OneDrive. Save a generated report into their drive, fetch a contract they picked, share a link, or attach a drive file to a social post. Every call takes the accountId of an account connected with the files area.
#What Pozy can see
| Provider | Access |
|---|---|
| Google Drive | Only files created through Pozy and files the user picked in Google Picker. Pozy never asks for full Drive access |
| OneDrive | Every file the user can see in their OneDrive. No picker step |
On Google, a file outside those two groups returns 404 with details.reason: "file_not_granted". Picker sessions, which let the user grant such a file, are not available yet (see below), so for now work with files created through Pozy.
#Ask the user to choose Drive files
Picker sessions are not available yet: POST /v1/files/picker-sessions answers 403 with code: "feature_not_available". This section describes how they will work once Pozy hosts the picker page.
Start a picker session and open its url in the user's browser. Pozy hosts the page, where Google Picker lets them select the files to share.
curl -X POST https://api.pozy.ai/v1/files/picker-sessions \
-H "Authorization: Bearer $POZY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "6710c501e4b0d2f1a8c95e77",
"redirectUrl": "https://app.example.com/files/picked",
"mimeTypes": ["application/pdf", "image/jpeg", "image/png"]
}'const res = await fetch("https://api.pozy.ai/v1/files/picker-sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
accountId: "6710c501e4b0d2f1a8c95e77",
redirectUrl: "https://app.example.com/files/picked",
mimeTypes: ["application/pdf", "image/jpeg", "image/png"],
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
// Redirect the user to data.data.urlimport os, requests
session = requests.post(
"https://api.pozy.ai/v1/files/picker-sessions",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
json={"accountId": "6710c501e4b0d2f1a8c95e77", "redirectUrl": "https://app.example.com/files/picked"},
).json()["data"]| Field | What it does |
|---|---|
redirectUrl |
Where the user goes afterwards. Optional if you handle picks on your server |
fileIds |
Files already ticked when the picker opens, 50 at most |
mimeTypes |
Only show these types, 30 at most |
multiselect |
Allow several files. Default true |
Once the user is done, Pozy sends them to redirectUrl with pickerSessionId and either status=picked plus the chosen fileIds (comma-separated) or status=cancelled. The same files also arrive in a file.picked webhook. Each session works once and lapses after 30 minutes, so make a new one for every pick. Access to picked files does not lapse: Pozy can read them until the user removes the app in their Google account. Pickers exist for Google only; on a Microsoft account the call fails with 400 platform_not_supported.
#List and search
curl "https://api.pozy.ai/v1/files?accountId=6710c501e4b0d2f1a8c95e77&q=invoice&limit=20" \
-H "Authorization: Bearer $POZY_API_KEY"const res = await fetch("https://api.pozy.ai/v1/files?accountId=6710c501e4b0d2f1a8c95e77&q=invoice&limit=20", {
headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
for (const f of data.data) console.log(f.kind, f.name, f.size, f.webUrl);files = requests.get(
"https://api.pozy.ai/v1/files",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
params={"accountId": "6710c501e4b0d2f1a8c95e77", "q": "invoice", "limit": 20},
).json()["data"]Without folderId you get the root (OneDrive) or the granted files (Drive). q searches names (and content on OneDrive), up to 200 characters. Pages hold up to 100 items, 50 by default. Each item has id, name, kind (file or folder), mimeType, size, parentId, webUrl, downloadable, createdAt, modifiedAt and trashed. GET /v1/files/{fileId}?accountId=... returns one item.
#Download
GET /v1/files/{fileId}/download?accountId=... returns the file's content, with its filename and content type. Files in Google's own formats are not stored as bytes, so Pozy converts them as it downloads:
| Google file | You receive |
|---|---|
| Docs | |
| Slides | |
| Sheets | XLSX |
| Drawings | PNG |
Folders, Forms and Sites cannot be downloaded and show downloadable: false.
#Upload
Upload from a URL as JSON, or send the file as multipart/form-data:
curl -X POST https://api.pozy.ai/v1/files \
-H "Authorization: Bearer $POZY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "6710c501e4b0d2f1a8c95e77",
"name": "October report.pdf",
"contentType": "application/pdf",
"url": "https://files.example.com/reports/october.pdf",
"parentId": "1qFolderAbC"
}'const res = await fetch("https://api.pozy.ai/v1/files", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
accountId: "6710c501e4b0d2f1a8c95e77",
name: "October report.pdf",
contentType: "application/pdf",
url: "https://files.example.com/reports/october.pdf",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.data.id, data.data.webUrl);resp = requests.post(
"https://api.pozy.ai/v1/files",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
json={
"accountId": "6710c501e4b0d2f1a8c95e77",
"name": "October report.pdf",
"contentType": "application/pdf",
"url": "https://files.example.com/reports/october.pdf",
},
)| Limit | Value |
|---|---|
| Upload by URL | Up to 100 MB, HTTPS only, no redirects, must download within 20 seconds |
| Multipart upload | Bounded by the 4.5 MB request size. Send larger files by URL |
| Names | Up to 255 characters, no / or \ |
convertTo |
Google only: import as a Google Doc, Sheet or Slides. OneDrive refuses it |
A file uploaded through Pozy is granted from then on, so you can read it back on Drive.
#Organise and share
| Job | Call |
|---|---|
| Create a folder | POST /v1/files/folders with name and optional parentId |
| Rename or move | PATCH /v1/files/{fileId} with name or parentId |
| Trash | DELETE /v1/files/{fileId}?accountId=... (Drive trash, OneDrive recycle bin) |
| Share link | GET /v1/files/{fileId}/share-link?accountId=... opens the file to anyone who has the link, and gives you that link |
If a company has disabled anonymous links in OneDrive, the share-link call fails for its files.
#Post a file from a drive
In a post's mediaItems, a drive file can stand in for a URL:
{
"mediaItems": [{ "type": "image", "fileId": "1AbCdEfGhIjK", "accountId": "6710c501e4b0d2f1a8c95e77" }]
}Pozy takes its own copy as soon as the post is created. Later edits to the file, or a disconnected account, do not affect the post. A folder, or any file with nothing to download, makes that media item fail with 400. See Media.
#Webhook events
file.created, file.updated and file.deleted fire for changes to files Pozy can see. The payload carries the file id and changeType; fetch the file for its current state. file.picked lists the files chosen in a picker session.
| Event | When it fires |
|---|---|
file.created |
File created. |
file.updated |
File updated. |
file.picked |
Files picked. |
file.deleted |
File deleted. |
#Errors
| Error | Cause | Fix |
|---|---|---|
404, reason: "file_not_granted" |
Pozy has no access to that Drive file: it was not made through Pozy and the user never picked it | Use a file created through Pozy. Picker sessions are not available yet |
400 on url |
The link is not HTTPS, redirects, or points to more than 100 MB | Link straight to the file over HTTPS, and keep it under 100 MB |
400 platform_not_supported |
Picker sessions and convertTo on a Microsoft account |
Both only exist for Google |
412 account_scope_missing |
No files area on the account |
Reconnect with files in scopes |
#Endpoints
| Endpoint | What it does |
|---|---|
GET /v1/files |
List files in a folder or search the drive |
POST /v1/files |
Upload a file |
POST /v1/files/folders |
Create a folder |
POST /v1/files/picker-sessions |
Create a hosted Google Picker session (not available yet) |
GET /v1/files/{fileId} |
Get a file or folder |
PATCH /v1/files/{fileId} |
Rename or move a file |
DELETE /v1/files/{fileId} |
Move a file to the trash |
GET /v1/files/{fileId}/download |
Download a file |
GET /v1/files/{fileId}/share-link |
Get an anyone-with-the-link share link |