curl --request POST \
--url https://api.luminpdf.com/v1/workspaces/spaces \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "Sales Team",
"members": [
{
"user_id": "5eafc19053615900182f85c6",
"role": "member"
}
]
}
'import requests
url = "https://api.luminpdf.com/v1/workspaces/spaces"
payload = {
"name": "Sales Team",
"members": [
{
"user_id": "5eafc19053615900182f85c6",
"role": "member"
}
]
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Sales Team',
members: [{user_id: '5eafc19053615900182f85c6', role: 'member'}]
})
};
fetch('https://api.luminpdf.com/v1/workspaces/spaces', 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.luminpdf.com/v1/workspaces/spaces",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Sales Team',
'members' => [
[
'user_id' => '5eafc19053615900182f85c6',
'role' => 'member'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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.luminpdf.com/v1/workspaces/spaces"
payload := strings.NewReader("{\n \"name\": \"Sales Team\",\n \"members\": [\n {\n \"user_id\": \"5eafc19053615900182f85c6\",\n \"role\": \"member\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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.luminpdf.com/v1/workspaces/spaces")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Sales Team\",\n \"members\": [\n {\n \"user_id\": \"5eafc19053615900182f85c6\",\n \"role\": \"member\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.luminpdf.com/v1/workspaces/spaces")
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["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Sales Team\",\n \"members\": [\n {\n \"user_id\": \"5eafc19053615900182f85c6\",\n \"role\": \"member\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"space": {
"id": "69d74983d0cbaa0977be7997",
"name": "Sales Team",
"created_at": "2026-04-09T06:38:59.381Z",
"workspace_id": "60ab55f099ce3f001250857b",
"role_of_user": "admin",
"total_members": 2,
"owner": {
"user_id": "655f01fadb5d4b9916422581",
"name": "Jane Smith",
"email": "[email protected]"
},
"member_invite_notice": "Some members couldn't be added as they're not in this Workspace or aren't eligible."
}
}{
"error_code": "<string>",
"error_message": "<string>"
}Create Space
Create a new Space within the authorized Workspace.
curl --request POST \
--url https://api.luminpdf.com/v1/workspaces/spaces \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "Sales Team",
"members": [
{
"user_id": "5eafc19053615900182f85c6",
"role": "member"
}
]
}
'import requests
url = "https://api.luminpdf.com/v1/workspaces/spaces"
payload = {
"name": "Sales Team",
"members": [
{
"user_id": "5eafc19053615900182f85c6",
"role": "member"
}
]
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'Sales Team',
members: [{user_id: '5eafc19053615900182f85c6', role: 'member'}]
})
};
fetch('https://api.luminpdf.com/v1/workspaces/spaces', 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.luminpdf.com/v1/workspaces/spaces",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Sales Team',
'members' => [
[
'user_id' => '5eafc19053615900182f85c6',
'role' => 'member'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"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.luminpdf.com/v1/workspaces/spaces"
payload := strings.NewReader("{\n \"name\": \"Sales Team\",\n \"members\": [\n {\n \"user_id\": \"5eafc19053615900182f85c6\",\n \"role\": \"member\"\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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.luminpdf.com/v1/workspaces/spaces")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Sales Team\",\n \"members\": [\n {\n \"user_id\": \"5eafc19053615900182f85c6\",\n \"role\": \"member\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.luminpdf.com/v1/workspaces/spaces")
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["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Sales Team\",\n \"members\": [\n {\n \"user_id\": \"5eafc19053615900182f85c6\",\n \"role\": \"member\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"space": {
"id": "69d74983d0cbaa0977be7997",
"name": "Sales Team",
"created_at": "2026-04-09T06:38:59.381Z",
"workspace_id": "60ab55f099ce3f001250857b",
"role_of_user": "admin",
"total_members": 2,
"owner": {
"user_id": "655f01fadb5d4b9916422581",
"name": "Jane Smith",
"email": "[email protected]"
},
"member_invite_notice": "Some members couldn't be added as they're not in this Workspace or aren't eligible."
}
}{
"error_code": "<string>",
"error_message": "<string>"
}Required scopes (OAuth 2.0)
Required scopes (OAuth 2.0)
workspacesAuthorizations
Provide your API key in the X-API-Key header, e.g., X-API-Key: YOUR_API_KEY.
Body
The name of the Space to create.
1 - 100Initial members to invite into the Space. If omitted, the Space is created with only the requesting user as owner. Ineligible entries are skipped; see member_invite_notice on the response.
Hide child attributes
Hide child attributes
Lumin user ID of the member to invite. Must correspond to a user returned by Get Workspace Members for this Workspace. If the user is not an active Workspace member or fails other invite checks, this entry is skipped; the Space is still created and an aggregate member_invite_notice may be returned.
Role assigned to this member in the new Space.
admin, member Response
Returns the newly created Space.
Hide child attributes
Hide child attributes
The unique identifier of the newly created Space.
The name of the Space.
The timestamp when the Space was created (ISO 8601).
The ID of the parent Workspace this Space belongs to.
The role of the requesting user in the newly created Space (typically admin).
admin, member Total members in the Space after this request (owner plus every members entry that was successfully invited). Skipped invitees are not counted.
Optional. Omitted when every requested members entry was successfully invited. When present, at least one invitee was skipped (the Space was still created).