cURL
curl 'https://api.gumloop.com/api/v1/brain/sources/PFqdAMir8PA2Xc6qcszSN9/files' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-F 'files=@handbook.pdf' \
-F 'files=@release-process.md'from gumloop import Gumloop
client = Gumloop(access_token="YOUR_ACCESS_TOKEN")
upload = client.brain.upload_files(
"PFqdAMir8PA2Xc6qcszSN9",
{"handbook.pdf": open("handbook.pdf", "rb").read()},
)
print([f.status for f in upload.files], upload.rejected)
const form = new FormData();
form.append('files', '<string>');
form.append('files.items', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.gumloop.com/api/v1/brain/sources/{source_id}/files', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gumloop.com/api/v1/brain/sources/{source_id}/files",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data; boundary=---011000010111000001101001"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gumloop.com/api/v1/brain/sources/{source_id}/files"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gumloop.com/api/v1/brain/sources/{source_id}/files")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gumloop.com/api/v1/brain/sources/{source_id}/files")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'multipart/form-data; boundary=---011000010111000001101001'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"files": [
{
"id": "f2bf0108-1650-47cd-a20d-15268a3cc5cc",
"file_name": "handbook.pdf",
"mime_type": "application/pdf",
"size_bytes": 48213,
"sha256": "9bae5b3a3eb1af86840cd141aa644f73d55ec445e056b74fb2ecffc17f15ac9d",
"status": "uploaded",
"error": null,
"document_id": null,
"created_at": "2026-09-25T23:52:13.997124+00:00",
"indexed_at": null
}
],
"rejected": [
{
"file_name": "notes.exe",
"error": "unsupported file type \".exe\""
}
],
"sync_run_id": "4umrkunyhiBgUhLLBT2toA"
}Upload files
Upload up to 25 files as multipart/form-data parts named files. Accepted types are PDF, Word, PowerPoint, Excel, and text formats (.txt, .md, .html, .csv, .rtf), each up to 25 MB.
Indexing starts on its own after the upload: an active source indexes and bills immediately, a draft source runs a credit estimate instead (see Retrieve estimate). Poll List files until each file’s status is indexed.
Files the upload policy refuses (unsupported type, too large, empty) are returned in rejected with a 201; the request is a 400 no_files_accepted only when every file was refused.
POST
/
brain
/
sources
/
{source_id}
/
files
cURL
curl 'https://api.gumloop.com/api/v1/brain/sources/PFqdAMir8PA2Xc6qcszSN9/files' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-F 'files=@handbook.pdf' \
-F 'files=@release-process.md'from gumloop import Gumloop
client = Gumloop(access_token="YOUR_ACCESS_TOKEN")
upload = client.brain.upload_files(
"PFqdAMir8PA2Xc6qcszSN9",
{"handbook.pdf": open("handbook.pdf", "rb").read()},
)
print([f.status for f in upload.files], upload.rejected)
const form = new FormData();
form.append('files', '<string>');
form.append('files.items', '{
"fileName": "example-file"
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.gumloop.com/api/v1/brain/sources/{source_id}/files', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.gumloop.com/api/v1/brain/sources/{source_id}/files",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data; boundary=---011000010111000001101001"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.gumloop.com/api/v1/brain/sources/{source_id}/files"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.gumloop.com/api/v1/brain/sources/{source_id}/files")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "multipart/form-data; boundary=---011000010111000001101001")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gumloop.com/api/v1/brain/sources/{source_id}/files")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'multipart/form-data; boundary=---011000010111000001101001'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files.items\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n{\r\n \"fileName\": \"example-file\"\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"files": [
{
"id": "f2bf0108-1650-47cd-a20d-15268a3cc5cc",
"file_name": "handbook.pdf",
"mime_type": "application/pdf",
"size_bytes": 48213,
"sha256": "9bae5b3a3eb1af86840cd141aa644f73d55ec445e056b74fb2ecffc17f15ac9d",
"status": "uploaded",
"error": null,
"document_id": null,
"created_at": "2026-09-25T23:52:13.997124+00:00",
"indexed_at": null
}
],
"rejected": [
{
"file_name": "notes.exe",
"error": "unsupported file type \".exe\""
}
],
"sync_run_id": "4umrkunyhiBgUhLLBT2toA"
}Authorizations
Path Parameters
The source id.
Body
multipart/form-data
One part per file. The part's filename becomes the file's name in the source.
Maximum array length:
25Response
At least one file was stored.
Was this page helpful?
