Skip to content

Conversation

@basbz
Copy link
Contributor

@basbz basbz commented Feb 9, 2026

Add external_id field to User and Organization structs and implement
new API endpoints to fetch entities by their external ID:

  • GET /user_management/users/external_id/:external_id
  • GET /organizations/external_id/:external_id

New functions:

  • WorkOS.UserManagement.get_user_by_external_id/1,2
  • WorkOS.Organizations.get_organization_by_external_id/1,2

This enables looking up users and organizations by their external
identifier, which is useful when integrating WorkOS with existing
user management systems.

@greptile-apps
Copy link

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR adds external_id to the WorkOS.UserManagement.User and WorkOS.Organizations.Organization structs and introduces convenience API wrappers to fetch a user/org by external ID (GET /user_management/users/external_id/:external_id and GET /organizations/external_id/:external_id). Tests and Tesla mocks were added to cover the new endpoints.

Main issue to address before merge: both structs use @enforce_keys, and the new external_id is optional but is not handled safely in cast/1, so responses that omit external_id will raise during struct construction.

Confidence Score: 3/5

  • This PR should not merge until the struct-casting runtime crash around optional external_id is fixed.
  • The API wrapper functions and tests look consistent, but both User and Organization structs can raise at runtime when API responses omit the new optional external_id key due to @enforce_keys behavior during cast/1 struct construction.
  • lib/workos/user_management/user.ex, lib/workos/organizations/organization.ex

Important Files Changed

Filename Overview
lib/workos/organizations.ex Adds get_organization_by_external_id/1,2 wrapper that calls GET /organizations/external_id/:external_id using path_params.
lib/workos/organizations/organization.ex Adds external_id field to Organization type/struct/cast; current @enforce_keys + cast will raise if API omits external_id.
lib/workos/user_management.ex Adds get_user_by_external_id/1,2 wrapper that calls GET /user_management/users/external_id/:external_id using path_params.
lib/workos/user_management/user.ex Adds external_id field to User type/struct/cast; current @enforce_keys + cast will raise if API omits external_id.
test/support/organizations_client_mock.ex Adds Tesla mock helper for get_organization_by_external_id endpoint including external_id in response body.
test/support/user_management_client_mock.ex Extends user mock with external_id and adds Tesla mock helper for get_user_by_external_id endpoint.
test/workos/organizations_test.exs Adds test coverage for get_organization_by_external_id/1 returning Organization.external_id.
test/workos/user_management_test.exs Adds test coverage for get_user_by_external_id/1 returning User.external_id.

Sequence Diagram

sequenceDiagram
  autonumber
  participant App as Client Code
  participant Orgs as WorkOS.Organizations
  participant UM as WorkOS.UserManagement
  participant HTTP as WorkOS.Client
  participant API as WorkOS API

  App->>Orgs: get_organization_by_external_id(external_id)
  Orgs->>HTTP: GET /organizations/external_id/:external_id
  HTTP->>API: HTTP request
  API-->>HTTP: 200 {.., external_id}
  HTTP-->>Orgs: {:ok, %Organization{external_id: ...}}
  Orgs-->>App: {:ok, organization}

  App->>UM: get_user_by_external_id(external_id)
  UM->>HTTP: GET /user_management/users/external_id/:external_id
  HTTP->>API: HTTP request
  API-->>HTTP: 200 {.., external_id}
  HTTP-->>UM: {:ok, %User{external_id: ...}}
  UM-->>App: {:ok, user}
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link

greptile-apps bot commented Feb 9, 2026

Additional Comments (2)

lib/workos/organizations/organization.ex
external_id breaks enforce_keys
external_id was added to the struct/type but not added to @enforce_keys, so cast/1 will raise at runtime when the API response doesn’t include external_id (which is valid since it’s typed as String.t() | nil). Either add :external_id to @enforce_keys and guarantee it is always present, or (more likely) remove @enforce_keys entirely / avoid using it for optional fields so %__MODULE__{external_id: nil} can be constructed safely.


lib/workos/user_management/user.ex
external_id breaks enforce_keys
Same issue as the Organization struct: external_id is optional (String.t() | nil) but cast/1 always constructs %__MODULE__{external_id: map["external_id"]}. If the API response omits this key, struct construction will raise because @enforce_keys doesn’t include :external_id (and enforce_keys require missing keys to be present even if nil). Adjust @enforce_keys/struct construction so missing external_id doesn’t crash.

@basbz
Copy link
Contributor Author

basbz commented Feb 9, 2026

Thanks for the review Greptile bot! I believe the current implementation is actually correct. The external_id field is intentionally not in @enforce_keys since it's optional. The cast/1 function explicitly sets external_id: map["external_id"], which will be nil when the key is absent from the API response. Since external_id isn't an enforced key, constructing the struct with external_id: nil works fine.
Happy to add a test case that explicitly verifies casting works when external_id is missing from the response if that would help demonstrate correctness.

@gjtorikian
Copy link
Contributor

Heya--would you mind merging in main (I just made a change to our release process) and fixing the lint issue?

basbz added 2 commits February 9, 2026 19:03
Add external_id field to User and Organization structs and implement
  new API endpoints to fetch entities by their external ID:

  - GET /user_management/users/external_id/:external_id
  - GET /organizations/external_id/:external_id

  New functions:
  - WorkOS.UserManagement.get_user_by_external_id/1,2
  - WorkOS.Organizations.get_organization_by_external_id/1,2

  This enables looking up users and organizations by their external
  identifier, which is useful when integrating WorkOS with existing
  user management systems.
@basbz basbz force-pushed the feature/add-external-id-support branch from 49f736a to 19b0009 Compare February 9, 2026 18:03
@basbz
Copy link
Contributor Author

basbz commented Feb 9, 2026

Heya--would you mind merging in main (I just made a change to our release process) and fixing the lint issue?

Sorry, didn't notice your message, went straight from my inbox to the failed action.
Should be up to date now.

@gjtorikian gjtorikian changed the title Add external_id support for User and Organization entities feat: Add external_id support for User and Organization entities Feb 9, 2026
@gjtorikian gjtorikian merged commit 0394535 into workos:main Feb 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants