diff --git a/equinix/provider.go b/equinix/provider.go
index 45dc2f0b9..e1af82f75 100644
--- a/equinix/provider.go
+++ b/equinix/provider.go
@@ -133,7 +133,6 @@ func Provider() *schema.Provider {
 			"equinix_metal_project_api_key":      resourceMetalProjectAPIKey(),
 			"equinix_metal_device":               resourceMetalDevice(),
 			"equinix_metal_device_network_type":  resourceMetalDeviceNetworkType(),
-			"equinix_metal_organization_member":  resourceMetalOrganizationMember(),
 			"equinix_metal_port":                 resourceMetalPort(),
 			"equinix_metal_project":              metal_project.Resource(),
 			"equinix_metal_reserved_ip_block":    resourceMetalReservedIPBlock(),
diff --git a/equinix/resource_metal_organization_member.go b/equinix/resource_metal_organization_member.go
deleted file mode 100644
index 585a6ec44..000000000
--- a/equinix/resource_metal_organization_member.go
+++ /dev/null
@@ -1,285 +0,0 @@
-package equinix
-
-import (
-	"fmt"
-	"log"
-	"path"
-	"strings"
-
-	"github.com/equinix/terraform-provider-equinix/internal/converters"
-
-	equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors"
-	equinix_schema "github.com/equinix/terraform-provider-equinix/internal/schema"
-
-	"github.com/equinix/terraform-provider-equinix/internal/config"
-
-	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
-	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
-	"github.com/packethost/packngo"
-)
-
-type member struct {
-	*packngo.Member
-	*packngo.Invitation
-}
-
-func (m *member) isMember() bool {
-	return m.Member != nil
-}
-
-func (m *member) isInvitation() bool {
-	return m.Invitation != nil
-}
-
-func resourceMetalOrganizationMember() *schema.Resource {
-	return &schema.Resource{
-		Create: resourceMetalOrganizationMemberCreate,
-		Read:   resourceMetalOrganizationMemberRead,
-		Delete: resourceMetalOrganizationMemberDelete,
-		Importer: &schema.ResourceImporter{
-			State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
-				parts := strings.Split(d.Id(), ":")
-				invitee := parts[0]
-				orgID := parts[1]
-				d.SetId(d.Id())
-				d.Set("invitee", invitee)
-				d.Set("organization_id", orgID)
-				if err := resourceMetalOrganizationMemberRead(d, meta); err != nil {
-					return nil, err
-				}
-				if d.Id() == "" {
-					return nil, fmt.Errorf("Member %s does not exist in organization %s.", invitee, orgID)
-				}
-				return []*schema.ResourceData{d}, nil
-			},
-		},
-
-		Schema: map[string]*schema.Schema{
-			"invitee": {
-				Type:         schema.TypeString,
-				Description:  "The email address of the user to invite",
-				Required:     true,
-				ForceNew:     true,
-				ValidateFunc: validation.StringIsNotEmpty,
-			},
-			"invited_by": {
-				Type:        schema.TypeString,
-				Description: "The user id of the user that sent the invitation (only known in the invitation stage)",
-				Computed:    true,
-			},
-			"organization_id": {
-				Type:         schema.TypeString,
-				Description:  "The organization to invite the user to",
-				Required:     true,
-				ForceNew:     true,
-				ValidateFunc: validation.StringIsNotEmpty,
-			},
-			"projects_ids": {
-				Type:        schema.TypeSet,
-				Description: "Project IDs the member has access to within the organization. If the member is an 'owner', the projects list should be empty.",
-				Required:    true,
-				Elem: &schema.Schema{
-					Type:         schema.TypeString,
-					ValidateFunc: validation.StringIsNotEmpty,
-				},
-				// TODO: Update should be supported. packngo.InvitationService does not offer an Update	method.
-				ForceNew: true,
-			},
-			"nonce": {
-				Type:        schema.TypeString,
-				Description: "The nonce for the invitation (only known in the invitation stage)",
-				Computed:    true,
-			},
-			"message": {
-				Type:        schema.TypeString,
-				Description: "A message to the invitee (only used during the invitation stage)",
-				Optional:    true,
-				ForceNew:    true,
-			},
-			"created": {
-				Type:        schema.TypeString,
-				Description: "When the invitation was created (only known in the invitation stage)",
-				Computed:    true,
-			},
-			"updated": {
-				Type:        schema.TypeString,
-				Description: "When the invitation was updated (only known in the invitation stage)",
-				Computed:    true,
-			},
-			"roles": {
-				Type:        schema.TypeSet,
-				Description: "Organization roles (owner, collaborator, limited_collaborator, billing)",
-				Required:    true,
-				Elem:        &schema.Schema{Type: schema.TypeString},
-				// TODO: Update should be supported. packngo.InvitationService does not offer an Update	method.
-				ForceNew: true,
-			},
-			"state": {
-				Type:        schema.TypeString,
-				Description: "The state of the membership ('invited' when an invitation is open, 'active' when the user is an organization member)",
-				Computed:    true,
-			},
-		},
-	}
-}
-
-func resourceMetalOrganizationMemberCreate(d *schema.ResourceData, meta interface{}) error {
-	client := meta.(*config.Config).Metal
-
-	email := d.Get("invitee").(string)
-	createRequest := &packngo.InvitationCreateRequest{
-		Invitee:     email,
-		Roles:       converters.IfArrToStringArr(d.Get("roles").(*schema.Set).List()),
-		ProjectsIDs: converters.IfArrToStringArr(d.Get("projects_ids").(*schema.Set).List()),
-		Message:     strings.TrimSpace(d.Get("message").(string)),
-	}
-
-	orgID := d.Get("organization_id").(string)
-	_, _, err := client.Invitations.Create(orgID, createRequest, nil)
-	if err != nil {
-		return equinix_errors.FriendlyError(err)
-	}
-
-	d.SetId(fmt.Sprintf("%s:%s", email, orgID))
-
-	return resourceMetalOrganizationMemberRead(d, meta)
-}
-
-func findMember(invitee string, members []packngo.Member, invitations []packngo.Invitation) (*member, error) {
-	for _, mbr := range members {
-		if mbr.User.Email == invitee {
-			return &member{Member: &mbr}, nil
-		}
-	}
-
-	for _, inv := range invitations {
-		if inv.Invitee == invitee {
-			return &member{Invitation: &inv}, nil
-		}
-	}
-	return nil, fmt.Errorf("member not found")
-}
-
-func resourceMetalOrganizationMemberRead(d *schema.ResourceData, meta interface{}) error {
-	client := meta.(*config.Config).Metal
-	parts := strings.Split(d.Id(), ":")
-	invitee := parts[0]
-	orgID := parts[1]
-
-	listOpts := &packngo.ListOptions{Includes: []string{"user"}}
-	invitations, _, err := client.Invitations.List(orgID, listOpts)
-	if err != nil {
-		err = equinix_errors.FriendlyError(err)
-		// If the org was destroyed, mark as gone.
-		if equinix_errors.IsNotFound(err) {
-			d.SetId("")
-			return nil
-		}
-		return err
-	}
-
-	members, _, err := client.Members.List(orgID, &packngo.GetOptions{Includes: []string{"user"}})
-	if err != nil {
-		err = equinix_errors.FriendlyError(err)
-		// If the org was destroyed, mark as gone.
-		if equinix_errors.IsNotFound(err) {
-			d.SetId("")
-			return nil
-		}
-		return err
-	}
-	member, err := findMember(invitee, members, invitations)
-	if !d.IsNewResource() && err != nil {
-		log.Printf("[WARN] Could not find member %s in organization, removing from state", d.Id())
-		d.SetId("")
-		return nil
-	}
-
-	if member.isMember() {
-		projectIDs := []string{}
-		for _, project := range member.Member.Projects {
-			projectIDs = append(projectIDs, path.Base(project.URL))
-		}
-		return equinix_schema.SetMap(d, map[string]interface{}{
-			"state":           "active",
-			"roles":           converters.StringArrToIfArr(member.Member.Roles),
-			"projects_ids":    converters.StringArrToIfArr(projectIDs),
-			"organization_id": path.Base(member.Member.Organization.URL),
-		})
-	} else if member.isInvitation() {
-		projectIDs := []string{}
-		for _, project := range member.Invitation.Projects {
-			projectIDs = append(projectIDs, path.Base(project.Href))
-		}
-		return equinix_schema.SetMap(d, map[string]interface{}{
-			"state":           "invited",
-			"organization_id": path.Base(member.Invitation.Organization.Href),
-			"roles":           member.Invitation.Roles,
-			"projects_ids":    projectIDs,
-			"created":         member.Invitation.CreatedAt.String(),
-			"updated":         member.Invitation.UpdatedAt.String(),
-			"nonce":           member.Invitation.Nonce,
-			"invited_by":      path.Base(member.Invitation.InvitedBy.Href),
-		})
-	}
-	return fmt.Errorf("got an invalid member object")
-}
-
-func resourceMetalOrganizationMemberDelete(d *schema.ResourceData, meta interface{}) error {
-	client := meta.(*config.Config).Metal
-
-	listOpts := &packngo.ListOptions{Includes: []string{"user"}}
-	invitations, _, err := client.Invitations.List(d.Get("organization_id").(string), listOpts)
-	if err != nil {
-		err = equinix_errors.FriendlyError(err)
-		// If the org was destroyed, mark as gone.
-		if equinix_errors.IsNotFound(err) {
-			d.SetId("")
-			return nil
-		}
-		return err
-	}
-
-	orgID := d.Get("organization_id").(string)
-	org, _, err := client.Organizations.Get(orgID, &packngo.GetOptions{Includes: []string{"members", "members.user"}})
-	if err != nil {
-		err = equinix_errors.FriendlyError(err)
-		// If the org was destroyed, mark as gone.
-		if equinix_errors.IsNotFound(err) {
-			d.SetId("")
-			return nil
-		}
-		return err
-	}
-
-	member, err := findMember(d.Get("invitee").(string), org.Members, invitations)
-	if err != nil {
-		d.SetId("")
-		return nil
-	}
-
-	if member.isMember() {
-		_, err = client.Members.Delete(orgID, member.Member.ID)
-		if err != nil {
-			err = equinix_errors.FriendlyError(err)
-			// If the member was deleted, mark as gone.
-			if equinix_errors.IsNotFound(err) {
-				d.SetId("")
-				return nil
-			}
-			return err
-		}
-	} else if member.isInvitation() {
-		_, err = client.Invitations.Delete(member.Invitation.ID)
-		if err != nil {
-			err = equinix_errors.FriendlyError(err)
-			// If the invitation was deleted, mark as gone.
-			if equinix_errors.IsNotFound(err) {
-				d.SetId("")
-				return nil
-			}
-			return err
-		}
-	}
-	return nil
-}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index e682f63c3..f5677c607 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -8,6 +8,7 @@ import (
 	metalconnection "github.com/equinix/terraform-provider-equinix/internal/resources/metal/connection"
 	metalgateway "github.com/equinix/terraform-provider-equinix/internal/resources/metal/gateway"
 	metalorganization "github.com/equinix/terraform-provider-equinix/internal/resources/metal/organization"
+	metalorganizationmember "github.com/equinix/terraform-provider-equinix/internal/resources/metal/organization_member"
 	metalprojectsshkey "github.com/equinix/terraform-provider-equinix/internal/resources/metal/project_ssh_key"
 	metalsshkey "github.com/equinix/terraform-provider-equinix/internal/resources/metal/ssh_key"
 	equinix_validation "github.com/equinix/terraform-provider-equinix/internal/validation"
@@ -116,6 +117,7 @@ func (p *FrameworkProvider) Resources(ctx context.Context) []func() resource.Res
 		metalsshkey.NewResource,
 		metalconnection.NewResource,
 		metalorganization.NewResource,
+		metalorganizationmember.NewResource,
 	}
 }
 
