Skip to main content

Segments API

Create and manage dynamic user segments programmatically.

All endpoints on this page are relative to the base URL: https://api-eu1.joryio.com - see API Overview.

Authentication

All requests require API key authentication:

Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

Create Segment

Create a new user segment with filters.

Endpoint

POST /segments

Request Body

FieldTypeRequiredDescription
namestringYesSegment name (max 255 chars)
descriptionstringNoSegment description (max 1000 chars)
filterGroupsarrayYesArray of filter groups (max 20)
excludeFilterGroupsarrayNoUsers matching any of these groups are removed (max 20)
groupOperatorstringYesHow to combine groups: AND or OR
tagsarrayNoTag names for organizing segments

Filter Structure

Each filter group contains up to 50 filters:

{
filters: [
{
type: 'attribute' | 'default_attribute' | 'event' | 'ecommerce'
| 'behavioral' | 'segment' | 'canvas_execution'
| 'list_membership' | 'channel_subscription' | 'app'
| 'entity' | 'bounce_status' | 'wallet_pass',
field?: string, // For attribute filters
operator: string, // See Filter Operators below
value?: any, // Comparison value (also carries N for count operators)
eventName?: string, // For event filters
withinDays?: number, // Time window for event filters
startDate?: string, // Absolute window start (ISO 8601, event filters)
endDate?: string, // Absolute window end (ISO 8601, event filters)
segmentId?: string, // For segment filters
listId?: string, // For list_membership filters
channel?: string // For channel_subscription filters
}
],
operator: 'AND' | 'OR'
}

Example Request - Simple Attribute Filter

curl -X POST https://api-eu1.joryio.com/segments \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Users",
"description": "Users on premium plan",
"filterGroups": [
{
"filters": [
{
"type": "attribute",
"field": "plan",
"operator": "equals",
"value": "premium"
}
],
"operator": "AND"
}
],
"groupOperator": "AND"
}'

Example Request - Behavioral Segment

curl -X POST https://api-eu1.joryio.com/segments \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Active Trial Users",
"description": "Trial users active in last 7 days",
"filterGroups": [
{
"filters": [
{
"type": "attribute",
"field": "plan",
"operator": "equals",
"value": "trial"
},
{
"type": "event",
"eventName": "Session Started",
"operator": "performed",
"withinDays": 7
}
],
"operator": "AND"
}
],
"groupOperator": "AND"
}'

Example Request - Complex Segment

curl -X POST https://api-eu1.joryio.com/segments \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "High-Value At-Risk Users",
"description": "Paid users with high LTV who haven'\''t logged in recently",
"filterGroups": [
{
"filters": [
{
"type": "attribute",
"field": "plan",
"operator": "in",
"value": ["premium", "enterprise"]
},
{
"type": "attribute",
"field": "lifetimeValue",
"operator": "gte",
"value": 500
}
],
"operator": "AND"
},
{
"filters": [
{
"type": "event",
"eventName": "Login",
"operator": "not_performed",
"withinDays": 14
}
],
"operator": "AND"
}
],
"groupOperator": "AND"
}'

Response

The segment object is returned directly (no wrapper envelope). Segment IDs are UUIDs. Member counts are not stored on the segment - use GET /segments/:id/size:

{
"id": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d",
"name": "Premium Users",
"description": "Users on premium plan",
"filterGroups": [
{
"filters": [
{
"type": "attribute",
"field": "plan",
"operator": "equals",
"value": "premium"
}
],
"operator": "AND"
}
],
"excludeFilterGroups": [],
"groupOperator": "AND",
"tags": [],
"status": "active",
"createdAt": "2024-01-20T10:30:00.000Z",
"updatedAt": "2024-01-20T10:30:00.000Z"
}

Get Segment

Retrieve segment details.

Endpoint

GET /segments/:id

Path Parameters

ParameterTypeDescription
idstringSegment ID

Example Request

curl -X GET https://api-eu1.joryio.com/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d \
-H "Authorization: Bearer jry_live_your_api_key"

Response

The segment object, returned directly (for the current member count, call GET /segments/:id/size):

{
"id": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d",
"name": "Premium Users",
"description": "Users on premium plan",
"filterGroups": [...],
"excludeFilterGroups": [],
"groupOperator": "AND",
"tags": [],
"status": "active",
"createdAt": "2024-01-20T10:30:00.000Z",
"updatedAt": "2024-01-20T10:30:00.000Z"
}

List Segments

Get all segments with pagination.

Endpoint

GET /segments

Query Parameters

ParameterTypeDefaultDescription
limitnumber100Results per page (max 100)
offsetnumber0Number of segments to skip
qstring-Free-text search on segment name
statusstring-Filter by status: active or archived
tagsstring-Comma-separated tag names
createdBystring-Comma-separated creator user IDs
editedBystring-Comma-separated last-editor user IDs

Example Request

