cURL
curl --request POST \
--url https://api.nekt.ai/api/v1/organization/object-permissions/ \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"assignments": [
{
"users": [],
"groups": [],
"secrets": [],
"live_connections": [],
"tools": [
"<string>"
]
}
],
"notify_members": false,
"message": "<string>"
}
'import requests
url = "https://api.nekt.ai/api/v1/organization/object-permissions/"
payload = {
"assignments": [
{
"users": [],
"groups": [],
"secrets": [],
"live_connections": [],
"tools": ["<string>"]
}
],
"notify_members": False,
"message": "<string>"
}
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({
assignments: [
{users: [], groups: [], secrets: [], live_connections: [], tools: ['<string>']}
],
notify_members: false,
message: '<string>'
})
};
fetch('https://api.nekt.ai/api/v1/organization/object-permissions/', 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.nekt.ai/api/v1/organization/object-permissions/",
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([
'assignments' => [
[
'users' => [
],
'groups' => [
],
'secrets' => [
],
'live_connections' => [
],
'tools' => [
'<string>'
]
]
],
'notify_members' => false,
'message' => '<string>'
]),
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.nekt.ai/api/v1/organization/object-permissions/"
payload := strings.NewReader("{\n \"assignments\": [\n {\n \"users\": [],\n \"groups\": [],\n \"secrets\": [],\n \"live_connections\": [],\n \"tools\": [\n \"<string>\"\n ]\n }\n ],\n \"notify_members\": false,\n \"message\": \"<string>\"\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.nekt.ai/api/v1/organization/object-permissions/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"assignments\": [\n {\n \"users\": [],\n \"groups\": [],\n \"secrets\": [],\n \"live_connections\": [],\n \"tools\": [\n \"<string>\"\n ]\n }\n ],\n \"notify_members\": false,\n \"message\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nekt.ai/api/v1/organization/object-permissions/")
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 \"assignments\": [\n {\n \"users\": [],\n \"groups\": [],\n \"secrets\": [],\n \"live_connections\": [],\n \"tools\": [\n \"<string>\"\n ]\n }\n ],\n \"notify_members\": false,\n \"message\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"created": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"permission_level": "manager",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"user": 123,
"group": "<string>",
"secret": "<string>",
"live_connection": "<string>",
"granted_by": 123,
"tool_scope": "<unknown>"
}
],
"updated": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"permission_level": "manager",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"user": 123,
"group": "<string>",
"secret": "<string>",
"live_connection": "<string>",
"granted_by": 123,
"tool_scope": "<unknown>"
}
],
"revoked": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"permission_level": "manager",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"user": 123,
"group": "<string>",
"secret": "<string>",
"live_connection": "<string>",
"granted_by": 123,
"tool_scope": "<unknown>"
}
]
}Secrets & live connections
Assign Object Permissions
Grant, change, and revoke access to secrets and live connections in a single call.
POST
/
api
/
v1
/
organization
/
object-permissions
/
cURL
curl --request POST \
--url https://api.nekt.ai/api/v1/organization/object-permissions/ \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"assignments": [
{
"users": [],
"groups": [],
"secrets": [],
"live_connections": [],
"tools": [
"<string>"
]
}
],
"notify_members": false,
"message": "<string>"
}
'import requests
url = "https://api.nekt.ai/api/v1/organization/object-permissions/"
payload = {
"assignments": [
{
"users": [],
"groups": [],
"secrets": [],
"live_connections": [],
"tools": ["<string>"]
}
],
"notify_members": False,
"message": "<string>"
}
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({
assignments: [
{users: [], groups: [], secrets: [], live_connections: [], tools: ['<string>']}
],
notify_members: false,
message: '<string>'
})
};
fetch('https://api.nekt.ai/api/v1/organization/object-permissions/', 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.nekt.ai/api/v1/organization/object-permissions/",
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([
'assignments' => [
[
'users' => [
],
'groups' => [
],
'secrets' => [
],
'live_connections' => [
],
'tools' => [
'<string>'
]
]
],
'notify_members' => false,
'message' => '<string>'
]),
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.nekt.ai/api/v1/organization/object-permissions/"
payload := strings.NewReader("{\n \"assignments\": [\n {\n \"users\": [],\n \"groups\": [],\n \"secrets\": [],\n \"live_connections\": [],\n \"tools\": [\n \"<string>\"\n ]\n }\n ],\n \"notify_members\": false,\n \"message\": \"<string>\"\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.nekt.ai/api/v1/organization/object-permissions/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"assignments\": [\n {\n \"users\": [],\n \"groups\": [],\n \"secrets\": [],\n \"live_connections\": [],\n \"tools\": [\n \"<string>\"\n ]\n }\n ],\n \"notify_members\": false,\n \"message\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nekt.ai/api/v1/organization/object-permissions/")
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 \"assignments\": [\n {\n \"users\": [],\n \"groups\": [],\n \"secrets\": [],\n \"live_connections\": [],\n \"tools\": [\n \"<string>\"\n ]\n }\n ],\n \"notify_members\": false,\n \"message\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"created": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"permission_level": "manager",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"user": 123,
"group": "<string>",
"secret": "<string>",
"live_connection": "<string>",
"granted_by": 123,
"tool_scope": "<unknown>"
}
],
"updated": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"permission_level": "manager",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"user": 123,
"group": "<string>",
"secret": "<string>",
"live_connection": "<string>",
"granted_by": 123,
"tool_scope": "<unknown>"
}
],
"revoked": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"permission_level": "manager",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"user": 123,
"group": "<string>",
"secret": "<string>",
"live_connection": "<string>",
"granted_by": 123,
"tool_scope": "<unknown>"
}
]
}The same declarative bulk upsert as Assign Permissions, applied to the resources that live outside the Catalog: secrets and live connections. Each assignment is a cross product of recipients and resources, and
Each object in
Three rules govern
permission_level: null revokes.
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
assignments | array of objects | Yes | One or more assignment blocks. Must not be empty. |
notify_members | boolean | No | Accepted for compatibility. See the note below. |
message | string | No | Accepted for compatibility. See the note below. |
notify_members and message are accepted by this endpoint but do not send email. Grants take effect regardless; recipients are simply not notified.assignments:
| Parameter | Type | Required | Description |
|---|---|---|---|
permission_level | viewer, editor, manager, or null | Yes | The level to apply. null revokes. |
users | array of integers | No | Recipient user ids. |
groups | array of UUIDs | No | Recipient permission groups. |
secrets | array of UUIDs | No | Target secrets. |
live_connections | array of UUIDs | No | Target live connections. |
tools | array of strings | No | Live connections only. Restrict the grant to a subset of the connection’s available tools. Omit for the full set; [] grants no tools. |
What the levels mean here
Secrets and live connections do not use the Catalog meaning of the levels. Secret grants are enforced once secret permissions are enabled for your workspace.| Level | Secret | Live connection |
|---|---|---|
viewer | See the metadata and reference the secret in Queries and Notebooks. | Use the connection’s tools. |
editor | Also edit the description and rotate the value. | Also edit the description and tags. Nothing else. |
manager | Also manage access and delete the secret. | Also change config, status, slug, tools, and setup links, and delete. |
The value of a secret is never readable through the API at any level, including
manager. Only pipeline and notebook runtimes resolve it.Share a secret with a group
curl --request POST \
--url https://api.nekt.ai/api/v1/organization/object-permissions/ \
--header "x-api-key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"assignments": [
{
"permission_level": "viewer",
"groups": ["b8c5e1e3-6d02-4f45-ad20-8f4b6e2d0e13"],
"secrets": ["c9d0e1f2-a3b4-45c6-87d8-e9f0a1b2c3d4"]
}
]
}'
Scope a live connection to specific tools
tools narrows what the recipient may call. It is validated against each connection’s current available set: a name the connection does not expose is rejected with Connection '<slug>' has no available tools named: ….
curl --request POST \
--url https://api.nekt.ai/api/v1/organization/object-permissions/ \
--header "x-api-key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"assignments": [
{
"permission_level": "viewer",
"users": [42],
"live_connections": ["d1e2f3a4-b5c6-47d8-99e0-f1a2b3c4d5e6"],
"tools": ["search_contacts", "get_contact"]
}
]
}'
tools, and all three return 400 when broken:
- It requires at least one live connection in the same assignment. A block with
toolsand onlysecretsis an error. - It cannot be combined with
manager, since a manager always holds the full set. - Every name must be currently available on every connection in the same assignment.
Omitting
tools is not the same as listing every tool. Omitted means “whatever is available”, and it keeps tracking the connection as tools are added or removed. An explicit list is a fixed subset, and tools: [] grants no tools at all. Re-assigning an existing scoped grant without tools resets it to the full set.Removing a tool from a live connection’s available set strips it from every grant that named it. Adding the tool back later does not restore those grants: you have to reassign them.
Errors
| Status | When |
|---|---|
400 | A tools rule was broken, a recipient’s membership is deactivated, or a referenced resource is not visible to the key’s creator. |
403 | The key’s ceiling does not allow the grant. See Permissions flow. |
Related
- Permissions flow: the end-to-end walkthrough and the ceiling rules.
- List Object Permission Recipients: where recipient ids come from.
- Secrets: what a secret is and how levels behave in the app.
Authorizations
API Key authentication. Format: 'x-api-key: api_key'
Body
application/jsonapplication/x-www-form-urlencodedmultipart/form-data
Was this page helpful?