diff --git a/internal/resources/metal/organization_member/models.go b/internal/resources/metal/organization_member/models.go
new file mode 100644
index 000000000..9a9b16ce8
--- /dev/null
+++ b/internal/resources/metal/organization_member/models.go
@@ -0,0 +1,77 @@
+package organizationmember
+
+import (
+	"context"
+	"path"
+
+	"github.com/hashicorp/terraform-plugin-framework/diag"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+type ResourceModel struct {
+	ID             types.String `tfsdk:"id"`
+	Invitee        types.String `tfsdk:"invitee"`
+	InvitedBy      types.String `tfsdk:"invited_by"`
+	OrganizationID types.String `tfsdk:"organization_id"`
+	ProjectsIDs    types.Set    `tfsdk:"projects_ids"`
+	Nonce          types.String `tfsdk:"nonce"`
+	Message        types.String `tfsdk:"message"`
+	Created        types.String `tfsdk:"created"`
+	Updated        types.String `tfsdk:"updated"`
+	Roles          types.Set    `tfsdk:"roles"`
+	State          types.String `tfsdk:"state"`
+}
+
+// func (m *ResourceModel) parse(ctx context.Context, invitee string, members []packngo.Member, invitations []packngo.Invitation) diag.Diagnostics {
+func (m *ResourceModel) parse(ctx context.Context, member *member) diag.Diagnostics {
+	var diags diag.Diagnostics
+
+	if member.isMember() {
+		projectIDs := []string{}
+		for _, project := range member.Member.Projects {
+			projectIDs = append(projectIDs, path.Base(project.URL))
+		}
+
+		projectsList, diag := types.SetValueFrom(ctx, types.StringType, projectIDs)
+		if diag.HasError() {
+			return diag
+		}
+		m.ProjectsIDs = projectsList
+		m.State = types.StringValue("active")
+
+		rolesList, diag := types.SetValueFrom(ctx, types.StringType, member.Member.Roles)
+		if diag.HasError() {
+			return diag
+		}
+		m.Roles = rolesList
+		m.OrganizationID = types.StringValue(member.Member.Organization.URL)
+
+	} else if member.isInvitation() {
+		projectIDs := []string{}
+		for _, project := range member.Invitation.Projects {
+			projectIDs = append(projectIDs, path.Base(project.Href))
+		}
+		projectsList, diag := types.SetValueFrom(ctx, types.StringType, projectIDs)
+		if diag.HasError() {
+			return diag
+		}
+		m.ProjectsIDs = projectsList
+
+		m.State = types.StringValue("invited")
+
+		rolesList, diag := types.SetValueFrom(ctx, types.StringType, member.Invitation.Roles)
+		if diag.HasError() {
+			return diag
+		}
+		m.Roles = rolesList
+
+		m.OrganizationID = types.StringValue(path.Base(member.Invitation.Organization.Href))
+		m.Created = types.StringValue(member.Invitation.CreatedAt.String())
+		m.Updated = types.StringValue(member.Invitation.UpdatedAt.String())
+		m.Nonce = types.StringValue(member.Invitation.Nonce)
+
+		m.InvitedBy = types.StringValue(path.Base(member.Invitation.InvitedBy.Href))
+		m.ID = types.StringValue(member.Invitation.ID)
+	}
+	return diags
+}
diff --git a/internal/resources/metal/organization_member/resource.go b/internal/resources/metal/organization_member/resource.go
new file mode 100644
index 000000000..7b7c7ec88
--- /dev/null
+++ b/internal/resources/metal/organization_member/resource.go
@@ -0,0 +1,339 @@
+package organizationmember
+
+import (
+	"context"
+	"fmt"
+	"log"
+	"strings"
+
+	equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors"
+	"github.com/equinix/terraform-provider-equinix/internal/framework"
+	tfpath "github.com/hashicorp/terraform-plugin-framework/path"
+	"github.com/hashicorp/terraform-plugin-framework/resource"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+	"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+	"github.com/hashicorp/terraform-plugin-log/tflog"
+	"github.com/packethost/packngo"
+)
+
+type member struct {
+	*packngo.Member
+	*packngo.Invitation
+}
+
+func (m *member) isMember() bool {
+	return m.Member != nil
+}
+
+func (m *member) isInvitation() bool {
+	return m.Invitation != nil
+}
+
+func NewResource() resource.Resource {
+	return &Resource{
+		BaseResource: framework.NewBaseResource(
+			framework.BaseResourceConfig{
+				Name:   "equinix_metal_organization_member",
+				Schema: GetResourceSchema(),
+			},
+		),
+	}
+}
+
+type Resource struct {
+	framework.BaseResource
+}
+
+func (r *Resource) ImportState(
+	ctx context.Context,
+	req resource.ImportStateRequest,
+	resp *resource.ImportStateResponse,
+) {
+	tflog.Debug(ctx, "importer Organization")
+
+	parts := strings.Split(req.ID, ":")
+	if len(parts) != 2 {
+		return
+
+	}
+	invitee := parts[0]
+	orgID := parts[1]
+
+	resp.Diagnostics.Append(resp.State.SetAttribute(ctx, tfpath.Root("invitee"), invitee)...)
+	resp.Diagnostics.Append(resp.State.SetAttribute(ctx, tfpath.Root("organization_id"), orgID)...)
+}
+
+func (r *Resource) Create(
+	ctx context.Context,
+	req resource.CreateRequest,
+	resp *resource.CreateResponse,
+) {
+	r.Meta.AddFwModuleToMetalUserAgent(ctx, req.ProviderMeta)
+	client := r.Meta.Metal
+
+	var plan ResourceModel
+	resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
+	if resp.Diagnostics.HasError() {
+		return
+	}
+
+	invite := plan.Invitee.ValueString()
+
+	roles := make([]string, 0)
+	for _, elem := range plan.Roles.Elements() {
+		if strValue, ok := elem.(types.String); ok {
+
+			if !strValue.IsNull() {
+				roles = append(roles, strValue.ValueString())
+			}
+		}
+	}
+
+	projects := make([]string, 0)
+	for _, elem := range plan.ProjectsIDs.Elements() {
+		if strValue, ok := elem.(types.String); ok {
+			projects = append(projects, strValue.ValueString())
+		}
+	}
+
+	createRequest := &packngo.InvitationCreateRequest{
+		Invitee:     invite,
+		Roles:       roles,
+		ProjectsIDs: projects,
+		Message:     strings.TrimSpace(plan.Message.ValueString()),
+	}
+
+	orgID := plan.OrganizationID.ValueString()
+	_, _, err := client.Invitations.Create(orgID, createRequest, nil)
+	if err != nil {
+		resp.Diagnostics.AddError(
+			"Failed to create invitation",
+			err.Error(),
+		)
+		return
+	}
+
+	listOpts := &packngo.ListOptions{Includes: []string{"user"}}
+	invitations, _, err := client.Invitations.List(orgID, listOpts)
+	if err != nil {
+		err = equinix_errors.FriendlyError(err)
+		// If the org was destroyed, mark as gone.
+		if equinix_errors.IsNotFound(err) {
+			plan.OrganizationID = basetypes.NewStringNull()
+			return
+		}
+		resp.Diagnostics.AddError(
+			"Failed to list invitations",
+			err.Error(),
+		)
+		return
+	}
+
+	members, _, err := client.Members.List(orgID, listOpts)
+	if err != nil {
+		err = equinix_errors.FriendlyError(err)
+		// If the org was destroyed, mark as gone.
+		if equinix_errors.IsNotFound(err) {
+			return
+		}
+		resp.Diagnostics.AddError(
+			"Failed to List members",
+			err.Error(),
+		)
+		return
+	}
+
+	member, err := findMember(invite, members, invitations)
+	if err != nil {
+		log.Printf("[WARN] Could not find member %s in organization, removing from state", plan.OrganizationID)
+		plan.OrganizationID = basetypes.NewStringNull()
+		resp.Diagnostics.AddError(
+			"Failed to find members",
+			err.Error(),
+		)
+		return
+	}
+
+	// Parse API response into the Terraform state
+	if member != nil {
+		diags := plan.parse(ctx, member)
+		if diags.HasError() {
+			resp.Diagnostics.Append(diags...)
+			return
+		}
+	}
+
+	// Set state to fully populated data
+	resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
+}
+
+func (r *Resource) Read(
+	ctx context.Context,
+	req resource.ReadRequest,
+	resp *resource.ReadResponse,
+) {
+	tflog.Debug(ctx, "Read Organization")
+	r.Meta.AddFwModuleToMetalUserAgent(ctx, req.ProviderMeta)
+	client := r.Meta.Metal
+
+	// Retrieve values from plan
+	var data ResourceModel
+	resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+	if resp.Diagnostics.HasError() {
+		return
+	}
+
+	invitee := data.Invitee.ValueString()
+	orgID := data.OrganizationID.ValueString()
+
+	listOpts := &packngo.ListOptions{Includes: []string{"user"}}
+	invitations, _, err := client.Invitations.List(orgID, listOpts)
+	if err != nil {
+		err = equinix_errors.FriendlyError(err)
+		// If the org was destroyed, mark as gone.
+		if equinix_errors.IsNotFound(err) {
+			data.OrganizationID = basetypes.NewStringNull()
+			return
+		}
+		resp.Diagnostics.AddError(
+			"Failed to list invitations",
+			err.Error(),
+		)
+		return
+	}
+
+	members, _, err := client.Members.List(orgID, &packngo.GetOptions{Includes: []string{"user"}})
+	if err != nil {
+		err = equinix_errors.FriendlyError(err)
+		// If the org was destroyed, mark as gone.
+		if equinix_errors.IsNotFound(err) {
+			data.OrganizationID = basetypes.NewStringNull()
+			return
+		}
+		resp.Diagnostics.AddError(
+			"Failed to list members",
+			err.Error(),
+		)
+		return
+	}
+	member, err := findMember(invitee, members, invitations)
+	if err != nil {
+		log.Printf("[WARN] Could not find member %s in organization, removing from state", data.OrganizationID)
+		data.OrganizationID = basetypes.NewStringNull()
+		return
+	}
+
+	diags := data.parse(ctx, member)
+	if diags.HasError() {
+		resp.Diagnostics.Append(diags...)
+		return
+	}
+	// Set state to fully populated data
+	resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *Resource) Delete(
+	ctx context.Context,
+	req resource.DeleteRequest,
+	resp *resource.DeleteResponse,
+) {
+	tflog.Debug(ctx, "Delete Organization")
+	r.Meta.AddFwModuleToMetalUserAgent(ctx, req.ProviderMeta)
+	client := r.Meta.Metal
+
+	var data ResourceModel
+
+	listOpts := &packngo.ListOptions{Includes: []string{"user"}}
+	invitations, _, err := client.Invitations.List(data.OrganizationID.ValueString(), listOpts)
+	if err != nil {
+		err = equinix_errors.FriendlyError(err)
+		// If the org was destroyed, mark as gone.
+		if equinix_errors.IsNotFound(err) {
+			data.OrganizationID = types.StringNull()
+			return
+		}
+		resp.Diagnostics.AddError(
+			"Failed to list invitations",
+			err.Error(),
+		)
+		return
+	}
+
+	org, _, err := client.Organizations.Get(data.OrganizationID.ValueString(), &packngo.GetOptions{Includes: []string{"members", "members.user"}})
+	if err != nil {
+		err = equinix_errors.FriendlyError(err)
+		// If the org was destroyed, mark as gone.
+		if equinix_errors.IsNotFound(err) {
+			data.OrganizationID = types.StringNull()
+			return
+		}
+
+		resp.Diagnostics.AddError(
+			"Failed to get Organizations",
+			err.Error(),
+		)
+		return
+	}
+
+	member, err := findMember(data.Invitee.ValueString(), org.Members, invitations)
+	if err != nil {
+		data.OrganizationID = types.StringNull()
+		return
+	}
+
+	if member.isMember() {
+		_, err = client.Members.Delete(data.OrganizationID.ValueString(), member.Member.ID)
+		if err != nil {
+			err = equinix_errors.FriendlyError(err)
+			// If the member was deleted, mark as gone.
+			if equinix_errors.IsNotFound(err) {
+				data.OrganizationID = types.StringNull()
+				return
+			}
+			resp.Diagnostics.AddError(
+				"Failed to delete member",
+				err.Error(),
+			)
+			return
+		}
+	} else if member.isInvitation() {
+		_, err = client.Invitations.Delete(member.Invitation.ID)
+		if err != nil {
+			err = equinix_errors.FriendlyError(err)
+			// If the invitation was deleted, mark as gone.
+			if equinix_errors.IsNotFound(err) {
+				data.OrganizationID = types.StringNull()
+				return
+			}
+
+			resp.Diagnostics.AddError(
+				"Failed to delete invitation",
+				err.Error(),
+			)
+			return
+		}
+	}
+}
+
+func (r *Resource) Update(
+	ctx context.Context,
+	req resource.UpdateRequest,
+	resp *resource.UpdateResponse,
+) {
+	// This resource does not support updates
+}
+
+func findMember(invitee string, members []packngo.Member, invitations []packngo.Invitation) (*member, error) {
+	for _, mbr := range members {
+		if mbr.User.Email == invitee {
+			return &member{Member: &mbr}, nil
+		}
+	}
+
+	for _, inv := range invitations {
+		if inv.Invitee == invitee {
+			return &member{Invitation: &inv}, nil
+		}
+	}
+	return nil, fmt.Errorf("member not found")
+}
diff --git a/internal/resources/metal/organization_member/resource_schema.go b/internal/resources/metal/organization_member/resource_schema.go
new file mode 100644
index 000000000..7808020bd
--- /dev/null
+++ b/internal/resources/metal/organization_member/resource_schema.go
@@ -0,0 +1,67 @@
+package organizationmember
+
+import (
+	"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
+	"github.com/hashicorp/terraform-plugin-framework/resource/schema"
+	"github.com/hashicorp/terraform-plugin-framework/schema/validator"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+func GetResourceSchema() *schema.Schema {
+	return &schema.Schema{
+		Attributes: map[string]schema.Attribute{
+			"id": schema.StringAttribute{
+				Description: "The unique identifier for the organization member.",
+				Computed:    true,
+			},
+			"invitee": schema.StringAttribute{
+				Description: "The email address of the user to invite",
+				Required:    true,
+				Validators: []validator.String{
+					stringvalidator.LengthAtLeast(1),
+				},
+			},
+			"invited_by": schema.StringAttribute{
+				Description: "The user id of the user that sent the invitation (only known in the invitation stage)",
+				Computed:    true,
+			},
+			"organization_id": schema.StringAttribute{
+				Description: "The organization to invite the user to",
+				Required:    true,
+				Validators: []validator.String{
+					stringvalidator.LengthAtLeast(1),
+				},
+			},
+			"projects_ids": schema.SetAttribute{
+				Description: "Project IDs the member has access to within the organization. If the member is an 'owner', the projects list should be empty.",
+				Required:    true,
+				ElementType: types.StringType,
+			},
+			"nonce": schema.StringAttribute{
+				Description: "The nonce for the invitation (only known in the invitation stage)",
+				Computed:    true,
+			},
+			"message": schema.StringAttribute{
+				Description: "A message to the invitee (only used during the invitation stage)",
+				Optional:    true,
+			},
+			"created": schema.StringAttribute{
+				Description: "When the invitation was created (only known in the invitation stage)",
+				Computed:    true,
+			},
+			"updated": schema.StringAttribute{
+				Description: "When the invitation was updated (only known in the invitation stage)",
+				Computed:    true,
+			},
+			"roles": schema.SetAttribute{
+				ElementType: types.StringType,
+				Description: "Organization roles (owner, collaborator, limited_collaborator, billing)",
+				Required:    true,
+			},
+			"state": schema.StringAttribute{
+				Description: "The state of the membership ('invited' when an invitation is open, 'active' when the user is an organization member)",
+				Computed:    true,
+			},
+		},
+	}
+}
diff --git a/equinix/resource_metal_organization_member_acc_test.go b/internal/resources/metal/organization_member/resource_test.go
similarity index 77%
rename from equinix/resource_metal_organization_member_acc_test.go
rename to internal/resources/metal/organization_member/resource_test.go
index 9e201437c..41f53942d 100644
--- a/equinix/resource_metal_organization_member_acc_test.go
+++ b/internal/resources/metal/organization_member/resource_test.go
@@ -1,9 +1,10 @@
-package equinix
+package organizationmember_test
 
 import (
 	"fmt"
 	"testing"
 
+	"github.com/equinix/terraform-provider-equinix/internal/acceptance"
 	"github.com/equinix/terraform-provider-equinix/internal/config"
 	"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
 	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
@@ -15,11 +16,9 @@ func TestAccResourceMetalOrganizationMember_owner(t *testing.T) {
 	rInt := acctest.RandInt()
 	org := &packngo.Organization{}
 	resource.ParallelTest(t, resource.TestCase{
-		PreCheck:                 func() { testAccPreCheck(t) },
-		ExternalProviders:        testExternalProviders,
-		ProtoV5ProviderFactories: testAccProtoV5ProviderFactories,
-		// TODO: CheckDestroy: testAccMetalOrganizationMemberCheckDestroyed,
-		CheckDestroy: nil,
+		PreCheck:                 func() { acceptance.TestAccPreCheckMetal(t); acceptance.TestAccPreCheckProviderConfigured(t) },
+		ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories,
+		CheckDestroy:             testAccMetalOrganizationCheckDestroyed,
 		Steps: []resource.TestStep{
 			{
 				Config: testAccResourceMetalOrganizationMember_basic(rInt),
@@ -35,13 +34,6 @@ func TestAccResourceMetalOrganizationMember_owner(t *testing.T) {
 				}),
 				ImportState: true,
 			},
-			/*
-				{
-					ResourceName: "equinix_metal_organization_member.owner",
-					Config:       testAccResourceMetalOrganizationMember_basic(rInt) + testAccResourceMetalOrganizationMember_owner(),
-					ExpectError:  regexp.MustCompile("User is already a member of the Organization"),
-				},
-			*/
 			{
 				Config: testAccResourceMetalOrganizationMember_basic(rInt),
 			},
@@ -53,11 +45,9 @@ func TestAccResourceMetalOrganizationMember_basic(t *testing.T) {
 	rInt := acctest.RandInt()
 	org := &packngo.Organization{}
 	resource.ParallelTest(t, resource.TestCase{
-		PreCheck:                 func() { testAccPreCheck(t) },
-		ExternalProviders:        testExternalProviders,
-		ProtoV5ProviderFactories: testAccProtoV5ProviderFactories,
-		// TODO: CheckDestroy: testAccMetalOrganizationMemberCheckDestroyed,
-		CheckDestroy: nil,
+		PreCheck:                 func() { acceptance.TestAccPreCheckMetal(t); acceptance.TestAccPreCheckProviderConfigured(t) },
+		ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories,
+		CheckDestroy:             testAccMetalOrganizationCheckDestroyed,
 		Steps: []resource.TestStep{
 			{
 				Config: testAccResourceMetalOrganizationMember_basic(rInt),
@@ -104,21 +94,21 @@ resource "equinix_metal_project" "test" {
 }
 
 func testAccResourceMetalOrganizationMember_owner() string {
-	return fmt.Sprintf(`
+	return `
 	resource "equinix_metal_organization_member" "owner" {
 		invitee = "/* TODO: Add org owner email or token owner email here */"
 		roles = ["owner"]
 		projects_ids = []
 		organization_id = equinix_metal_organization.test.id
 	}
-	`)
+	`
 }
 
 func testAccResourceMetalOrganizationMember_member() string {
 	return `
 resource "equinix_metal_organization_member" "member" {
     invitee = "tfacc.testing.member@equinixmetal.com"
-    roles = ["limited_collaborator"]
+	roles = ["limited_collaborator"]
     projects_ids = [equinix_metal_project.test.id]
     organization_id = equinix_metal_organization.test.id
 	message = "This invitation was sent by the github.com/equinix/terraform-provider-equinix acceptance tests to test equinix_metal_organization_member resources."
@@ -126,6 +116,21 @@ resource "equinix_metal_organization_member" "member" {
 `
 }
 
+func testAccMetalOrganizationCheckDestroyed(s *terraform.State) error {
+	client := acceptance.TestAccProvider.Meta().(*config.Config).Metal
+
+	for _, rs := range s.RootModule().Resources {
+		if rs.Type != "equinix_metal_organization" {
+			continue
+		}
+		if _, _, err := client.Organizations.Get(rs.Primary.ID, nil); err == nil {
+			return fmt.Errorf("Metal Organization still exists")
+		}
+	}
+
+	return nil
+}
+
 func testAccMetalOrganizationExists(n string, org *packngo.Organization) resource.TestCheckFunc {
 	return func(s *terraform.State) error {
 		rs, ok := s.RootModule().Resources[n]
@@ -136,7 +141,7 @@ func testAccMetalOrganizationExists(n string, org *packngo.Organization) resourc
 			return fmt.Errorf("No Record ID is set")
 		}
 
-		client := testAccProvider.Meta().(*config.Config).Metal
+		client := acceptance.TestAccProvider.Meta().(*config.Config).Metal
 
 		foundOrg, _, err := client.Organizations.Get(rs.Primary.ID, &packngo.GetOptions{Includes: []string{"address", "primary_owner"}})
 		if err != nil {