Add a REST API endpoint to restore a soft-deleted organization
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Add a REST API endpoint that restores a soft-deleted organization (transitions it from soft_deleted back to active) by exposing Organizations::RestoreService (from #599343 (closed)). Admin-only.
Dependency
Blocked by #599343 (closed), which provides:
Organizations::RestoreService(the service this endpoint calls), and- the
:restore_organizationpolicy ability (admin-only) used forauthorize!.
The route_setting :authorization, permissions: :restore_organization also relies on the granular-token permission registry defined in #599344 (closed) (config/authz/permissions/organization/restore.yml). Whichever of #599344 (closed) / this issue lands first should add that file.
Background
The Organizations REST API (lib/api/organizations.rb) currently exposes only POST /organizations (create). There is no member route yet. The Groups API already has a direct template for this in lib/api/groups.rb — POST /groups/:id/restore calling Groups::RestoreService — which this endpoint mirrors. The find_organization! helper (lib/api/helpers.rb) already loads an organization and enforces :read_organization.
Implementation plan
1. Endpoint — lib/api/organizations.rb
Add a member route inside the existing resource :organizations block, mirroring the create action's style (route_setting :lifecycle, :experiment, route_setting :authorization, ServiceResponse handling):
desc 'Restore a soft-deleted organization' do
detail 'This feature was introduced in GitLab 19.1.'
success Entities::Organizations::Organization
tags %w[organizations]
end
params do
requires :id, type: Integer, desc: 'The ID of the organization'
end
route_setting :lifecycle, :experiment
route_setting :authorization, permissions: :restore_organization, boundary_type: :instance
post ':id/restore' do
organization = find_organization!(params[:id])
authorize! :restore_organization, organization
response = ::Organizations::RestoreService
.new(organization, current_user: current_user)
.execute
if response.success?
present response[:organization], with: Entities::Organizations::Organization
else
render_api_error!(response.message, :bad_request)
end
endNotes:
find_organization!returnsnot_found!for unknown IDs and enforces:read_organization; soft-deleted organizations remain readable (no default scope hides them), andfind_by_idfinds them.authorize! :restore_organizationenforces the admin-only ability from #599343 (closed) — non-admin owners who can read the org are still rejected.- The existing
Entities::Organizations::Organizationis reused as-is for the response; no entity changes needed.
2. Documentation — doc/api/organizations.md
Add a "Restore an organization" section after "Create an organization", documenting:
POST /organizations/:id/restore- the
idattribute, - a
curlexample and a sample response (the organization entity), - the experiment/admin-only note.
3. Request spec — spec/requests/api/organizations_spec.rb
Add describe 'POST /organizations/:id/restore' covering:
- Unauthenticated request →
401. - Authenticated non-admin (e.g. org owner) →
403. - Unknown organization ID →
404. - Admin restoring a
soft_deletedorganization →201/200with the organization payload, state becomesactive. - Admin restoring a non-
soft_deletedorganization →400with the service error message.
Out of scope
Organizations::RestoreServiceitself - Add an Organizations::RestoreService service (#599343 - closed)- The
OrganizationRestoreGraphQL mutation - Add OrganizationRestore GraphQL mutation (#599344 - closed) - Admin Area UI — separate issue.
Acceptance criteria
-
POST /organizations/:id/restoreexists and callsOrganizations::RestoreService. - The endpoint is admin-only via
authorize! :restore_organizationand declares the matching granular-tokenroute_setting :authorization, consistent with the create endpoint. - Restoring a soft-deleted organization returns the organization and transitions it to
active. - Validation/permission failures return appropriate HTTP status codes (
400/403/404). - The endpoint is behind the
experimentlifecycle marker. - REST API docs (
doc/api/organizations.md) document the new endpoint. - Request spec covers auth, success, validation failure, and not-found cases.