
Which employee data fields should each customer receive? A framework for field scoping and data minimization
Summarise the blog with AI

Key takeaways
- Per-customer field selection gets decided at three layers: scope and token, access model, and query. Each answers a different question.
- Data minimization is the standard all three have to satisfy, and Article 25 requires it to be the system's starting configuration.
- Employee data risk tiers do not follow the obvious lines. Dependent SSNs, protected-class attributes, and inference-carrying fields like deduction history deserve more attention than the fields teams usually guard.
- A scope narrows the area and a permission narrows the fields inside it. Neither substitutes for the other.
- GraphQL field selection solves over-fetching in the response, and the fetch itself depends on the resolver behind it.
- Tenant isolation and field scoping are different problems. Isolation keeps customers apart. Scoping decides how much of a customer's own data their own integration receives.
Which employee data fields should each customer receive?
Ask a platform team why a customer's integration returns the fields it does, and the answer depends on who you ask. The security lead points at the token. Whoever owns the schema points at the response. Whoever wrote the permission model points at the roles. All three are describing something real. Each one describes about a third of it.
The failure shows up in three shapes. A token can be scoped correctly and still sit behind a permission model that hands over the whole record. A query can be filtered carefully and still sit behind a token that never should have reached the data. Each one looks like a different bug in the ticket queue. They are the same bug: nobody decided in advance which layer was supposed to answer this question.
The European Data Protection Board set the standard that answer has to satisfy in its Guidelines 4/2019 on Article 25, adopted in version 2.0 on 20 October 2020. Personal data processing must be adequate, relevant, and limited to what is necessary, and that limitation has to be the system's default configuration. A customer should never have to ask you to stop sending something. The guidelines say nothing about which layer enforces this, which is the engineering problem left over.
This guide covers the three layers where field decisions actually get made, which employee and benefits fields carry enough risk to be worth the effort, and a worked example against a real API. It is written for whoever owns the integration layer and has to decide, not just document, which fields each customer gets.
Why one question gets five answers
Field access sits at the intersection of five disciplines that rarely meet:
- Minimization belongs to legal.
- Token scoping belongs to security.
- Roles and permissions belong to whoever built the admin panel.
- Response shape belongs to the API team.
- Tenant isolation belongs to infrastructure.
Each group has a correct answer to a different question, and most teams have never written down which question belongs to whom.
Employee and benefits data makes this worse than it is elsewhere, because the objects are wide. A single employee record in a unified HRIS model carries name and work email alongside SSN, date of birth, home address, ethnicity, marital status, and termination reason. A dependent record carries a child's SSN and date of birth. These arrive in the same payload as the job title.
So a platform serving multiple customers has real variation to manage. One customer's contract covers eligibility and coverage tier. Another covers deduction and contribution history. A third only wants life-event triggers to fire a qualifying-event workflow. Handing all of them the same object means two of the three are receiving data their purpose never justified.
Those decisions resolve into three layers:
- The scope and token layer decides what a connection is authorized to reach at all.
- The access-model layer decides which fields inside that area a given customer or role is permitted to see.
- The query layer decides what one specific request returns.
Minimization sits above all three as the standard they collectively have to meet. It is the test. The three layers are where you pass or fail it.
Which employee fields actually carry risk
Before deciding where to enforce, decide what is worth enforcing on. Generic access-control writing treats every field as equivalent. Employee data is not, and the risk tiers do not follow the obvious lines.
The last row is the one teams miss, so it is worth spelling out. Deduction history reveals wage garnishments, union membership, and charitable giving. Coverage tier reveals family structure. Dependent relationship values like SPOUSE and DOMESTIC_PARTNER disclose marital and partnership status with no marital status field anywhere in the payload. Tobacco-use flags read as health attributes and work as insurance rating factors. A field can carry no sensitive label at all and still give away a protected characteristic by implication.
Where the fields are protected health information, HIPAA's minimum-necessary standard applies directly, limiting PHI disclosure to the minimum needed for the purpose (45 CFR 164.502(b) and 164.514(d)). Same principle as GDPR minimization, narrower scope, separate enforcement.
This taxonomy is what the three layers exist to route. Directory fields can sit at the scope layer and be done. Identity and dependent fields deserve an access-model decision per customer. Inference-carrying fields usually need a query-layer choice, because whether they are appropriate depends on what the request is for.
Scope, access model, and query: three different jobs
The first two layers get confused constantly, because in most stacks they sit inches apart.
A scope decides what a client's credential can reach at all: an area of data, a set of operations, granted once at connection time. A field-level permission operates inside that area and decides which values a given customer sees. NIST calls the shared principle least privilege in SP 800-53's AC-6 control: grant only the access needed for the assigned task. Scopes apply it at the request boundary. Permissions apply it inside the response.
Treating the scope as the finished job is how integrations end up over-privileged. A credential scoped to benefits data reaches the whole benefits object: dependents, deductions, coverage tiers, contribution history. If the customer's actual use case stops at eligibility status, everything after that first field moved for no reason. The scope narrows the area. Something else has to narrow the fields.
The query layer is where the response takes its final shape. GraphQL's selection set is the clearest version of this: a client names the fields it wants and gets exactly those, by specification. That solves over-fetching from the client's side. Whether the backend avoided reading the unrequested fields depends entirely on the resolver behind it. A resolver that pulls the full record from the source system and discards the unrequested keys has produced a correct response shape and moved every sensitive value anyway. It just discarded them afterward.
Put the three together and the distinction gets concrete:
- Scope decides the area.
- Permission decides the fields in that area for this customer.
- Query decides which of those fields this request returns.
Get one wrong and the other two will not cover for it.
RBAC, ABAC, and why isolation is a separate problem
The access-model layer is where most of the design work goes, and the choice between RBAC and ABAC is really a question about how field access varies across your customer base.
RBAC assigns permissions to roles and lets users inherit them. It works well when the fields a role can see are stable and few. A benefits-admin role sees eligibility and coverage tier. A payroll-integration role adds deduction and contribution fields. That mapping holds for years.
It breaks when access needs to vary by something a role cannot express:
- A specific plan type.
- A data-sharing agreement negotiated with one customer and not the rest.
- Whether the record belongs to an active or terminated employee.
Each distinction becomes a new role, and role count starts growing faster than the actual variation in access.
ABAC evaluates a policy against attributes of the request instead: who is asking, which customer they belong to, what the record itself contains, what the request is for. It suits the matrix that benefits data becomes as customers accumulate. The cost is real, since a policy engine is more machinery to build and reason about than a role table. You should pay that cost once role explosion is the alternative, and rarely before.
The tell is role count. When roles multiply to express distinctions that were never about role, ABAC is overdue.
Isolation is a separate problem sitting underneath all of this, and conflating the two is the most common error in this area. Tenant isolation keeps customer A's request from reaching customer B's records. Field scoping decides how much of customer A's own data customer A's integration receives. A platform can have airtight isolation and terrible field scoping at the same time: every customer walled off from every other, and every customer handed far more of their own data than their integration's purpose requires.
Where a unified API sits in this
This is where vendor content usually gets vague, so here is the division of labor stated plainly.
Bindbee reads and writes employee, payroll, and benefits data across 67+ connected systems and normalizes it into 40+ unified data models covering employees, employments, compensation, benefits, benefit coverages, dependents, dependent benefits, payroll runs, timesheets, and time off. What it gives you at the isolation and query layers is documented and specific. What it does not do is decide which fields your customer sees. That belongs to your product, and it is the reason this framework matters to you at all.
The mechanics, in more detail:
Isolation runs on connector tokens. Bindbee has two credentials and no OAuth scopes. An API key authenticates your organization as Authorization: Bearer. A connector token authenticates one end-customer connection as X-Connector-Token, and every request touching end-user data requires both. The connector token is issued per connector instance, which in practice means per employer. Using one against a different API category returns 403. Each token carries its own independent limit of 200 requests per minute, so one customer's backfill cannot starve another's. That is the isolation primitive the section above calls a precondition, and it is enforced on every request rather than configured once.
Sensitive payload extras are off by default. Raw upstream data and custom fields both require an explicit opt-in per request (include_raw_data=true, include_custom_fields=true). Omit them and you get neither. Default-off is exactly the posture Article 25 asks for, applied to the two widest parts of the payload.
Field selection exists on expanded relations. The expand parameter takes a bracketed field list, so expand=employee[first_name,last_name] returns a dependent's employee relation with two keys instead of the full employee object. It works on relations only, so the base model still comes back whole.
Custom Fields are additive, and scoped per connector. Custom Fields extend a unified model with extra attributes pulled from the raw upstream payload through a JMESPath expression. They only ever add to the payload, which makes them the wrong tool for minimization and a bad thing to sell as one. What they do give you is per-customer configuration: every mapping attaches either to an integration (organization scope) or to a single connector token (connector scope), and the connector-level mapping overrides the organization-level one. The configuration endpoint returns the effective mapping for a given connector and model, listing unmapped fields with a null path. That answers the question this article is built around, at least for the extended fields: which fields does this specific customer's connection actually return, and why. Validate the expression with the preview endpoint before saving, since an unresolvable path returns INVALID_JSON_PATH in place of the value instead of raising an error.
Bindbee holds SOC 2 Type II, HIPAA, GDPR, and ISO 27001, with details on the security page. A standard BAA template is available and negotiated on enterprise agreements. That covers the contractual half. The engineering half is the framework above, and it runs in your product. If you are still weighing whether a unified API belongs in your stack at all, the tradeoffs are worth reading first.
A worked example
Take one employer connection, X-Connector-Token: ct_acme_corp, and two workflows running against it.
Workflow one: census sync to a benefits carrier
GET /api/hris/v1/employees?employment_status=ACTIVE
Authorization: Bearer YOUR_BINDBEE_API_KEY
X-Connector-Token: ct_acme_corp
The unified response carries the full employee model, including ssn, date_of_birth, ethnicity, gender, marital_status, home_location, and termination_reason. The carrier needs six of those fields. Your serialization layer decides the rest never leave your service.
Released: first_name, last_name, date_of_birth, ssn, employment_status, start_date.
Withheld: ethnicity, gender, marital_status, personal_email, home_location, termination_reason.
The SSN and date of birth are identity-grade and go anyway, because the carrier cannot match a member without them. The EEO attributes have no place in an enrollment file.
Workflow two: payroll reconciliation, same customer, same token
GET /api/hris/v1/employee-payroll-runs
Authorization: Bearer YOUR_BINDBEE_API_KEY
X-Connector-Token: ct_acme_corp
Released: employee, deductions, contributions, pay_period_start, pay_period_end.
Withheld: ssn, because reconciliation matches on your internal employee ID.
Deduction detail is inference-carrying and goes only because this workflow is what deductions are for.
Same customer, same isolation boundary, same connector token, and two entirely different field sets. The difference got decided at the query layer, by you, per workflow. That is the case for keeping the three layers separate: no scope or role would have produced this split, because the variation is not about who is asking. It is about what they are asking for.
For dependents, the relation trim keeps the join without dragging the parent object along:
GET /api/hris/v1/dependents?expand=employee[first_name,last_name]
Authorization: Bearer YOUR_BINDBEE_API_KEY
X-Connector-Token: ct_acme_corp
Mapping a field requirement to its layer
Isolation sits underneath all three rows. It establishes that customer A cannot reach customer B's records at all, before any of the three layers gets to decide which of customer A's own fields come back.
In practice the decision runs top to bottom:
- Define the area a connection needs, before writing any field logic.
- Check how access varies inside that area, by role or by attribute. That is what settles RBAC against ABAC, not a general preference for either.
- Decide whether the response varies per request. This becomes true the moment one customer runs two workflows against the same data.
If you are running this exercise against a vendor rather than your own stack, the same three questions work as evaluation criteria for a third-party platform.
What Bindbee builds
We build and maintain the connections to 67+ HRIS, payroll, ATS, and benefits systems, and normalize what comes back into 40+ unified data models with the depth that makes field scoping worth doing. The scoping framework above runs in your product, where it belongs.
We build the integrations. You build the product.
See the connector token and authentication model in the docs
Frequently asked questions
What is the difference between a scope and a field-level permission?
A scope is granted to a credential and defines the area of data and set of operations that connection can reach. A field-level permission works inside that area and decides which specific values a given customer sees. A scope with no field-level permission behind it authorizes the entire object it names.
Which employee data fields are most sensitive?
SSN, date of birth, and home address are identity-grade for both employees and dependents. Ethnicity, gender, and marital status are protected-class attributes that exist for EEO reporting and rarely belong in an integration payload. Deduction history, coverage tier, and dependent relationship are inference-carrying: they disclose garnishments, union membership, family structure, and partnership status without naming any of it.
Does a unified API handle data minimization for me?
It handles part of it. A unified API can isolate one customer's data from another's, keep optional payload extras off by default, and give you per-connector configuration. Deciding which fields a specific customer's contract actually reaches is a product decision that lives in your application, because only you know what each customer signed.
When should I use ABAC instead of RBAC?
Use RBAC when field access maps to a small, stable set of roles. Use ABAC when access varies by attribute, plan type, data-sharing agreement, or request purpose, in ways that would force a new role for every combination. The tell is role count: once roles multiply to express distinctions that were never about role, ABAC is overdue.
Does GraphQL prevent over-fetching of sensitive data?
GraphQL's selection set guarantees the client receives only the fields it names, which solves over-fetching in the response. It says nothing about whether the backend read the unrequested fields to build that response. That depends on the resolver. Query-layer field selection reduces exposure without guaranteeing minimization.




