Skip to content

Add match-identifier endpoint#151

Open
ALIIQBAL786 wants to merge 12 commits intocamaraproject:mainfrom
ALIIQBAL786:endpoint-branch
Open

Add match-identifier endpoint#151
ALIIQBAL786 wants to merge 12 commits intocamaraproject:mainfrom
ALIIQBAL786:endpoint-branch

Conversation

@ALIIQBAL786
Copy link
Copy Markdown

What type of PR is this?

Add one of the following kinds:

  • enhancement/feature

What this PR does / why we need it:

Introduces a new POST /match-identifier endpoint to the Device Identifier API. This endpoint allows an API consumer to check whether a device identifier they provide (IMEI, IMEISV, or TAC) matches the one the network currently associates with a given mobile subscription, returning a simple boolean result (match: true/false) instead of exposing the actual device identifier.

This addresses data minimisation concerns — in use cases such as fraud prevention, device-based KYC, account takeover protection, and digital onboarding, partners only need a binary signal ("does this device match?") rather than the full IMEI/TAC/PPID. The new endpoint aligns with the match/verify patterns already established in other CAMARA APIs (e.g. SIM Swap, Device Status).

Which issue(s) this PR fixes:

Fixes #146

Special notes for reviewers:

The new endpoint reuses all existing shared components (Device, RequestBody, CommonResponseBody, DeviceResponse, error responses) — no duplication was introduced.
MatchRequestBody extends RequestBody via allOf, so the optional device object for 2-legged access tokens is inherited, not redefined.
The MatchResult schema only contains the match boolean; device and lastChecked come from CommonResponseBody, consistent with how DeviceIdentifier, DeviceType, and DevicePPID are composed in the other 200 responses.
No IMEI/TAC/PPID is exposed in the match response — only the boolean and optional metadata from CommonResponseBody.
The endpoint name /match-identifier is a working name and open to discussion.

Changelog input

 Added new POST /match-identifier endpoint to Device Identifier API, enabling boolean match verification of a provided device identifier (IMEI, IMEISV, or TAC) against the network's current association for a subscription, without exposing the actual device identifier in the response.

Additional documentation

The new /match-identifier endpoint is fully documented inline in the OpenAPI specification (device-identifier.yaml), including description, request/response schemas, examples for all supported identification methods (3-legged token, phone number, IP address, multiple identifiers), and integration with existing error handling. No separate documentation changes are required.

Copy link
Copy Markdown
Collaborator

@AxelNennker AxelNennker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow matching PPID


ProvidedIdentifierType:
type: string
enum:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enum:
enum:
- PPID

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API consumer would check that the PPID have associated with their end-user's account is the same as the last time.

Copy link
Copy Markdown

@albertoramosmonagas albertoramosmonagas Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @AxelNennker, I understand the use case you’re describing, but from my side, that use case is already covered by the existing retrieve-ppid endpoint: the client stores the PPID and simply compares the new value with the one they had before. We don’t really need a new /match-identifier call for that.

The whole point of /match-identifier was to offer a PPID-free, data-minimising binding check for cases where the partner has an IMEI/TAC and only wants a yes/no answer from the network. If we allow PPID as a providedIdentifierType, this endpoint stops being that alternative and essentially becomes “verify my persistent token”.

I’d strongly prefer to keep providedIdentifierType limited to IMEI / IMEISV / TAC and rely on retrieve-ppid for PPID-based checks.

Copy link
Copy Markdown
Collaborator

@AxelNennker AxelNennker Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should the whole-point be to provide a ppid free endpoint? PPID is the privacy respecting and data-minimizing alternative to the other identifier. "verify my token" is good.
Regarding access tokens, it is more secure to have a match-identifer access token on file compared to a retrieve-identifier access token. Storing IMEI/IMEISV makes then easier to steal and to use for tracking a sites that are not privacy respecting as sites that use PPID.

For example if the API consumer is selling phone insurance that is bound to the device identifier then they should use the PPID. We should reduce the use of IMEI etc to get to a more privacy friendly environment or charge 10 times for the IMEI compared to the PPID.

Globally unique, persistent identifiers esse delendam.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Axel, I really see your point: for use cases that need a long-lived device binding, PPID is clearly preferable to exposing raw IMEI/IMEISV. Your phone-insurance example fits exactly there, and from my side retrieve-ppid is the right tool in that scenario.