curl -X GET "https://api-eu1.joryio.com/segments?limit=50&status=active" \
-H "Authorization: Bearer jry_live_your_api_key"

Response

{
"data": [
{
"id": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d",
"name": "Premium Users",
"status": "active",
"createdAt": "2024-01-20T10:30:00.000Z"
},
{
"id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"name": "Trial Users",
"status": "active",
"createdAt": "2024-01-19T09:15:00.000Z"
}
],
"pagination": {
"total": 23,
"page": 1,
"limit": 50,
"offset": 0,
"totalPages": 1,
"hasMore": false
}
}

Update Segment

Update segment name, description, or filters. Uses PUT (there is no PATCH route); fields you omit are left unchanged.

Endpoint

PUT /segments/:id

Request Body

{
"name": "Updated Name",
"description": "Updated description",
"filterGroups": [...]
}

Example Request

curl -X PUT https://api-eu1.joryio.com/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"description": "Premium users who have made at least one purchase"
}'

Response

The updated segment object, returned directly:

{
"id": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d",
"name": "Premium Users",
"description": "Premium users who have made at least one purchase",
"status": "active",
"updatedAt": "2024-01-21T14:30:00.000Z"
}

Archive Segment

Segments cannot be hard-deleted - campaigns and journeys hold segment references, so removal is archive-only. Archived segments stop appearing in active lists and can be restored at any time.

Endpoints

POST /segments/:id/archive
POST /segments/:id/unarchive

Example Request

curl -X POST https://api-eu1.joryio.com/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d/archive \
-H "Authorization: Bearer jry_live_your_api_key"

Response

The segment object with its new status:

{
"id": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d",
"name": "Premium Users",
"status": "archived",
"updatedAt": "2024-01-21T14:30:00.000Z"
}

Notes

  • Archiving a segment doesn't delete the users in it
  • Active campaigns using this segment will be affected
  • Use POST /segments/:id/unarchive to restore

Get Segment Users

Get list of users in a segment.

Endpoint

GET /segments/:id/users

Query Parameters

ParameterTypeDefaultDescription
limitnumber100Number of users to return
offsetnumber0Number of users to skip

Example Request

curl -X GET "https://api-eu1.joryio.com/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d/users?limit=100" \
-H "Authorization: Bearer jry_live_your_api_key"

Response

A bare JSON array of user documents (no pagination envelope - page with limit / offset):

[
{
"_id": "665f1e2a9b3c4d5e6f7a8b9c",
"externalId": "user_123",
"email": "user1@example.com",
"attributes": {
"plan": "premium",
"signupDate": "2024-01-15"
}
},
{
"_id": "665f1e2a9b3c4d5e6f7a8b9d",
"externalId": "user_456",
"email": "user2@example.com",
"attributes": {
"plan": "premium",
"signupDate": "2024-01-18"
}
}
]

Get Segment Size

Get the current number of users in a segment. By default this is a fast approximate estimate; pass ?exact=true for a precise count. The size number is the only thing that is ever approximate - actual membership and sends are always exact.

Endpoint

GET /segments/:id/size

Query Parameters

ParameterTypeDefaultDescription
exactbooleanfalsetrue returns the precise count (slower on large workspaces)

Example Request

curl -X GET https://api-eu1.joryio.com/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d/size \
-H "Authorization: Bearer jry_live_your_api_key"

Response

{
"segmentId": "3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d",
"size": 1234,
"approximate": true
}

Filter Operators

Attribute Operators

OperatorDescriptionExample
equalsExact matchplan equals "premium"
not_equalsNot equalplan not_equals "free"
inValue in listplan in ["premium", "enterprise"]
not_inValue not in listplan not_in ["free", "trial"]
containsString containsemail contains "@company.com"
not_containsString doesn't containemail not_contains "@competitor.com"
gtGreater thanlifetimeValue > 1000
gteGreater than or equalage >= 18
ltLess thanloginCount < 5
lteLess than or equalmrr <= 99
existsField existsphone exists
not_existsField doesn't existreferralCode not_exists
within_next_daysDate within next N daystrialEndsDate within_next_days 7

Event Operators

OperatorDescriptionExample
performedUser performed eventPerformed "Order Completed"
not_performedUser didn't perform eventNot performed "Onboarding Completed"
performed_count_gteEvent count greater than or equal (N in value)Performed "Login" >= 10 times
performed_count_lteEvent count less than or equal (N in value)Performed "Login" <= 5 times
performed_in_last_daysPerformed within the last N days (N in value)Performed "Login" in last 7 days
not_performed_in_last_daysNot performed within the last N days (N in value)No "Login" in last 14 days

Filter Examples

Attribute Filters

// String matching
{
"type": "attribute",
"field": "email",
"operator": "contains",
"value": "@company.com"
}

// Numeric comparison
{
"type": "attribute",
"field": "lifetimeValue",
"operator": "gte",
"value": 500
}

// Multiple values
{
"type": "attribute",
"field": "plan",
"operator": "in",
"value": ["premium", "enterprise"]
}

