Hi, I have a question about the API. I found an in...
# permit-saas
m
Hi, I have a question about the API. I found an inconsistency. The Check endpoint takes into account all RBAC, ABAC, and ReBAC rules, which is fine, but when I want to use user permission, I only get results that are defined in ReBAC. The endpoint does not return resources that are allowed by the ABAC rule.
Copy code
###
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:
Copy code
###
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 latest
a
Hi @Michał Wójcik, I'm an AI assistant for Permit.io. I'll analyze available sources and get back to you shortly.
You're experiencing an inconsistency where the
/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.
To learn more, see the sources I considered: [[1] Permit.check()](https://docs.permit.io/how-to/enforce-permissions/check)
a
hey @Michał Wójcik, please follow the attached guide and add the "enable_abac_user_permissions" flag. https://docs.permit.io/how-to/enforce-permissions/user-permissions/#eap-enabling-abac-in-user-permissions
m
Thanks for quick answer Alon. Unfortunately after adding that the response is the same.
a
Can you paste here your new request?
@Ask Inkeep
a
Thanks for tagging me @Alon Boshi. I'll look through relevant sources and get back to you shortly.
For ABAC to work with the user-permissions endpoint, you need to include the
context
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:
Copy code
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:
Copy code
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?
To learn more, see the sources I considered: [[1] Get user permissions](https://docs.permit.io/how-to/enforce-permissions/user-permissions)
Thanks for the feedback, glad I was helpful.
m
Thanks for help, AI is correct :)
I have one more question. How to approach to implement pagination with permit? Is there any endpoint where I can pass user, resource type and page size, number ? What is the best efficient way? @Ask Inkeep
a
Thanks for tagging me @Michał Wójcik. I'll look through relevant sources and get back to you shortly.
For pagination with Permit.io, several SDK methods support page and perPage parameters. Here's how different SDKs implement pagination: ​*Go SDK:*​
Copy code
rolesAssignments, err := Permit.Api.Users.GetAssignedRoles(ctx, "role-key", "default",1,10)
(1)
Copy code
tenants, err := Permit.Api.Tenants.List(ctx, 1, 10)
(2) ​*Node.js SDK:*​
Copy code
await permit.api.tenants.list({
  search: "example",
  page: 1,
  perPage: 20,
}) ;
(3) ​*Java SDK:*​
Copy code
TenantRead[] tenants = permit.api.tenants.list() ;
(4)
Copy code
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 required
To learn more, see the sources I considered: [[1] GetAssignedRoles](https://docs.permit.io/sdk/golang/user/GetAssignedRoles) [[2] List](https://docs.permit.io/sdk/golang/tenant/List) [[3] list](https://docs.permit.io/sdk/nodejs/tenant/list-tenants) [[4] permit.api.tenants.list()](https://docs.permit.io/sdk/java/tenant/list) [[5] permit.api.roles.list()](https://docs.permit.io/sdk/java/role/list) [[6] permitio/permit-java/src/main/java/io/permit/sdk/api/RoleAssignmentsApi.java](https://github.com/permitio/permit-java/blob/master/src/main/java/io/permit/sdk/api/RoleAssignmentsApi.java)
m
I'm using .net sdk, but it is not important I can call to pdp or api directly. I just would like to call one endpoint which will return me ex. 50 resource instances where i have permission X.
a
@Ask Inkeep
a
Thanks for tagging me @Alon Boshi. I'll look through relevant sources and get back to you shortly.
For retrieving resource instances where you have a specific permission, you can use the
getUserPermissions
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) :
Copy code
const transactionInstances = await permit.getUserPermissions(key, [tenant], [], ["Transaction"]) ;
For direct PDP API calls, you can specify resource types to get filtered results (2) :
Copy code
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) :
Copy code
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 :
Copy code
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) .
m
Thanks it was useful. Just one question. Is there an option to have audit logs when I call user-permission endpoint? Is audit log only store for the check, bulk check endpoints? @Ask Inkeep
a
Thanks for tagging me @Michał Wójcik. I'll look through relevant sources and get back to you shortly.
Based on the documentation, audit logs are generated automatically for enforcement points and policy decisions (1) . The audit logs capture "basic logs reflecting actions in regards to your policy rules" and "decision logs" that explain why the policy engine made a decision . Audit logs track permission checks and include detailed decision evaluations (2) . The logs capture "decision evaluations, policy matches, and enforcement actions" . Every time a permission check takes place, the system logs "who initiated a particular action on a resource and whether it was approved or denied" along with a detailed decision log (1) . The audit logs are written to the PDP's stdout/stderr, allowing you to stream them directly into your logging platform . You can view them in the Permit dashboard's Audit Log page or access them "directly in your deployed PDP microservice" . While the documentation specifically mentions that audit logs capture permission checks and enforcement points , it doesn't explicitly state whether the user-permissions endpoint generates audit logs. The focus appears to be on authorization decisions (allow/deny) rather than permission listing operations. For your specific needs regarding the user-permissions endpoint and audit logging, I'd recommend checking your PDP logs directly to see if these queries are being logged, or reaching out to Permit.io support for clarification on whether permission listing operations generate audit entries.
To learn more, see the sources I considered: [[1] Audit Types & Filtering](https://docs.permit.io/how-to/use-audit-logs/types-and-filtering) [[2] Best Practices for Authorization Audit Logs](https://www.permit.io/blog/audit-logs)
a
Hey @Michał Wójcik, The audit logs appear to be specifically for authorization enforcement decisions (like check/bulk-check) , while API calls like user-permissions would be tracked in the API Log section instead . Have a look here
m
Unfortunately I can't see for user-permissions call any logs in API Logs, but something after request has been uploaded
Copy code
[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"}
a
can you share how you sent the request?
If you need the full log details, you can check STDERR and STDOUT, or use the Logs Forwarder to send the events to another destination.
✅ 1