Where I think this endpoint is targeting a different class of use cases:

  • In many fraud / ATO / KYC flows, partners explicitly do not want to store any persistent token at all (neither IMEI nor PPID). They already have an IMEI/TAC in their flow and only want to ask the network:

    “For this subscription and this device identifier, do you currently see the same device, yes or no?”

  • In that context, a one-shot boolean is even more data-minimising than introducing a reusable PPID, even if PPID is better than IMEI when persistence is needed.

Also, the “verify my token” pattern for PPID is already possible today with retrieve-ppid + client-side comparison; the network doesn’t really add new semantics there.

That’s why, at least for this first version, I would keep /match-identifier scoped to IMEI/IMEISV/TAC only, and leave PPID verification to retrieve-ppid. That way we preserve a clear separation:

  • PPID = persistent pseudonymous binding when you actually need it
  • /match-identifier = PPID-free, point-in-time binding check for flows that only need a yes/no answer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That API consumer do not need a "match" feature because they can do the match by using "retrieve" is true for e.g. numberverification as well and there we have the "/verify" endpoint. So, that argument does not have merit in my opinion. Also, some legislations make "match" easy and "retrieve" illegal - at least without consent or opt-out. So, "match" for PPID might be the only legal and simple feature in those markets.

Furthermore, to the argument that some API consumers already have the IMEI and can do the match themselves. Sure, if they can handle the consent and/or opt-out legal requirements in their market that is good for them. But CAMARA have to think globally and there matching PPID might be the solution for some markets and legislations.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Axel — I think your latest point is fair in one respect: there may indeed be markets where a match-style operation is legally easier to expose than a retrieve-style operation, including for PPID.

That said, I still think adding PPID into ProvidedIdentifierType is the wrong move for this PR. The reason is not that “PPID match can never be useful”; the reason is that it is a different feature with a different semantic and privacy profile:

  • The current /match-identifier proposal is scoped as a subscription–device binding check using device identifiers (IMEI / IMEISV / TAC).
  • PPID is a persistent pseudonymous binding mechanism. Matching a PPID is no longer a hardware/device-identifier check; it becomes a verification of a long-lived partner-scoped token.

So from my perspective, this is mainly a scope and clarity issue:

  • This PR solves:

    “For this subscription and this device identifier, does the network currently see the same device?”

  • A potential PPID match feature would solve:

    “Is this still the same partner-scoped pseudonymous binding as before?”

Those are related, but not the same contract. I also think it is better for CAMARA design to keep those primitives clearly separated:

  • retrieve-ppid → persistent pseudonymous binding
  • /match-identifier → point-in-time boolean check on device identifiers
  • any future PPID match capability, if the WG sees clear legal/market demand, should be discussed explicitly as a separate enhancement rather than being folded into this enum expansion.

So my suggestion would be:

  • keep ProvidedIdentifierType limited to IMEI | IMEISV | TAC in this PR,
  • and, if there is real interest in PPID matching for certain legislations/markets, open a separate issue for that use case with its own rationale and scope.

That way we keep this PR tight, interoperable and easy to explain, while still leaving the door open for a PPID-specific evolution later if the WG wants it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR proposes security scope: device-identifier:match-identifier, so following the logic of current API definition another endpoint /match-ppid with device-identifier:match-ppid scope can be considered if needed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way we keep this PR tight, interoperable and easy to explain, while still leaving the door open for a PPID-specific evolution later if the WG wants it.

I think this PR is easier to explain if this PR handles all identifiers the same and not exclude one.

Copy link
Copy Markdown

@albertoramosmonagas albertoramosmonagas Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @AxelNennker, I understand the appeal of having a single match operation that handles every identifier in the same way. That said, from my perspective that would actually make this PR harder to explain, not easier, because the identifiers are not semantically equivalent:

  • IMEI / IMEISV / TAC are device identifiers
  • PPID is a persistent partner-scoped pseudonymous token

So adding PPID here would not be a small enum extension; it would materially change the contract of this endpoint. At this stage, the PR has already been reviewed and refined around a narrower and clearer scope:

  • /match-identifier = point-in-time boolean check of a device identifier against the device currently seen for the subscription
  • retrieve-ppid = persistent pseudonymous binding retrieval
  • a future match-ppid capability, if the WG sees value in it, can be discussed separately