// Field exists
{
"type": "attribute",
"field": "phone",
"operator": "exists"
}

// Date within next N days (future dates)
{
"type": "attribute",
"field": "trialEndsDate",
"operator": "within_next_days",
"value": 7
}

Event Filters

// Event performed within timeframe
{
"type": "event",
"eventName": "Order Completed",
"operator": "performed",
"withinDays": 30
}

// Event not performed
{
"type": "event",
"eventName": "Onboarding Completed",
"operator": "not_performed"
}

// Event count (N goes in `value`)
{
"type": "event",
"eventName": "Login",
"operator": "performed_count_gte",
"value": 10,
"withinDays": 30
}

Segment Filters

// User in another segment
{
"type": "segment",
"segmentId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"operator": "in_segment"
}

// User not in another segment
{
"type": "segment",
"segmentId": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
"operator": "not_in_segment"
}

Common Segment Examples

Trial Conversion Opportunity

{
"name": "Trial Expiring Soon",
"description": "Users whose trial ends in the next 3 days and haven't purchased",
"filterGroups": [
{
"filters": [
{
"type": "attribute",
"field": "plan",
"operator": "equals",
"value": "trial"
},
{
"type": "attribute",
"field": "trialEndsDate",
"operator": "within_next_days",
"value": 3
},
{
"type": "event",
"eventName": "Order Completed",
"operator": "not_performed"
}
],
"operator": "AND"
}
],
"groupOperator": "AND"
}

Power Users

{
"name": "Power Users",
"filterGroups": [
{
"filters": [
{
"type": "event",
"eventName": "Login",
"operator": "performed_count_gte",
"value": 20,
"withinDays": 30
},
{
"type": "event",
"eventName": "Feature Used",
"operator": "performed_count_gte",
"value": 50,
"withinDays": 30
}
],
"operator": "AND"
}
],
"groupOperator": "AND"
}

At-Risk Customers

{
"name": "At-Risk Premium Users",
"filterGroups": [
{
"filters": [
{
"type": "attribute",
"field": "plan",
"operator": "in",
"value": ["premium", "enterprise"]
},
{
"type": "attribute",
"field": "lifetimeValue",
"operator": "gte",
"value": 500
}
],
"operator": "AND"
},
{
"filters": [
{
"type": "event",
"eventName": "Login",
"operator": "not_performed",
"withinDays": 14
}
],
"operator": "AND"
}
],
"groupOperator": "AND"
}

Dynamic Updates

Segments are dynamic: membership is not a stored list - the segment's filters are evaluated against current profile and event data whenever the segment is used (campaign targeting, journey gates, membership checks). There is nothing to refresh or recompute via the API.

Checking Segment Size

# Get current size (approximate by default; add ?exact=true for a precise count)
curl -X GET https://api-eu1.joryio.com/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d/size \
-H "Authorization: Bearer jry_live_your_api_key"

Error Responses

All errors use the standard error body - see API Overview: Error Response.

400 Bad Request - Invalid Filter

{
"statusCode": 400,
"message": "Bad Request Exception",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/segments",
"errors": [
"filterGroups.0.filters.0.operator must be one of the following values: equals, not_equals, contains, ..."
]
}

404 Not Found

{
"statusCode": 404,
"message": "Segment with ID 3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d not found",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/segments/3f9d2c1e-7a54-4b2e-9c1d-8e6f5a4b3c2d"
}

Rate Limits

The Segments API has no fixed per-endpoint rate limits today - see API Overview: Rate Limiting.


Best Practices

1. Keep Segments Focused

Good: Specific, targeted segments

{
"name": "Premium US Users - Active Last 7 Days",
"filters": [...]
}

Bad: Overly broad segments

{
"name": "All Users",
"filters": []
}

2. Use Descriptive Names

Good: Self-explanatory names

  • "Trial Users - Expiring This Week"
  • "High-Value At-Risk Customers"
  • "New Signups - Not Onboarded"

Bad: Unclear names

  • "Segment 1"
  • "Test"
  • "Users ABC"

3. Combine Filters Logically

Use AND for narrowing, OR for broadening:

// AND: Premium users who are active
{
"filters": [
{ "field": "plan", "operator": "equals", "value": "premium" },
{ "eventName": "Login", "operator": "performed", "withinDays": 7 }
],
"operator": "AND"
}

// OR: Users on any paid plan
{
"filters": [
{ "field": "plan", "operator": "equals", "value": "premium" },
{ "field": "plan", "operator": "equals", "value": "enterprise" }
],
"operator": "OR"
}

4. Monitor Segment Size

Track segment size over time:

// Poll segment size
setInterval(async () => {
const { size, approximate } = await fetch(`/segments/${segmentId}/size`).then(r => r.json());
console.log(`Segment size: ${approximate ? '≈' : ''}${size}`);
}, 60000); // Every minute

Next Steps