As a Google Ads administrator, you can manage user access invitations to a Google Ads
account. Calling these APIs requires an authenticated user with `ADMIN` access
privileges on the target customer account.

## Invite users

> [!NOTE]
> **Note:** When creating an invitation, you must specify a valid email address and assign an appropriate `access_role`. The Google Ads API may generate a multi-party approval request for completing this action. Refer to the [multi-party approval guide](https://developers.google.com/google-ads/api/docs/oauth/multi-party-approvals.md.txt) to learn more.

You can send an email invitation to a new user as part of
[managing access to a Google Ads account](https://support.google.com/google-ads/answer/6372672). This is done by creating a new
[`CustomerUserAccessInvitation`](https://developers.google.com/google-ads/api/reference/rpc/v26/CustomerUserAccessInvitation.md.txt)
using the `MutateCustomerUserAccessInvitation` method of the
[`CustomerUserAccessInvitationService`](https://developers.google.com/google-ads/api/reference/rpc/v26/CustomerUserAccessInvitationService.md.txt).

The email invitation needs to be manually accepted by the user who received the
invitation. The invitation can also be accepted by the user using an alternate
email address. It can take up to 24 hours for the status to change from pending
once the invitation is accepted. Once confirmed, you can manage the user's role
and access as described in [Manage user access](https://developers.google.com/google-ads/api/docs/account-management/managing-users.md.txt).

If Google determines that a multi-party approval is required:

- The [`MutateCustomerUserAccessInvitationResult`](https://developers.google.com/google-ads/api/reference/rpc/v26/MutateCustomerUserAccessInvitationResult.md.txt) will populate the [`multi_party_auth_review`](https://developers.google.com/google-ads/api/reference/rpc/v26/MutateCustomerUserAccessInvitationResult.md.txt#multi_party_auth_review) field containing the resource name of the pending review requiring approval.
- The `resource_name` field will **not** be populated.
- A new invitation cannot be sent for the same email address until the pending multi-party approval request is resolved.
- The pending review request can be approved or rejected by a second administrator using the [`ResolveMultiPartyAuthReview`](https://developers.google.com/google-ads/api/reference/rpc/v26/MultiPartyAuthReviewService/ResolveMultiPartyAuthReview.md.txt) method. Refer to the [multi-party approval guide](https://developers.google.com/google-ads/api/docs/oauth/multi-party-approvals.md.txt) to learn more.

This code snippet shows how to send an invitation:


### Java

```java
// Constructs an access invitation.
CustomerUserAccessInvitation invitation =
    CustomerUserAccessInvitation.newBuilder()
        .setEmailAddress(emailAddress)
        .setAccessRole(accessRole)
        .build();

// Constructs an operation to send the invitation.
CustomerUserAccessInvitationOperation operation =
    CustomerUserAccessInvitationOperation.newBuilder().setCreate(invitation).build();

// Creates a CustomerUserAccessInvitationServiceClient.
try (CustomerUserAccessInvitationServiceClient client =
    googleAdsClient.getLatestVersion().createCustomerUserAccessInvitationServiceClient()) {
  // Issues the request.
  MutateCustomerUserAccessInvitationResponse response =
      client.mutateCustomerUserAccessInvitation(String.valueOf(customerId), operation);

  if (response.getResult().getMultiPartyAuthReview().isEmpty()) {
    // A multi-party auth review was not triggered.
    System.out.printf(
        "Customer user access invitation was sent for customerId = "
            + "%d to email address = '%s' and access role = '%s'. The invitation resource "
            + "name is '%s'.%n",
        customerId, emailAddress, accessRole, response.getResult().getResourceName());
  } else {
    // A multi-party auth review was triggered. See
    // FetchAndApprovePendingMultiPartyAuthReviews.java for an example on how to fetch
    // and approve an MPA auth review.
    System.out.printf(
        "A multi-party auth review was triggered. The MPA review resource name is %s. "
            + "Ask a second administrator to approve this request to send user access invitation. "
            + "See FetchAndApprovePendingMultiPartyAuthReviews.java for an example on "
            + "how to approve an MPA auth review using the API.%n",
        response.getResult().getMultiPartyAuthReview());
  }
}
      
```

### C#

```c#
MutateCustomerUserAccessInvitationRequest invitationRequest =
    new MutateCustomerUserAccessInvitationRequest()
    {
        CustomerId = customerId.ToString(),
        Operation = new CustomerUserAccessInvitationOperation()
        {
            Create = new CustomerUserAccessInvitation()
            {
                EmailAddress = emailAddress,
                AccessRole = accessRole
            },
        }
    };
try
{
    var response = service.MutateCustomerUserAccessInvitation(invitationRequest);

    if (response.Result.MultiPartyAuthReview == null)
    {
        // A multi-party auth review was not triggered.
        Console.WriteLine("Customer user access invitation was sent for " +
            $"customerId = {customerId} to email address = {emailAddress} and " +
            $"access role = {accessRole}. The invitation resource name is " +
            $"{response.Result.ResourceName}.");
    }
    else 
    {
        // A multi-party auth review was triggered. See
        // FetchAndApprovePendingMultiPartyAuthReviews.cs for an example on how to fetch
        // and approve an MPA auth review.
        Console.WriteLine($"A multi-party auth review was triggered. The MPA review " +
            $"resource name is {response.Result.MultiPartyAuthReview}. Ask a second " +
            $"administrator to approve this request to send user access invitation. " +
            $"See FetchAndApprovePendingMultiPartyAuthReviews.cs for an example on " +
            $"how to approve an MPA auth review using the API.");
    }
}
catch (GoogleAdsException e)
{
    Console.WriteLine("Failure:");
    Console.WriteLine($"Message: {e.Message}");
    Console.WriteLine($"Failure: {e.Failure}");
    Console.WriteLine($"Request ID: {e.RequestId}");
    throw;
}
      
```

### PHP

```php
// Creates a customer user access invitation.
$customerUserAccessInvitation = new CustomerUserAccessInvitation([
    'email_address' =>  $emailAddress,
    'access_role' => AccessRole::value($accessRole)
]);

// Creates a customer user access invitation operation.
$customerUserAccessInvitationOperation = new CustomerUserAccessInvitationOperation();
$customerUserAccessInvitationOperation->setCreate($customerUserAccessInvitation);

// Issues a mutate request to send the customer user access invitation and prints its
// information.
$customerUserAccessInvitationServiceClient =
    $googleAdsClient->getCustomerUserAccessInvitationServiceClient();
$response = $customerUserAccessInvitationServiceClient->mutateCustomerUserAccessInvitation(
    MutateCustomerUserAccessInvitationRequest::build(
        $customerId,
        $customerUserAccessInvitationOperation
    )
);
printf(
    "Customer user access invitation with resource name '%s' was sent from customer "
    . "ID %d to email address '%s' with access role '%s'.%s",
    $response->getResult()->getResourceName(),
    $customerId,
    $emailAddress,
    $accessRole,
    PHP_EOL
);
      
```

### Python

```python
invitation_operation: CustomerUserAccessInvitationOperation = (
    client.get_type("CustomerUserAccessInvitationOperation")
)
invitation: CustomerUserAccessInvitation = invitation_operation.create
invitation.email_address = email_address
# The access_role field in the CustomerUserAccessInvitation message expects
# an AccessRoleEnum value (which is an int).
invitation.access_role = client.enums.AccessRoleEnum[access_role].value

response: MutateCustomerUserAccessInvitationResponse = (
    service.mutate_customer_user_access_invitation(
        customer_id=customer_id, operation=invitation_operation
    )
)
if response.result.multi_party_auth_review:
    # A multi-party auth review was triggered. See
    # FetchAndApprovePendingMultiPartyAuthReviews.cs for an example on how
    # to fetch and approve an MPA auth review.
    print(
        "A multi-party auth review was triggered. The MPA review resource "
        f"name is {response.result.multi_party_auth_review}. Ask a second "
        "administrator to approve this request to send user access invitation. "
        "See advanced_operations/fetch_and_approve_pending_multi_party_auth_reviews.py "
        "for an example on how to approve an MPA auth review using the API."
    )
else:
    # A multi-party auth review was not triggered.
    print(
        "Customer user access invitation was sent for "
        f"customer ID: '{customer_id}', "
        f"email address {email_address}, and "
        f"access role {access_role}. The invitation resource name is: "
        f"{response.result.resource_name}"
    )
      
```

### Ruby

```ruby
operation = client.operation.create_resource.customer_user_access_invitation do |inv|
  inv.email_address = email_address
  inv.access_role = access_role
end

# Issues a mutate request to get the response.
response = client.service.customer_user_access_invitation.mutate_customer_user_access_invitation(
  customer_id: customer_id,
  operation: operation,
)

# Prints out information of the created invitation.
puts "Customer user access invitation was sent for customerId = #{customer_id} " \
  "email address = '#{email_address}', " \
  "access role = '#{access_role}'."
      
```

### Perl

```perl
sub invite_user_with_access_role {
  my ($api_client, $customer_id, $email_address, $access_role) = @_;

  # Create the user access invitation.
  my $user_access_invitation =
    Google::Ads::GoogleAds::V26::Resources::CustomerUserAccessInvitation->new({
      emailAddress => $email_address,
      accessRole   => $access_role
    });

  # Create the user access invitation operation.
  my $invitation_operation =
    Google::Ads::GoogleAds::V26::Services::CustomerUserAccessInvitationService::CustomerUserAccessInvitationOperation
    ->new({create => $user_access_invitation});

  # Send the user access invitation.
  my $invitation_response =
    $api_client->CustomerUserAccessInvitationService()->mutate({
      customerId => $customer_id,
      operation  => $invitation_operation
    });

  if (not $invitation_response->{result}{multiPartyAuthReview}) {
    printf "Customer user access invitation was sent for customerId = %d " .
      "to email address = '%s' and access role = '%s'. " .
      "The invitation resource name is '%s'.\n",
      $customer_id, $email_address, $access_role,
      $invitation_response->{result}{resourceName};
  } else {
    printf "A multi-party auth review was triggered. The MPA review " .
      "resource name is '%s'. Ask a second administrator to approve this " .
      "request to send user access invitation. See " .
      "fetch_and_approve_pending_multi_party_auth_reviews.pl for an example " .
      "on how to approve an MPA auth review using the API.\n",
      $invitation_response->{result}{multiPartyAuthReview};
  }

  return 1;
}
      
```

### curl

```console
# This code example sends an invitation email to a user.
#
# The invitation is to manage a customer account with a desired access role.
#
# Variables:
#   API_VERSION,
#   CUSTOMER_ID,
#   MANAGER_CUSTOMER_ID,
#   OAUTH2_ACCESS_TOKEN:
#     See https://developers.google.com/google-ads/api/rest/auth#request_headers
#     for details.
#
#   EMAIL_ADDRESS: The email address of the user to invite.
curl -f --request POST \
"https://googleads.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/customerUserAccessInvitations:mutate" \
--header "Content-Type: application/json" \
--header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \
--header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \
--data @- <<EOF
{
  "operation": {
    "create": {
      "emailAddress": "${EMAIL_ADDRESS}",
      "accessRole": "ADMIN"
    }
  }
}
EOF
      
```

<br />

## Revoke invitations

You can revoke a pending invitation by executing a `remove` operation with the
`MutateCustomerUserAccessInvitation` method of the
[`CustomerUserAccessInvitationService`](https://developers.google.com/google-ads/api/reference/rpc/v26/CustomerUserAccessInvitationService.md.txt), passing the resource name of the
invitation to remove.

## Retrieve user invitations

You can retrieve the list of pending user invitations by building a
[Google Ads Query Language](https://developers.google.com/google-ads/api/docs/query/overview.md.txt) statement to query all the
[`CustomerUserAccessInvitation`](https://developers.google.com/google-ads/api/reference/rpc/v26/CustomerUserAccessInvitation.md.txt) entities associated with a customer
ID. Here is a typical query:

```sql
SELECT
  customer_user_access_invitation.invitation_id,
  customer_user_access_invitation.email_address,
  customer_user_access_invitation.access_role,
  customer_user_access_invitation.invitation_status,
  customer_user_access_invitation.creation_date_time
FROM customer_user_access_invitation
```

> [!NOTE]
> **Note:** If a user invitation is pending a multi-party approval, then it won't show up when retrieving user invitations using the [`GoogleAdsService.Search`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/Search.md.txt) or [`GoogleAdsService.SearchStream`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/SearchStream.md.txt) method.

You can add additional filtering conditions to retrieve subsets of invitations.
For example, a common use case is to retrieve the list of pending user
invitations by filtering for
`customer_user_access_invitation.invitation_status = PENDING`.