Skip to content

Conversation

@Fodoj
Copy link
Contributor

@Fodoj Fodoj commented Dec 2, 2025

It seems OpenAI broke at least 2 administrative APIs recently. This changes are not documented on https://platform.openai.com/docs/api-reference/, but endpoints return data in a different format.

Summary by CodeRabbit

  • Documentation
    • Updated provider docs to reflect schema changes: renamed added_atcreated, nametitle, and created_atcreated.
    • Added new read-only project fields: archived_at and is_initial.
    • Removed project description and the usage_limits nested schema.
    • Examples updated to use title/created consistently.

✏️ Tip: You can customize this high-level summary in your review settings.

@Fodoj Fodoj self-assigned this Dec 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

Walkthrough

This PR renames organization user timestamps from added_at to created, restructures project fields (rename nametitle, created_atcreated, remove usage_limits, add archived_at and is_initial), and introduces new user/org user types and a ToUser() conversion in the Go client.

Changes

Cohort / File(s) Summary
Organization User — docs & provider
docs/data-sources/organization_user.md, docs/resources/organization_user.md, internal/provider/data_source_openai_organization_user.go, internal/provider/resource_openai_organization_user.go
Rename read-only field added_atcreated (int). Update schema declarations, d.Set mappings, and read logic to use user.Created.
Organization Users (list) — docs & provider
docs/data-sources/organization_users.md, internal/provider/data_source_openai_organization_users.go
Rename nested user field added_atcreated. Read mapping now sources Created and converts API items via ToUser() when flattening for Terraform schema.
Project data sources — docs & provider
docs/data-sources/project.md, docs/data-sources/projects.md, internal/provider/data_source_openai_project.go, internal/provider/data_source_openai_projects.go
Rename nametitle, created_atcreated (int/int64); add archived_at (nullable int) and is_initial (bool); remove usage_limits. Update ProjectResponse struct, schema blocks, and read mappings accordingly.
Project resource — docs, examples & provider
docs/resources/project.md, examples/data-sources/openai_project/data-source.tf, examples/resources/openai_project/resource.tf, internal/provider/resource_openai_project.go
Replace required name and optional description with title; remove description usage; change created_atcreated (Number), archived_at type to Number, add is_initial (Computed bool). Update examples and CRUD flows to use title.
Go client types & APIs
internal/client/client.go
Restructure Project (add Title, Created, ArchivedAt, IsInitial; remove legacy fields), simplify project create/update signatures to accept title only, introduce UserInfo, OrganizationUser, User types and OrganizationUser.ToUser() conversion, update responses and user-related methods to use new types.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~45 minutes

  • internal/client/client.go: verify ToUser() mapping, JSON tags, and changed method signatures are consistent.
  • internal/provider/data_source_openai_project.go and internal/provider/data_source_openai_projects.go: validate ProjectResponse changes and removal of UsageLimits.
  • internal/provider/resource_openai_project.go: ensure CRUD and import flows align with new title/timestamp types and no leftover description handling.

Poem

🐰 I hopped through fields and gave them light,
added_at to created, name to title bright.
Projects trimmed their limits, time kept as a number,
Users find their form, conversions without blunder.
A cheerful hop — the provider springs to flight!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete and lacks critical details required by the template, such as issue reference, type of change checkbox, testing information, and a comprehensive summary of changes. Complete the description by filling in the issue reference, selecting the breaking change checkbox, detailing testing methodology, and providing a comprehensive summary of the API field renamings and type changes.
Title check ❓ Inconclusive The title 'Fix breaking APIs' is vague and generic, lacking specific details about which APIs are fixed or what the actual changes entail. Use a more descriptive title that specifies the primary API changes, such as 'Update project and organization user API field mappings' or 'Rename and restructure project/user API fields'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-breaking

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
internal/provider/data_source_openai_project.go (1)

101-104: Use log.Printf instead of fmt.Printf for consistency.

