curl --request POST \
--url https://api.getoneprofile.ai/table-imports/preview/ \
--header 'Content-Type: multipart/form-data' \
--header 'X-API-Key: <api-key>' \
--form file='@example-file'import requests
url = "https://api.getoneprofile.ai/table-imports/preview/"
files = { "file": ("example-file", open("example-file", "rb")) }
headers = {"X-API-Key": "<api-key>"}
response = requests.post(url, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
const options = {method: 'POST', headers: {'X-API-Key': '<api-key>'}};
options.body = form;
fetch('https://api.getoneprofile.ai/table-imports/preview/', 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.getoneprofile.ai/table-imports/preview/",
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=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"X-API-Key: <api-key>"
],
]);
$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.getoneprofile.ai/table-imports/preview/"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.getoneprofile.ai/table-imports/preview/")
.header("X-API-Key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getoneprofile.ai/table-imports/preview/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"columns": [
{
"inferred_type": "text",
"name": "<string>",
"sample_values": [
"<string>"
],
"source_index": 123
}
],
"estimated_row_count": 123,
"import_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"importable_row_count": 123,
"row_limit": 123,
"sample_rows": [
[
"<string>"
]
],
"warnings": [
"<string>"
],
"selected_sheet": "<string>",
"sheet_names": [
"<string>"
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>",
"issues": [
{
"input": "<string>",
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>"
}Upload a CSV or Excel file and preview the table it would create
Upload a .csv or .xlsx file. The response carries one suggested column per field — a name taken from the header row and a type every sampled value fits — plus a few raw rows so the user can judge those guesses.
NOTHING is created here: no table, no columns, no rows. Review the mapping, edit it, and POST it to the commit endpoint to build the table.
The format is decided by the file’s own first bytes, not by its name or its declared content type, both of which are client-supplied. A workbook is read one sheet at a time: sheet_names lists the rest and the sheet endpoint re-reads the same upload from another one.
Rejects a file that is too large or too wide, so an import that cannot succeed fails before it costs a table name. A file with more rows than the plan allows is NOT rejected: importable_row_count comes back below estimated_row_count and the import takes the file’s first rows.
curl --request POST \
--url https://api.getoneprofile.ai/table-imports/preview/ \
--header 'Content-Type: multipart/form-data' \
--header 'X-API-Key: <api-key>' \
--form file='@example-file'import requests
url = "https://api.getoneprofile.ai/table-imports/preview/"
files = { "file": ("example-file", open("example-file", "rb")) }
headers = {"X-API-Key": "<api-key>"}
response = requests.post(url, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', '<string>');
const options = {method: 'POST', headers: {'X-API-Key': '<api-key>'}};
options.body = form;
fetch('https://api.getoneprofile.ai/table-imports/preview/', 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.getoneprofile.ai/table-imports/preview/",
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=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"X-API-Key: <api-key>"
],
]);
$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.getoneprofile.ai/table-imports/preview/"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.getoneprofile.ai/table-imports/preview/")
.header("X-API-Key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getoneprofile.ai/table-imports/preview/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"columns": [
{
"inferred_type": "text",
"name": "<string>",
"sample_values": [
"<string>"
],
"source_index": 123
}
],
"estimated_row_count": 123,
"import_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"importable_row_count": 123,
"row_limit": 123,
"sample_rows": [
[
"<string>"
]
],
"warnings": [
"<string>"
],
"selected_sheet": "<string>",
"sheet_names": [
"<string>"
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>",
"issues": [
{
"input": "<string>",
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>"
}
]
}{
"detail": "<string>"
}{
"detail": "<string>"
}{
"detail": "<string>"
}Authorizations
Body
The .csv or .xlsx file to import.
Response
Successful Response
What an upload returns: a mapping to review, and enough of the file to judge it.
Nothing is created yet — no table, no columns, no rows. Edit the mapping and POST it to the commit endpoint to actually build the table.
When importable_row_count is below estimated_row_count the file is
longer than the plan allows and the import will take its first
importable_row_count rows. Say so before the user commits: the two numbers
are here as numbers, rather than as a sentence in warnings, because the
client puts its upgrade control beside them.
The inferred mapping.
Show child attributes
Show child attributes
Data rows in the file, excluding the header.
Identifies this upload through commit and polling.
How many of those rows the import will write, once the cap is applied.
Rows one table may hold on this organisation's plan.
Raw sampled rows, in file order.
Non-fatal things the user should see.
Which sheet these columns were read from. Null for a CSV. POST it to the sheet endpoint to re-read the same upload from a different one.
Every sheet the uploaded workbook offers, in tab order. Empty for a CSV, which has no sheets — that is what says not to offer a sheet picker.
Was this page helpful?