Exposure Profiles API
Manage data access profiles that control what native apps (L1) and third-party apps (L2) can access.
The Exposure Profiles API is used by users on app.ofself.ai (L0) to configure what data native and third-party apps can access. L1 and L2 apps cannot call these endpoints directly — they operate within the permissions granted by the user's exposure profile configuration.
Endpoints
POST /exposure-profiles
POST Create an exposure profile.
curl -X POST "https://api.ofself.ai/api/v1/exposure-profiles" \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Work Data Only",
"description": "Share work notes and documents",
"tag_filters": {
"include_all": ["urgent"],
"include_any": ["work", "personal"],
"exclude_any": ["archived", "private"]
},
"allowed_node_types": ["EXPERIENCE", "BELIEF"],
"excluded_node_types": ["ENTITY"],
"max_detail_level": "summary"
}'
Request Body:
| Field | Type | Description |
|---|---|---|
name | string | Required. Profile name (1-100 chars) |
description | string | Optional description |
tag_filters | object | Simple tag filtering (see below) |
tag_expression | object | Advanced boolean tag logic (see below) |
allowed_tag_ids | array | Legacy: Only nodes with these tags (OR logic) |
allowed_tags_logic | string | Legacy: OR (default) or AND |
excluded_tag_ids | array | Legacy: Exclude nodes with these tags |
allowed_node_ids | array | Specific node UUIDs to share |
allowed_node_types | array | Node types to allow |
excluded_node_types | array | Node types to exclude |
date_range_start | datetime | Only nodes after this date (ISO 8601) |
date_range_end | datetime | Only nodes before this date (ISO 8601) |
transformations | array | Data transformations (e.g., ["redact_pii"]) |
max_detail_level | string | full, summary, or minimal |
tag_permissions | object | Granular tag permissions (see below) |
schema_permissions | object | Granular schema permissions (see below) |
Tag Filters (Simple):
{
"tag_filters": {
"include_all": ["urgent"], // Must have ALL these tags
"include_any": ["work", "personal"], // Must have AT LEAST ONE
"exclude_any": ["archived", "deleted"] // Must NOT have ANY
}
}
Tag Expression (Advanced):
{
"tag_expression": {
"op": "AND",
"conditions": [
{"tag": "work"},
{"op": "OR", "conditions": [{"tag": "urgent"}, {"tag": "today"}]}
]
}
}
Granular Tag Permissions:
{
"tag_permissions": {
"discover": {"tag_ids": ["uuid"], "allow_all": false},
"read": {"tag_ids": ["uuid"], "allow_all": false},
"propose": {"tag_ids": ["uuid"], "allow_all": false, "allow_new": true},
"edit": {"tag_ids": ["uuid"], "allow_all": false},
"create": {"tag_ids": ["uuid"], "allow_all": false, "allow_new": true}
}
}
Granular Schema Permissions:
{
"schema_permissions": {
"read": {"schema_ids": ["schema-uuid", "__freeform__"], "allow_all": false},
"write": {"schema_ids": ["schema-uuid"], "allow_all": false}
}
}
Use "__freeform__" in schema_ids to include nodes without a schema (schema_id IS NULL).
GET /exposure-profiles
GET List exposure profiles.
curl -X GET "https://api.ofself.ai/api/v1/exposure-profiles?is_active=true" \
-H "Authorization: Bearer your-jwt-token"
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
is_active | boolean | Filter by active status |
limit | integer | Results per page (default: 20, max: 100) |
offset | integer | Pagination offset |
GET /exposure-profiles/:profile_id
GET Get an exposure profile.
curl -X GET "https://api.ofself.ai/api/v1/exposure-profiles/profile_abc?include_yaml=true" \
-H "Authorization: Bearer your-jwt-token"
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
include_yaml | boolean | Include YAML representation (default: true) |
resolve_tag_names | boolean | Replace UUIDs with tag names (default: true) |
PUT /exposure-profiles/:profile_id
PUT Update an exposure profile.
curl -X PUT "https://api.ofself.ai/api/v1/exposure-profiles/profile_abc" \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-d '{
"name": "Updated Work Profile",
"is_active": false
}'
All fields from POST are available for updates (all optional).
DELETE /exposure-profiles/:profile_id
DELETE Delete an exposure profile.
curl -X DELETE "https://api.ofself.ai/api/v1/exposure-profiles/profile_abc" \
-H "Authorization: Bearer your-jwt-token"
Note: Cannot delete if profile is in use by active third-party access or if it's the default profile.
GET /exposure-profiles/default
GET Get or create the default (transparent) profile.
curl -X GET "https://api.ofself.ai/api/v1/exposure-profiles/default" \
-H "Authorization: Bearer your-jwt-token"
GET /exposure-profiles/:profile_id/yaml
GET Get YAML representation of a profile.
curl -X GET "https://api.ofself.ai/api/v1/exposure-profiles/profile_abc/yaml" \
-H "Authorization: Bearer your-jwt-token"
POST /exposure-profiles/from-template
POST Create a profile from a template.
curl -X POST "https://api.ofself.ai/api/v1/exposure-profiles/from-template" \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-d '{
"template": "restrictive",
"name": "Limited Access Profile"
}'
Templates:
transparent: Full access (creates default profile)restrictive: Minimal access (locked down)