Michał Wójcik
10/15/2025, 10:00 AM###
curl -X POST "<http://localhost:7766/allowed>" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer {{api_key}}" \
-d '{
"user": { "key": "grzegorz@sea.com" },
"action": "distribute",
"resource": {
"type": "market_order",
"key": "anton03",
"tenant": "default"
},
"context": {}
}'
response:
HTTP/1.1 200 OK
content-type: application/json
content-length: 823
connection: close
date: Wed, 15 Oct 2025 09:58:30 GMT
{
"allow": true,
"debug": {
"abac": {
"allow": true,
"allowing_rules": [
{
"resourceset": "resourceset_Large_5fquantity",
"userset": "userset_Seacom_5fUsers"
}
],
"code": "allow",
"reason": "user 'grzegorz@sea.com' matched 'userset_Seacom_5fUsers' userset conditions, the given resource matched the 'resourceset_Large_5fquantity' resourceset conditions, users matching 'userset_Seacom_5fUsers' userset conditions has the 'distribute' permission on resources of type 'market_order' matching 'resourceset_Large_5fquantity' resourceset conditions"
},
"request": {
"action": "distribute",
"resource": {
"attributes": {
"Quantity": 100000,
"type": "market_order"
},
"type": "market_order"
},
"tenant": "default",
"user": {
"attributes": {
"email": "grzegorz@sea.com",
"key": "grzegorz@sea.com",
"roles": [],
"tenants": []
},
"key": "grzegorz@sea.com",
"synced": true
}
}
},
"result": false
}
GetPermission:
###
curl --location '<http://localhost:7766/user-permissions>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{api_key}}' \
--data '{
"user": {
"key": "grzegorz@sea.com"
},
"tenants": [
"default"
]
}'
HTTP/1.1 200 OK
content-type: application/json
cache-control: private, max-age=3600
expires: Wed, 15 Oct 2025 10:58:53 +0000
content-length: 138
connection: close
date: Wed, 15 Oct 2025 09:58:53 GMT
{
"company:sea": {
"tenant": {
"key": "default"
},
"resource": {
"key": "sea",
"type": "company",
"attributes": {}
},
"permissions": [],
"roles": [
"member"
]
}
}
looking at the Check results based on the ABAC policy it should return me market_order:anton03
workspace: sea.live
project: dev
env: default
pdp version : the latestAsk Inkeep
10/15/2025, 10:00 AMAsk Inkeep
10/15/2025, 10:00 AM/allowed check endpoint correctly evaluates ABAC rules, but the /user-permissions endpoint only returns ReBAC-based permissions. This appears to be a limitation where the user-permissions endpoint focuses on relationship-based permissions rather than attribute-based rules.
The check endpoint evaluates RBAC, ABAC, and ReBAC policies as you've confirmed (1) , but the user-permissions endpoint seems to be designed primarily for returning role and relationship-based permissions rather than dynamically evaluated ABAC conditions.
To help our engineers investigate this further, could you please provide:
1. Which Workspace / Project / Env you are using
2. What SDK calls you're performing (if using SDKs) or the full CURL commands
3. Which PDP version you are running
4. Any relevant logs from your PDP
This will help determine if this is expected behavior or if there's an issue with how ABAC permissions are being returned by the user-permissions endpoint.Ask Inkeep
10/15/2025, 10:00 AMAlon Boshi
10/15/2025, 10:26 AMMichał Wójcik
10/15/2025, 10:51 AMAlon Boshi
10/15/2025, 11:29 AMAlon Boshi
10/15/2025, 11:36 AMAsk Inkeep
10/15/2025, 11:36 AMAsk Inkeep
10/15/2025, 11:36 AMcontext parameter with enable_abac_user_permissions set to true, and you must also specify resource_types (1) . The resource_types parameter is required when using ABAC with user permissions .
Here's the correct format based on the documentation:
curl --location '<http://localhost:7766/user-permissions>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <api key>' \
--data '{
"user": {
"key": "eddie"
},
"resource_types": [
"document",
"__tenant"
],
"context": {
"enable_abac_user_permissions": true
}
}'
For your specific case with market_order resources, try:
curl --location '<http://localhost:7766/user-permissions>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {{api_key}}' \
--data '{
"user": {
"key": "<mailto:grzegorz@sea.com|grzegorz@sea.com>"
},
"resource_types": [
"market_order",
"__tenant"
],
"context": {
"enable_abac_user_permissions": true
}
}'
The key points are:
• The resource_types array is always required for ABAC
• Include "__tenant" in the resource_types array to not ignore RBAC-based permissions
• The context object must contain "enable_abac_user_permissions": true
Note that not all SDKs support this feature yet, so you may need to call the PDP API directly as shown .
To help our engineers investigate further:
1. Which Workspace / Project / Env you are using (you mentioned sea.live/dev/default)
2. What calls are you performing (the CURL commands you've shared)
3. Which PDP version you are running (you mentioned "the latest" - could you provide the specific version?)
4. Could you share relevant logs from your PDP showing the ABAC evaluation?Ask Inkeep
10/15/2025, 11:37 AMAsk Inkeep
10/15/2025, 11:59 AMMichał Wójcik
10/15/2025, 12:16 PMMichał Wójcik
10/15/2025, 12:20 PMAsk Inkeep
10/15/2025, 12:20 PMAsk Inkeep
10/15/2025, 12:20 PMrolesAssignments, err := Permit.Api.Users.GetAssignedRoles(ctx, "role-key", "default",1,10)
(1)
tenants, err := Permit.Api.Tenants.List(ctx, 1, 10)
(2)
*Node.js SDK:*
await permit.api.tenants.list({
search: "example",
page: 1,
perPage: 20,
}) ;
(3)
*Java SDK:*
TenantRead[] tenants = permit.api.tenants.list() ;
(4)
RoleRead[] roles = permit.api.roles.list() ;
(5)
The Java SDK's RoleAssignmentsApi provides more detailed pagination options (6) :
• list(userKey, tenantKey, roleKey, resourceInstanceKey, page, perPage) - full control
• list(userKey, tenantKey, roleKey, resourceInstanceKey, page) - uses default 100 per page
• list(userKey, tenantKey, roleKey, resourceInstanceKey) - defaults to page 1
For filtering by user and resource type specifically, the Java RoleAssignmentsApi allows filtering with userKey, roleKey, tenantKey, and resourceInstanceKey parameters .
The most efficient approach depends on your SDK, but generally you'd:
1. Use the list methods with page/perPage parameters
2. Filter by user, role, or resource as needed
3. Iterate through pages as requiredAsk Inkeep
10/15/2025, 12:20 PMMichał Wójcik
10/15/2025, 12:29 PMAlon Boshi
10/15/2025, 12:32 PMAsk Inkeep
10/15/2025, 12:32 PMAsk Inkeep
10/15/2025, 12:33 PMgetUserPermissions function which filters based on resource types (1) (2) . Here's how to get paginated results:
The getUserPermissions function allows filtering by resource types (1) :
const transactionInstances = await permit.getUserPermissions(key, [tenant], [], ["Transaction"]) ;
For direct PDP API calls, you can specify resource types to get filtered results (2) :
curl <https://pdp-api.permit.io/user-permissions> \
--request POST \
--header "Authorization: Bearer YOUR_SECRET_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"user": {
"id": "<mailto:bob@example.com|bob@example.com>"
},
"tenants": ["tenant_123"],
"resources": ["blog_post:3"],
"resource_types": ["blog_post"],
"context": {}
}'
For pagination specifically, the Go SDK's resource instances API supports page and perPage parameters (3) (4) :
func (r *ResourceInstances) List(
ctx context.Context,
page int,
perPage int,
tenantFilter string,
resourceFilter string,
keyFilter string,
) (*[]models.ResourceInstanceRead, error)
(3)
The API endpoint accepts these query parameters (4) :
• page - Page number of the results to fetch, starting at 1
• per_page - The number of results per page (max 100)
• tenant - The tenant key or id to filter by
• resource - The resource key or id to filter by
For your .NET use case, you'd make a direct API call to list resource instances with pagination :
GET /v2/facts/{proj_id}/{env_id}/resource_instances?page=1&per_page=50&resource={resource_type}
However, this lists resource instances rather than filtering by permission. To get 50 resource instances where you have permission X, you'd need to combine getUserPermissions with the resource_types filter to get the instances you can access (1) (2) .Ask Inkeep
10/15/2025, 12:33 PMMichał Wójcik
10/16/2025, 8:52 AMAsk Inkeep
10/16/2025, 8:54 AMAsk Inkeep
10/16/2025, 8:54 AMAsk Inkeep
10/16/2025, 8:55 AMAlon Boshi
10/16/2025, 9:05 AMMichał Wójcik
10/16/2025, 9:22 AM[2025-10-16T09:10:08Z INFO pdp_server::opa_client::user_permissions] permit.user_permissions("<mailto:anton@clarksons.com|anton@clarksons.com>", tenants=None, resources=None, resource_types=Some(["market_order", "__tenant"])) -> 4 permissions
2025-10-16T09:10:08.986406+0000 | opal_client.engine.logger | INFO | Sent response. POST /v1/data/permit/user_permissions -> 200
2025-10-16T09:10:09.389681+0000 | opal_client.engine.logger | INFO | Logs uploaded successfully. {"plugin": "decision_logs", "time": "2025-10-16T09:10:09Z"}
2025-10-16T09:10:13.749746+0000 | uvicorn.protocols.http.httptools_impl | INFO | 127.0.0.1:41048 - "GET /healthy HTTP/1.1" 200
2025-10-16T09:10:17.193810+0000 | opal_client.engine.logger | INFO | Logs uploaded successfully. {"plugin": "decision_logs", "time": "2025-10-16T09:10:17Z"}Alon Boshi
10/16/2025, 9:55 AMAlon Boshi
10/16/2025, 2:11 PM