From Telefónica’s side, this is the scope we support for the current PR. If PPID were added into ProvidedIdentifierType, we would see that as a different feature that should be handled through a separate issue / endpoint discussion rather than through this PR.

So my suggestion would be to close this thread on the basis of the current scoped proposal, and, if there is still interest in PPID matching, open a separate issue for that specific capability.

providedIdentifierType: "IMEI"
providedIdentifier: "4901542032375181"

MatchDeviceByPhoneNumber:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MatchDeviceByPhoneNumber:
MatchDeviceByPhoneNumberProvidePPID:
description: Matching device identifier by phone number and provided PPID
value:
device:
phoneNumber: "+123456789"
providedIdentifierType: "PPID"
providedIdentifier: "b083f65ccdad365d7489fff24b6d5074b30c12b6d81db3404d25964ffd908813"
MatchDeviceByPhoneNumber:

- lastChecked
- match
allOf:
- $ref: "#/components/schemas/CommonResponseBody"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR currently defines 200 as: match (bool) + lastChecked from CommonResponseBody.

However, it does not explicitly differentiate between:

  • false because the IMEI/TAC does not match,
  • false because no device info is available,
  • or cases where it should be 422 (not applicable) or 5xx (inconclusive/technical failure).

Do we want to reserve an optional field of type result (e.g., MATCH, MISMATCH, NO_DEVICE_INFO, INCONCLUSIVE) in CommonResponseBody or MatchResult, even though only MATCH/MISMATCH are currently used?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not, at the very least, it must be made clear in the description of /match-identifier that:

  • 404 = subscription not found
  • 422 = subscription found but service not applicable (due to policy/segment, etc.)
  • 200 + match=false = valid subscription and known device, but mismatch (not “no info”).

What do you think?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should go with the second option B:

I'd recommend not introducing a result enum (MATCH, MISMATCH, NO_DEVICE_INFO, INCONCLUSIVE) at this stage for the following reasons:

CAMARA design minimalism, speculative fields create contract obligations before those scenarios are well-defined.

Boolean is sufficient, the endpoint answers a binary question; edge cases like "no device info" are error conditions, not match results.

Consistency, other CAMARA match/verify APIs (e.g., Number Verification) use plain booleans
Non-breaking extensibility, an optional enum can always be added later without breaking existing consumers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ali, I'm fine with going with option B and keeping minimal for now. If we treat “no device info” / “not applicable” strictly as error conditions rather than match outcomes, then I think it becomes even more important to spell out the HTTP mapping explicitly in the spec. Something along these lines would already solve my concern:

  • 404 Not Found → subscription cannot be resolved from the device / token.
  • 422 Unprocessable Content → subscription is resolved, but the service cannot provide a result in a deterministic way (e.g. no device info available for this line, or local policy/regulation prevents returning the information) – i.e. business / applicability issues, not technical ones.
  • 200 with match = false → subscription resolved and device info available, comparison successfully performed, and the identifiers do not match (not “no info” / “not applicable”).

This keeps the response body minimal (just match + lastChecked), reserves false for a real mismatch, and aligns with your point that other match/verify APIs also rely on boolean + HTTP status to convey the outcome.

We can further reinforce this behaviour later on in the test suite, but having this mapping clearly stated in the description of /match-identifier would already give implementers a very concrete contract to follow.

description: Matching device identifier by phone number and provided IMEI
value:
device:
phoneNumber: "+123456789"
Copy link
Copy Markdown

@albertoramosmonagas albertoramosmonagas Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question: if we are using 3-legged, does it make sense to keep the phoneNumber here? I understand that this example would be for Multiple Identifiers? or just remove the phoneNumber?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an example request, and is only applicable if a 2-legged access token is being used (otherwise a 422 UNNECESSARY_IDENTIFIER would be returned).

So the example is valid for 2-legged access tokens, though I agree that might not be clear to all readers.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question was mainly about readability for the spec reader: the example itself is valid for a 2-legged access token, but that may not be obvious at first glance, especially since other examples in the same section cover different identification patterns. Would it make sense to make that explicit in the example description, e.g. something like:

“Matching device identifier by phone number and provided IMEI (2-legged token example)”

That way we keep the example as-is, but make the intended usage clearer to readers.

