Create custom context items
curl --request POST \
--url https://api.getmodus.com/api/v1/context/custom-items/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"items": [
{
"kind": "entity",
"sourceId": "billing-db",
"sourceName": "Billing database",
"collectionId": "contracts",
"collectionName": "Contracts",
"externalId": "contract-123",
"name": "Acme renewal contract",
"entityType": "contract",
"description": "Enterprise renewal metadata from the internal billing system.",
"attributes": [
{
"name": "status",
"dataType": "string",
"value": {
"text": "active"
}
}
],
"topics": [
"billing",
"renewals"
]
}
]
}
'import requests
url = "https://api.getmodus.com/api/v1/context/custom-items/batch"
payload = { "items": [
{
"kind": "entity",
"sourceId": "billing-db",
"sourceName": "Billing database",
"collectionId": "contracts",
"collectionName": "Contracts",
"externalId": "contract-123",
"name": "Acme renewal contract",
"entityType": "contract",
"description": "Enterprise renewal metadata from the internal billing system.",
"attributes": [
{
"name": "status",
"dataType": "string",
"value": { "text": "active" }
}
],
"topics": ["billing", "renewals"]
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
items: [
{
kind: 'entity',
sourceId: 'billing-db',
sourceName: 'Billing database',
collectionId: 'contracts',
collectionName: 'Contracts',
externalId: 'contract-123',
name: 'Acme renewal contract',
entityType: 'contract',
description: 'Enterprise renewal metadata from the internal billing system.',
attributes: [{name: 'status', dataType: 'string', value: {text: 'active'}}],
topics: ['billing', 'renewals']
}
]
})
};
fetch('https://api.getmodus.com/api/v1/context/custom-items/batch', 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.getmodus.com/api/v1/context/custom-items/batch",
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([
'items' => [
[
'kind' => 'entity',
'sourceId' => 'billing-db',
'sourceName' => 'Billing database',
'collectionId' => 'contracts',
'collectionName' => 'Contracts',
'externalId' => 'contract-123',
'name' => 'Acme renewal contract',
'entityType' => 'contract',
'description' => 'Enterprise renewal metadata from the internal billing system.',
'attributes' => [
[
'name' => 'status',
'dataType' => 'string',
'value' => [
'text' => 'active'
]
]
],
'topics' => [
'billing',
'renewals'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.getmodus.com/api/v1/context/custom-items/batch"
payload := strings.NewReader("{\n \"items\": [\n {\n \"kind\": \"entity\",\n \"sourceId\": \"billing-db\",\n \"sourceName\": \"Billing database\",\n \"collectionId\": \"contracts\",\n \"collectionName\": \"Contracts\",\n \"externalId\": \"contract-123\",\n \"name\": \"Acme renewal contract\",\n \"entityType\": \"contract\",\n \"description\": \"Enterprise renewal metadata from the internal billing system.\",\n \"attributes\": [\n {\n \"name\": \"status\",\n \"dataType\": \"string\",\n \"value\": {\n \"text\": \"active\"\n }\n }\n ],\n \"topics\": [\n \"billing\",\n \"renewals\"\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.getmodus.com/api/v1/context/custom-items/batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"items\": [\n {\n \"kind\": \"entity\",\n \"sourceId\": \"billing-db\",\n \"sourceName\": \"Billing database\",\n \"collectionId\": \"contracts\",\n \"collectionName\": \"Contracts\",\n \"externalId\": \"contract-123\",\n \"name\": \"Acme renewal contract\",\n \"entityType\": \"contract\",\n \"description\": \"Enterprise renewal metadata from the internal billing system.\",\n \"attributes\": [\n {\n \"name\": \"status\",\n \"dataType\": \"string\",\n \"value\": {\n \"text\": \"active\"\n }\n }\n ],\n \"topics\": [\n \"billing\",\n \"renewals\"\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getmodus.com/api/v1/context/custom-items/batch")
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"] = 'application/json'
request.body = "{\n \"items\": [\n {\n \"kind\": \"entity\",\n \"sourceId\": \"billing-db\",\n \"sourceName\": \"Billing database\",\n \"collectionId\": \"contracts\",\n \"collectionName\": \"Contracts\",\n \"externalId\": \"contract-123\",\n \"name\": \"Acme renewal contract\",\n \"entityType\": \"contract\",\n \"description\": \"Enterprise renewal metadata from the internal billing system.\",\n \"attributes\": [\n {\n \"name\": \"status\",\n \"dataType\": \"string\",\n \"value\": {\n \"text\": \"active\"\n }\n }\n ],\n \"topics\": [\n \"billing\",\n \"renewals\"\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"contextItems": [
{
"contextItemId": "7a3f9d2c-1111-4000-a000-000000000abc",
"contextType": "custom_entity_metadata",
"dataPath": [
"billing-db",
"contracts",
"contract-123"
],
"title": "Acme renewal contract"
}
]
}{
"error": {
"code": "BAD_REQUEST",
"status": "INVALID_ARGUMENT",
"message": "Invalid value for query parameter `pageSize`.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "UNAUTHORIZED",
"status": "UNAUTHENTICATED",
"message": "Missing or invalid access token.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "FORBIDDEN",
"status": "PERMISSION_DENIED",
"message": "Missing required scope(s) for this operation.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS",
"info": {
"missing": [
"<required-scope>"
]
}
}
}{
"error": {
"code": "NOT_FOUND",
"status": "NOT_FOUND",
"message": "Resource not found.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "CONFLICT",
"status": "ALREADY_EXISTS",
"message": "A resource with that identifier already exists.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "VALIDATION",
"status": "INVALID_ARGUMENT",
"message": "Updates that would revoke your own access are not allowed.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"status": "INTERNAL",
"message": "An unexpected error occurred.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}Context
Create custom context items
Creates or updates a batch of customer-owned custom context items. Batch imports are idempotent by source, collection, entity, and field identifiers.
Requires: context:write
POST
/
api
/
v1
/
context
/
custom-items
/
batch
Create custom context items
curl --request POST \
--url https://api.getmodus.com/api/v1/context/custom-items/batch \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"items": [
{
"kind": "entity",
"sourceId": "billing-db",
"sourceName": "Billing database",
"collectionId": "contracts",
"collectionName": "Contracts",
"externalId": "contract-123",
"name": "Acme renewal contract",
"entityType": "contract",
"description": "Enterprise renewal metadata from the internal billing system.",
"attributes": [
{
"name": "status",
"dataType": "string",
"value": {
"text": "active"
}
}
],
"topics": [
"billing",
"renewals"
]
}
]
}
'import requests
url = "https://api.getmodus.com/api/v1/context/custom-items/batch"
payload = { "items": [
{
"kind": "entity",
"sourceId": "billing-db",
"sourceName": "Billing database",
"collectionId": "contracts",
"collectionName": "Contracts",
"externalId": "contract-123",
"name": "Acme renewal contract",
"entityType": "contract",
"description": "Enterprise renewal metadata from the internal billing system.",
"attributes": [
{
"name": "status",
"dataType": "string",
"value": { "text": "active" }
}
],
"topics": ["billing", "renewals"]
}
] }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
items: [
{
kind: 'entity',
sourceId: 'billing-db',
sourceName: 'Billing database',
collectionId: 'contracts',
collectionName: 'Contracts',
externalId: 'contract-123',
name: 'Acme renewal contract',
entityType: 'contract',
description: 'Enterprise renewal metadata from the internal billing system.',
attributes: [{name: 'status', dataType: 'string', value: {text: 'active'}}],
topics: ['billing', 'renewals']
}
]
})
};
fetch('https://api.getmodus.com/api/v1/context/custom-items/batch', 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.getmodus.com/api/v1/context/custom-items/batch",
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([
'items' => [
[
'kind' => 'entity',
'sourceId' => 'billing-db',
'sourceName' => 'Billing database',
'collectionId' => 'contracts',
'collectionName' => 'Contracts',
'externalId' => 'contract-123',
'name' => 'Acme renewal contract',
'entityType' => 'contract',
'description' => 'Enterprise renewal metadata from the internal billing system.',
'attributes' => [
[
'name' => 'status',
'dataType' => 'string',
'value' => [
'text' => 'active'
]
]
],
'topics' => [
'billing',
'renewals'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.getmodus.com/api/v1/context/custom-items/batch"
payload := strings.NewReader("{\n \"items\": [\n {\n \"kind\": \"entity\",\n \"sourceId\": \"billing-db\",\n \"sourceName\": \"Billing database\",\n \"collectionId\": \"contracts\",\n \"collectionName\": \"Contracts\",\n \"externalId\": \"contract-123\",\n \"name\": \"Acme renewal contract\",\n \"entityType\": \"contract\",\n \"description\": \"Enterprise renewal metadata from the internal billing system.\",\n \"attributes\": [\n {\n \"name\": \"status\",\n \"dataType\": \"string\",\n \"value\": {\n \"text\": \"active\"\n }\n }\n ],\n \"topics\": [\n \"billing\",\n \"renewals\"\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.getmodus.com/api/v1/context/custom-items/batch")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"items\": [\n {\n \"kind\": \"entity\",\n \"sourceId\": \"billing-db\",\n \"sourceName\": \"Billing database\",\n \"collectionId\": \"contracts\",\n \"collectionName\": \"Contracts\",\n \"externalId\": \"contract-123\",\n \"name\": \"Acme renewal contract\",\n \"entityType\": \"contract\",\n \"description\": \"Enterprise renewal metadata from the internal billing system.\",\n \"attributes\": [\n {\n \"name\": \"status\",\n \"dataType\": \"string\",\n \"value\": {\n \"text\": \"active\"\n }\n }\n ],\n \"topics\": [\n \"billing\",\n \"renewals\"\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getmodus.com/api/v1/context/custom-items/batch")
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"] = 'application/json'
request.body = "{\n \"items\": [\n {\n \"kind\": \"entity\",\n \"sourceId\": \"billing-db\",\n \"sourceName\": \"Billing database\",\n \"collectionId\": \"contracts\",\n \"collectionName\": \"Contracts\",\n \"externalId\": \"contract-123\",\n \"name\": \"Acme renewal contract\",\n \"entityType\": \"contract\",\n \"description\": \"Enterprise renewal metadata from the internal billing system.\",\n \"attributes\": [\n {\n \"name\": \"status\",\n \"dataType\": \"string\",\n \"value\": {\n \"text\": \"active\"\n }\n }\n ],\n \"topics\": [\n \"billing\",\n \"renewals\"\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"contextItems": [
{
"contextItemId": "7a3f9d2c-1111-4000-a000-000000000abc",
"contextType": "custom_entity_metadata",
"dataPath": [
"billing-db",
"contracts",
"contract-123"
],
"title": "Acme renewal contract"
}
]
}{
"error": {
"code": "BAD_REQUEST",
"status": "INVALID_ARGUMENT",
"message": "Invalid value for query parameter `pageSize`.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "UNAUTHORIZED",
"status": "UNAUTHENTICATED",
"message": "Missing or invalid access token.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "FORBIDDEN",
"status": "PERMISSION_DENIED",
"message": "Missing required scope(s) for this operation.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS",
"info": {
"missing": [
"<required-scope>"
]
}
}
}{
"error": {
"code": "NOT_FOUND",
"status": "NOT_FOUND",
"message": "Resource not found.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "CONFLICT",
"status": "ALREADY_EXISTS",
"message": "A resource with that identifier already exists.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "VALIDATION",
"status": "INVALID_ARGUMENT",
"message": "Updates that would revoke your own access are not allowed.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}{
"error": {
"code": "INTERNAL_ERROR",
"status": "INTERNAL",
"message": "An unexpected error occurred.",
"requestId": "req_01HQ7K8ABCDEFGHIJKLMNOPQRS"
}
}Authorizations
A Modus personal access token (modus_<orgUuid>_<prefix>_<secret>) or an OAuth 2.1 access token, sent as Authorization: Bearer <token>.
Body
application/json
Custom context items to upsert. Batch imports are idempotent by item hierarchy.
Show child attributes
Show child attributes
Response
Custom context items created or updated by the batch.
Show child attributes
Show child attributes
⌘I