Metadata API
Inspect the schema of objects in your workspace. Use the Metadata API to discover what objects exist, what fields each one has, and how those fields are typed — before you write a line of integration code.
Base URL: https://api.experiture.ai/public/v1
Authentication: Bearer token with cdp:metadata:read. See Authentication.
Overview
| Operation | Endpoint | Returns |
|---|---|---|
| List objects | GET /metadata/objects | All objects in the workspace. |
| Get object schema | GET /metadata/objects/{object_name} | Full schema for a single object. |
Schemas are read-only from the public API. To add fields, use the Experiture console or the internal admin API.
List Objects
GET /metadata/objects
Authorization: Bearer <token>Response — 200 OK
{
"success": true,
"data": {
"items": [
{
"objectName": "profiles",
"displayName": "Customer Profiles",
"pluralDisplayName": "Customer Profiles",
"objectType": "profile",
"activeVersion": 3,
"primaryProfileRoot": true,
"ingestion": {
"single": true,
"jsonBatch": true,
"fileImport": true,
"defaultWriteMode": "upsert"
}
},
{
"objectName": "orders",
"displayName": "Orders",
"pluralDisplayName": "Orders",
"objectType": "event",
"activeVersion": 1,
"primaryProfileRoot": false,
"ingestion": {
"single": true,
"jsonBatch": true,
"fileImport": true,
"defaultWriteMode": "append"
}
}
]
},
"correlationId": "<uuid>"
}Get Object Schema
Full schema including every field, its type, nullability, and any enum constraints.
GET /metadata/objects/{object_name}
Authorization: Bearer <token>Example
curl https://api.experiture.ai/public/v1/metadata/objects/profiles \
-H "Authorization: Bearer <your_access_token>"Response — 200 OK
{
"success": true,
"data": {
"objectName": "profiles",
"displayName": "Customer Profiles",
"pluralDisplayName": "Customer Profiles",
"description": "Unified customer profile records.",
"objectType": "profile",
"activeVersion": 3,
"primaryProfileRoot": true,
"ingestion": {
"single": true,
"jsonBatch": true,
"fileImport": true,
"defaultWriteMode": "upsert",
"supportedWriteModes": ["append", "upsert"],
"eligibleMatchKeys": ["email", "phone", "customer_id"],
"defaultMatchKey": "email",
"profileAliasPath": "email"
},
"fields": [
{
"fieldName": "profile_id",
"displayName": "Profile ID",
"dataType": "string",
"nullable": false,
"isCustom": false,
"isSystem": true,
"isKey": true,
"isUnique": true,
"isIndexed": true
},
{
"fieldName": "email",
"displayName": "Email",
"dataType": "string",
"nullable": true,
"isCustom": false,
"isSystem": false,
"isKey": true,
"isUnique": true,
"isIndexed": true,
"piiClassification": "email"
},
{
"fieldName": "tier",
"displayName": "Loyalty Tier",
"dataType": "string",
"nullable": true,
"isCustom": true,
"isSystem": false,
"isKey": false,
"isUnique": false,
"isIndexed": false,
"constraints": { "enum": ["bronze", "silver", "gold", "platinum"] }
},
{
"fieldName": "last_order_at",
"displayName": "Last Order At",
"dataType": "timestamp",
"nullable": true,
"isCustom": true,
"isSystem": false,
"isKey": false,
"isUnique": false,
"isIndexed": false
}
]
},
"correlationId": "<uuid>"
}ingestion object fields
| Field | Type | Description |
|---|---|---|
single | boolean | Whether single-record writes (/records/{object}/append, /upsert) are supported. |
jsonBatch | boolean | Whether JSON batch writes (/records/{object}/append-batch, /upsert-batch) are supported. |
fileImport | boolean | Whether file-based import jobs (/import-jobs) are supported. |
defaultWriteMode | string | The write mode used when none is specified — typically "append" for event objects and "upsert" for profile objects. |
supportedWriteModes | string[] | All write modes this object accepts. Consult this before choosing a mode in your integration. |
eligibleMatchKeys | string[] | Fields that can be used as the matchKey for upsert operations. Only present on objects that support upsert. |
defaultMatchKey | string | null | The match key used when matchKey is omitted on an upsert. |
profileAliasPath | string | null | The field path used for profile alias resolution during identity stitching. Non-null only on primary profile root objects. Used internally by the CDP to link records across sources — useful context when designing your identity strategy. |
Field Types
The dataType field on each schema field uses the following values:
dataType | JSON representation | Notes |
|---|---|---|
string | string | — |
integer | integer | 64-bit signed. |
float | number | Double precision. |
boolean | true / false | — |
timestamp | ISO 8601 string | Timezone required on writes. |
date | YYYY-MM-DD | No timezone. |
json | object / array | Unstructured nested data. |
array<T> | array of T | T is any scalar type. |
Typical Usage
Before writing an integration, fetch the target object's schema so you know which fields are safe to send:
from experiture import Client # coming soon
client = Client(api_key="<your_access_token>")
schema = client.metadata.get_object("profiles")
key_fields = [f.field_name for f in schema.fields if f.is_key]
print("Identity / key fields:", key_fields)In CI / schema-drift detection: snapshot the schema hash and alert when it changes between deploys.
Errors
| HTTP Status | Code | Meaning |
|---|---|---|
401 | CDP_ETL.AUTH.UNAUTHORIZED | Missing or invalid bearer token. |
403 | CDP_ETL.AUTH.FORBIDDEN | Token lacks cdp:metadata:read. |
404 | CDP_ETL.OBJECT.NOT_FOUND | No object with that name in the workspace. |
Caching
Schemas change infrequently (only when an admin adds a field). Cache responses for 5–15 minutes in your application. updatedAt changes on every schema modification — use it as a cache-buster.
See Also
- Records API — write records that conform to these schemas
- Imports API — mapping step validates against schema