These debug statements use fmt.Printf which writes to stdout, while the rest of the codebase (including this file's other logging at line 100+) uses log.Printf. This inconsistency can cause issues with log aggregation and filtering.

-	fmt.Printf("Getting project with ID: %s\n", projectID)
-	fmt.Printf("Using URL: %s\n", strings.Replace(url, client.APIURL, "", 1))
-	fmt.Printf("OpenAI client config: API URL=%s, Organization ID=%s\n", client.APIURL, client.OrganizationID)
-	fmt.Printf("Making API request: GET %s\n", url)
+	log.Printf("[DEBUG] Getting project with ID: %s", projectID)
+	log.Printf("[DEBUG] Using URL: %s", strings.Replace(url, client.APIURL, "", 1))
+	log.Printf("[DEBUG] OpenAI client config: API URL=%s, Organization ID=%s", client.APIURL, client.OrganizationID)
+	log.Printf("[DEBUG] Making API request: GET %s", url)

You'll also need to add "log" to the imports.

internal/provider/resource_openai_project.go (1)

17-21: Panic recovery may hide bugs silently.

This defer/recover pattern silently logs panics as warnings and continues execution. While this prevents crashes, it can mask serious bugs and leave resources in inconsistent states. Consider whether this is truly necessary or if panics should propagate.

If panic recovery is genuinely needed, consider at least returning an error to the caller:

 func resourceOpenAIProject() *schema.Resource {
-	defer func() {
-		if r := recover(); r != nil {
-			log.Printf("[WARN] Recovered from panic in resourceOpenAIProject: %v", r)
-		}
-	}()
+	// Note: Removed panic recovery - panics should propagate to reveal bugs
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f74ae45 and 044359b.

📒 Files selected for processing (13)
  • docs/data-sources/organization_user.md (1 hunks)
  • docs/data-sources/organization_users.md (1 hunks)
  • docs/data-sources/project.md (3 hunks)
  • docs/data-sources/projects.md (2 hunks)
  • docs/resources/organization_user.md (1 hunks)
  • docs/resources/project.md (3 hunks)
  • internal/client/client.go (8 hunks)
  • internal/provider/data_source_openai_organization_user.go (2 hunks)
  • internal/provider/data_source_openai_organization_users.go (3 hunks)
  • internal/provider/data_source_openai_project.go (3 hunks)
  • internal/provider/data_source_openai_projects.go (2 hunks)
  • internal/provider/resource_openai_organization_user.go (4 hunks)
  • internal/provider/resource_openai_project.go (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
internal/provider/data_source_openai_organization_user.go (1)
internal/provider/data_source_openai_project_user.go (2)
  • dataSourceOpenAIProjectUserRead (139-218)
  • dataSourceOpenAIProjectUser (16-49)
internal/provider/data_source_openai_organization_users.go (1)
internal/provider/data_source_openai_project_users.go (1)
  • dataSourceOpenAIProjectUsers (14-83)
internal/client/client.go (3)
internal/provider/provider.go (1)
  • OpenAIClient (27-31)
internal/provider/resource_openai_fine_tuning_job.go (1)
  • Project (47-51)
internal/provider/resource_openai_project_user.go (3)
  • resourceOpenAIProjectUser (18-58)
  • resourceOpenAIProjectUserUpdate (259-348)
  • interface{} (395-395)
internal/provider/resource_openai_project.go (3)
internal/provider/resource_openai_upload.go (1)
  • resourceOpenAIUpload (43-103)
internal/provider/resource_openai_project_user.go (3)
  • resourceOpenAIProjectUser (18-58)
  • resourceOpenAIProjectUserUpdate (259-348)
  • resourceOpenAIProjectUserImport (395-435)
internal/provider/resource_openai_invite.go (1)
  • resourceOpenAIInvite (13-79)
🪛 GitHub Actions: CI
docs/resources/project.md

[error] 1-1: Process completed with exit code 1. CI step failed after diffs in docs/resources/project.md.

🔇 Additional comments (32)
internal/provider/data_source_openai_projects.go (4)

48-52: Breaking change: field renamed from name to title.

This reflects the OpenAI API change where projects now use title instead of name. Users will need to update their Terraform configurations to reference title instead of name when this change is deployed.


58-62: LGTM: field renamed from created_at to created.

This change aligns with the new OpenAI API response format.


63-72: LGTM: new fields added.

The archived_at and is_initial fields are new additions that enhance project management capabilities. These are additive (non-breaking) changes.


207-216: LGTM: mappings updated correctly.

The field mappings now use project.Title, project.Created, project.IsInitial, and conditionally set archived_at when non-nil. The nil check for ArchivedAt is appropriate since it's an optional pointer field.

internal/client/client.go (6)

143-151: Major Project struct restructuring to match new API format.

The Project struct has been significantly simplified to match the new OpenAI API response. Removed fields include Name, Description, CreatedAt, and several nested objects. The new structure uses Title instead of Name and Created instead of CreatedAt, with new fields ArchivedAt (as a nullable pointer) and IsInitial.


194-195: LGTM: CreateProjectRequest updated to use title.

The request struct now uses title instead of name, matching the new API contract.


562-611: LGTM: new user data structures with conversion helper.

The introduction of UserInfo, OrganizationUser, and User types with a ToUser() conversion method is a clean approach to handling the new nested API response structure. The conversion method correctly flattens user information from ou.User fields (ID, Email, Name) while preserving organization-level fields (Role, Created, IsDefault, etc.).


615-620: LGTM: UsersResponse updated to use OrganizationUser array.

The Data field now uses []OrganizationUser to match the new API response structure. Consumers of this response should use the ToUser() method for easier field access.


681-765: LGTM: user API methods updated to handle new data structure.

FindUserByEmail, GetUser, and UpdateUserRole all correctly unmarshal the API response as OrganizationUser and convert to the flattened User struct via ToUser(). This maintains a consistent return type while adapting to the new API format.


1114-1196: LGTM: project creation and update methods use title.

Both CreateProject and UpdateProject methods have been updated to use title as the parameter name and in the request body. Debug messages also reference "title" consistently.

docs/data-sources/organization_user.md (1)

25-25: LGTM: documentation updated to reflect field rename.

The documentation correctly reflects the rename from added_at to created for the organization user data source.

docs/data-sources/organization_users.md (1)

49-49: LGTM: documentation updated for nested schema.

The nested users schema documentation correctly shows created instead of added_at.

docs/resources/organization_user.md (1)

44-44: LGTM: resource documentation updated.

The resource documentation correctly reflects the created field rename.

internal/provider/data_source_openai_organization_user.go (2)

41-45: LGTM: schema field renamed from added_at to created.

The data source schema correctly uses created to match the new API response format.


117-119: LGTM: field mapping updated.

The code correctly sets created from user.Created with an appropriate error message.

internal/provider/resource_openai_organization_user.go (2)

49-53: LGTM: resource schema field renamed.

The resource schema correctly uses created instead of added_at.


101-103: LGTM: all CRUD operations updated consistently.

All resource CRUD operations (Create, Read, Update) correctly set the created field from user.Created with appropriate error messages.

Also applies to: 144-146, 176-178

internal/provider/data_source_openai_organization_users.go (3)

61-65: LGTM: schema field renamed to created.

The users list schema correctly uses created for the timestamp field.


103-109: LGTM: single user mapping updated.

When fetching a specific user by ID, the mapping correctly uses user.Created for the created field.


147-159: LGTM: paginated user list updated with conversion helper.

The pagination loop correctly:

  1. Iterates over resp.Data which is now []OrganizationUser
  2. Renames the loop variable to orgUser for clarity
  3. Converts each orgUser to a flattened User via ToUser()
  4. Maps all fields including user.Created to the created field

This ensures consistent output structure across both single-user and paginated cases.

docs/resources/project.md (3)

15-31: Example usage correctly updated to use title field.

The example usage properly demonstrates the new title field and removes the deprecated description field. This aligns with the API schema changes.


36-50: Schema documentation reflects the new API structure.

The schema correctly documents:

  • title as required
  • archived_at and created as Number (timestamps)
  • is_initial as Boolean

This matches the changes in resource_openai_project.go.


5-6: The description block in lines 5-6 is intentionally empty and is consistent with all other auto-generated resource documentation files in this repository. Since this file is auto-generated by terraform-plugin-docs (as noted in the header), the empty description format is expected and not a cause for concern. The pipeline failure is unrelated to the empty description.

Likely an incorrect or invalid review comment.

docs/data-sources/projects.md (1)

40-50: Nested schema for projects correctly documents new field structure.

The nested schema accurately reflects the updated API response structure with archived_at, created, is_initial, and title fields replacing the old created_at and name fields.

internal/provider/data_source_openai_project.go (2)

16-24: ProjectResponse struct correctly reflects the new API schema.

The struct properly maps the updated API fields with appropriate types:

  • Created as int64 for Unix timestamp
  • ArchivedAt as *int64 to handle nullable timestamps
  • IsInitial as bool

158-165: Nil check for ArchivedAt is handled correctly.

The code properly checks for nil before dereferencing the pointer, preventing potential nil pointer dereferences. The is_initial field is correctly set without needing a nil check since it's a bool with a zero value default.

internal/provider/resource_openai_project.go (4)

36-61: Schema correctly reflects the updated API structure.

The schema properly defines:

  • title as required (replacing name)
  • created as TypeInt (replacing created_at string)
  • archived_at as TypeInt
  • is_initial as TypeBool (new field)

This is consistent with the data source schema and documentation.


125-134: Consistent handling of nullable ArchivedAt field.

The nil check before dereferencing project.ArchivedAt is correct and consistent with the data source implementation. The is_initial field is properly set.


75-83: Verify CreateProject client method signature.

The call to c.CreateProject(title) assumes the client method accepts only a title parameter. Ensure the client implementation in the OpenAI SDK matches this signature and confirm whether the parameters have changed from a previous version that may have accepted name, description, and isDefault.


148-156: The UpdateProject method signature is correct.

The client method is defined as func (c *OpenAIClient) UpdateProject(id, title string) (*Project, error) in internal/client/client.go, which matches the call c.UpdateProject(d.Id(), title) exactly—both id and title are passed as strings, and the error return value is properly captured.

docs/data-sources/project.md (2)

26-32: Example correctly demonstrates the updated title field.

The locals block properly shows the renamed field access from name to title, helping users migrate their configurations.


46-53: Read-Only schema documentation is accurate.

The schema correctly documents the new fields (archived_at, created, is_initial, title) with appropriate types, matching the implementation in data_source_openai_project.go.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
docs/resources/project.md (1)

15-31: Example usage should reflect all required and new fields.

The example shows how to create projects with title, but users may benefit from seeing a more complete example that includes optional fields and demonstrates accessing read-only fields. Consider expanding the example to show how to reference the new fields in outputs (e.g., is_initial, created).

Expand the example to be more instructive:

 # Create a new OpenAI project
 resource "openai_project" "development" {
   title = "Development Project"
 }

 # Create a production project
 resource "openai_project" "production" {
   title = "Production API Services"
 }

 # Output the project ID
 output "dev_project_id" {
   value       = openai_project.development.id
   description = "The ID of the development project"
 }
+
+# Access read-only fields
+output "dev_project_created" {
+  value       = openai_project.development.created
+  description = "Unix timestamp when the development project was created"
+}
+
+output "dev_is_initial" {
+  value       = openai_project.development.is_initial
+  description = "Whether this is the initial project"
+}
examples/resources/openai_project/resource.tf (1)

2-9: Example usage is consistent with documented schema changes.

The resources correctly use the new title attribute. However, users accustomed to the name and description attributes should be warned of this breaking change in the example comments.

Add a clarifying comment to help users understand the changes:

 # Create a new OpenAI project
+# Note: The 'title' field replaces the previous 'name' and 'description' fields
 resource "openai_project" "development" {
   title = "Development Project"
 }

 # Create a production project
 resource "openai_project" "production" {
   title = "Production API Services"
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 044359b and 7558d8a.

📒 Files selected for processing (5)
  • docs/data-sources/project.md (2 hunks)
  • docs/data-sources/projects.md (1 hunks)
  • docs/resources/project.md (2 hunks)
  • examples/data-sources/openai_project/data-source.tf (1 hunks)
  • examples/resources/openai_project/resource.tf (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/data-sources/projects.md
  • docs/data-sources/project.md
🔇 Additional comments (1)
examples/data-sources/openai_project/data-source.tf (1)

16-16: Example usage correctly updated to reflect schema changes.

The local variable rename from project_name to project_title and the attribute access change from .name to .title are consistent with the documented schema changes. However, note that this is a breaking change for users with existing Terraform configurations referencing the .name attribute.

Verify that migration guidance or deprecation warnings are provided to users upgrading to this version, as the removal of the .name attribute will break existing configurations.

Comment on lines +38 to 50
- `title` (String) The title of the project

### Optional

- `description` (String) A description of the project
- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts))

### Read-Only

- `archived_at` (String) Timestamp when the project was archived, if applicable
- `created_at` (String) Timestamp when the project was created
- `archived_at` (Number) Timestamp when the project was archived, if applicable
- `created` (Number) Timestamp when the project was created
- `id` (String) The ID of this resource.
- `is_initial` (Boolean) Whether this is the initial project
- `status` (String) Status of the project (active, archived, etc.)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Breaking schema changes lack migration guidance.

The documentation reflects significant breaking changes but does not provide migration guidance:

  1. Removed fields (no longer accessible): description, usage_limits — users relying on these will encounter errors
  2. Type changes (String → Number): archived_at and created — users with string parsing logic will break
  3. Field rename (created_at → created): Affects both references and potentially parsing expectations

Users upgrading to this version will experience silent failures or errors if their configurations or parsing logic depend on the old field names or types.

Add a Breaking Changes section to the documentation to inform users:

### Breaking Changes

- **`name``title`**: The project name attribute has been renamed to `title`
- **`created_at``created`** with type change (String → Number): Now returns a Unix timestamp
- **`archived_at`** type change (String → Number): Now returns a Unix timestamp  
- **Removed fields**: `description` and `usage_limits` are no longer available
- **New field**: `is_initial` (Boolean) indicates if the project is the initial/default project
🤖 Prompt for AI Agents
In docs/resources/project.md around lines 38-50, add a "Breaking Changes"
section that enumerates field renames, type changes, and removals and provides
brief migration guidance: list name→title, created_at→created (String→Number)
and archived_at (String→Number) with instruction to convert/expect Unix
timestamps instead of parsing strings, note removed fields description and
usage_limits and recommend alternatives or fallbacks, and call out the new
is_initial Boolean; ensure the section clearly maps old field names/types to new
ones and gives one-line steps developers can take to update parsing/validation
and migrate stored data.

@Fodoj Fodoj merged commit 2cc4322 into main Dec 2, 2025
6 checks passed
@Fodoj Fodoj deleted the fix-breaking branch December 2, 2025 12:49
Fodoj added a commit that referenced this pull request Dec 4, 2025
Fodoj added a commit that referenced this pull request Dec 4, 2025
* Revert "Fix breaking APIs (#45)"

This reverts commit 2cc4322.

* Revert "Version bump (#47)"

This reverts commit 45157c6.

* Revert api changes

* Remove none existing fields

* Further projects clean up

* Remove usage limits

* Fix rate limits

* REmove unused field
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.

2 participants