ALIIQBAL786 and others added 4 commits February 16, 2026 14:47
Co-authored-by: Alberto Ramos Monagas <alberto.ramosmonagas@telefonica.com>
Co-authored-by: Alberto Ramos Monagas <alberto.ramosmonagas@telefonica.com>
Copy link
Copy Markdown
Author

@ALIIQBAL786 ALIIQBAL786 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the descriptions of status codes

@albertoramosmonagas
Copy link
Copy Markdown

Hi @AxelNennker, after the last working group meeting, it was noted that the merge cannot proceed until the open discussion around your comments has been resolved. Do you have any further comments, or are you satisfied with the response that has been provided?

CC: @ALIIQBAL786

@ALIIQBAL786
Copy link
Copy Markdown
Author

Thanks everyone for the thoughtful discussion. I think the points raised highlight two slightly different objectives.

The goal of this PR is to introduce a minimal, point-in-time device binding check for cases where the API consumer already has a device identifier (IMEI / IMEISV / TAC) and only needs a boolean confirmation from the network, without exposing the actual identifier. This follows the data-minimisation approach used in other CAMARA match/verify style APIs.

Regarding PPID, I agree with the arguments about its privacy benefits and its role as a partner-scoped pseudonymous identifier. However, including PPID in ProvidedIdentifierType would effectively change the semantic scope of this endpoint. The current proposal verifies a subscription–device association, while PPID verification would instead become a validation of a persistent partner-scoped token, which is already achievable today through the retrieve-ppid endpoint combined with client-side comparison.

To keep this PR focused and the contract clear for implementers, I suggest we proceed with the current scope:

/match-identifier → device identifier verification (IMEI / IMEISV / TAC)

retrieve-ppid → persistent pseudonymous identifier retrieval

At the same time, the idea of PPID verification via a match-style operation is interesting and could address regulatory or market scenarios where retrieval is restricted. To avoid expanding the scope of this PR, it might be better to open a separate issue to discuss this as future work, potentially considering a dedicated capability (for example /match-ppid or a similar mechanism).

This would allow us to merge the current proposal while still keeping the door open for a PPID-specific enhancement if the working group sees value in it.

Happy to hear further thoughts from reviewers.

@albertoramosmonagas
Copy link
Copy Markdown

Thanks everyone for the thoughtful discussion. I think the points raised highlight two slightly different objectives.

The goal of this PR is to introduce a minimal, point-in-time device binding check for cases where the API consumer already has a device identifier (IMEI / IMEISV / TAC) and only needs a boolean confirmation from the network, without exposing the actual identifier. This follows the data-minimisation approach used in other CAMARA match/verify style APIs.

Regarding PPID, I agree with the arguments about its privacy benefits and its role as a partner-scoped pseudonymous identifier. However, including PPID in ProvidedIdentifierType would effectively change the semantic scope of this endpoint. The current proposal verifies a subscription–device association, while PPID verification would instead become a validation of a persistent partner-scoped token, which is already achievable today through the retrieve-ppid endpoint combined with client-side comparison.

To keep this PR focused and the contract clear for implementers, I suggest we proceed with the current scope:

/match-identifier → device identifier verification (IMEI / IMEISV / TAC)

retrieve-ppid → persistent pseudonymous identifier retrieval

At the same time, the idea of PPID verification via a match-style operation is interesting and could address regulatory or market scenarios where retrieval is restricted. To avoid expanding the scope of this PR, it might be better to open a separate issue to discuss this as future work, potentially considering a dedicated capability (for example /match-ppid or a similar mechanism).

This would allow us to merge the current proposal while still keeping the door open for a PPID-specific enhancement if the working group sees value in it.

Happy to hear further thoughts from reviewers.

Thanks @ALIIQBAL786, from my side this captures the distinction very well, and I support proceeding exactly on that basis. I think this is the right way to keep the current PR focused and easy to implement.

  • /match-identifier → point-in-time boolean verification of a device identifier (IMEI / IMEISV / TAC) against the subscription currently seen by the network

That keeps the contract clear for implementers and preserves the original intent of this proposal as a data-minimising subscription–device binding check. I also agree that a PPID match-style capability may be worth discussing separately if the WG sees regulatory or market demand for that pattern, but I would keep that as a separate issue / future enhancement, rather than expanding the scope of this PR.

So from Telefónica’s side, I’m happy to move forward with the current scope of the PR as proposed.

Comment on lines +499 to +502
- 404 → Subscription cannot be resolved from device/token
- 422 → Subscription resolved but no deterministic result available (policy/regulation/no device info)
- 5xx → Transient or technical failures (timeouts, upstream errors)
Note: match=false is ONLY returned when a definitive comparison has been performed.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

422 does not necessarily mean that the subscription has been resolved. See my comments below.

My preference would be to only comment on the meaning of a status code in the description of that specific status codes, and not in the descriptions of other status codes. Otherwise, we risk conflicting descriptions.

Suggested change
- 404 → Subscription cannot be resolved from device/token
- 422 → Subscription resolved but no deterministic result available (policy/regulation/no device info)
- 5xx → Transient or technical failures (timeouts, upstream errors)
Note: match=false is ONLY returned when a definitive comparison has been performed.

Copy link
Copy Markdown

@albertoramosmonagas albertoramosmonagas Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @eric-murray, I think that's a fair point. I agree that the 200MatchIdentifier description should only describe the meaning of the 200 response itself, and not restate the semantics of 404, 422 or 5xx, otherwise we risk duplication or conflicts with the specific status code definitions.

What I wanted to preserve is just the normative point that:

  • 200 + match = false is only returned when a definitive comparison has been performed and the identifiers do not match.

So I’m happy to simplify the 200 description accordingly, and move the broader status-code mapping either to the /match-identifier operation description and/or rely on the specific 404 / 422 / 5xx definitions plus the test cases to make the behaviour explicit.

200MatchIdentifier:
  description: |
    A match result has been successfully determined for the provided device identifier.
    - `match=true` means the provided identifier matches the network's current record.
    - `match=false` is only returned when a definitive comparison has been performed and the provided identifier does not match the network's current record.

WDYT?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HI @albertoramosmonagas -

I think you can align the two descriptions for simplicity:

200MatchIdentifier:
  description: |
    A match result has been successfully determined for the provided device identifier.
    - `match=true` means the provided identifier matches the network's current record.
    - `match=false` means the provided identifier does not match the network's current record.

422UnprocessableContent:
description: Unprocessable Content
description: |
Subscription found but the service cannot provide a deterministic match result.
Copy link
Copy Markdown
Collaborator

@eric-murray eric-murray Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of the four codes currently defined for the 422 status code, only SERVICE_NOT_APPLICABLE means that the device has been identified but processing cannot proceed. The example given in the introduction is that the phone number belongs to a landline, but it would also apply to other reasons, such as the local policy or regulatory reasons mentioned.

Also note that, if the reason is "temporary", then a 503 Service Unavailable status code should be used to indicate that the required result may be available later. However, we have not really discussed this, and there is a separate discussion in Commonalities on conveying "business outcomes" in a standardised way, so I would not explicitly add a 503 error to the OAS just yet.

For the remaining three code (UNSUPPORTED_IDENTIFIER, UNNECESSARY_IDENTIFIER and MISSING_IDENTIFIER), the device has not been definitively identified, either because the identifier provided is not supported, the identification is (potentially) ambiguous, or no identifier has been provided at all.

So this proposed update needs to be re-written.

Also, if you need to use the term "subscription", then be explicit and say "mobile device subscription". But better not to use the term at all in the error description if you can avoid it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @eric-murray agreed, this is too narrow for the full set of 422 causes. You’re right that only SERVICE_NOT_APPLICABLE implies that processing cannot proceed even though the service context is otherwise valid (e.g. local policy/regulatory reasons, line type, etc.). For UNSUPPORTED_IDENTIFIER, UNNECESSARY_IDENTIFIER, and MISSING_IDENTIFIER, we cannot assume that the device / line has been definitively identified.

I also agree that we should avoid saying “subscription found” in the generic 422 description. I’d suggest rewriting it more generically, for example:

422UnprocessableContent:
  description: |
    The request is valid, but it cannot be processed due to business, identification, or applicability conditions.

and then leave the more specific meaning to the individual cause values / examples.

Also agreed on not introducing an explicit 503 in this PR for temporary cases until that is better aligned in Commonalities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proposal: Add IMEI boolean match endpoint to Device Identifier API

6 participants