

# Custom domain names for private APIs in API Gateway
<a name="apigateway-private-custom-domains"></a>

You can create a custom domain name for your private APIs. Use a private custom domain name to provide API callers with a simpler and more intuitive URL. With a private custom domain name, you can reduce complexity, configure security measures during the TLS handshake, and control the certificate lifecycle of your domain name using Amazon Certificate Manager (ACM). For more information, see [Securing your certificate's private key for your custom domain name](#apigateway-private-custom-domains-secure-certificate-private-key).

Custom domain names for private APIs don’t need to be unique across multiple accounts. You can create `example.private.com` in account 111122223333 and in account 555555555555, as long as your ACM certificate covers the domain name. To identify a private custom domain name, use the private custom domain name ARN. This identifier is unique to private custom domain names.

When you create a private custom domain name in API Gateway, you're an *API provider*. You can provide your private custom domain name to other Amazon Web Services accounts using API Gateway or Amazon Resource Access Manager (Amazon RAM).

When you invoke a private custom domain name, you're an *API consumer*. You can consume a private custom domain name from your own Amazon Web Services account or from another Amazon Web Services account.

When you consume a private custom domain name, you create a domain name access association between a VPC endpoint and a private custom domain name. With a domain name access association, API consumers can invoke your private custom domain name while isolated from the public internet. For more information, see [Tasks of API providers and API consumers for custom domain names for private APIs](apigateway-private-custom-domains-associations.md).

## Securing your certificate's private key for your custom domain name
<a name="apigateway-private-custom-domains-secure-certificate-private-key"></a>

When you request an SSL/TLS certificate using ACM to create your custom domain name for private APIs, ACM generates a public/private key pair. When you import a certificate, you generate the key pair. The public key becomes part of the certificate. To safely store the private key, ACM creates another key using Amazon KMS, called the KMS key, with the alias **aws/acm**. Amazon KMS uses this key to encrypt your certificate’s private key. For more information, see [Data protection in Amazon Certificate Manager](https://docs.amazonaws.cn/acm/latest/userguide/data-protection.html) in the *Amazon Certificate Manager User Guide*.

API Gateway uses Amazon TLS Connection Manager, a service that is only accessible to Amazon Web Services services, to secure and use your certificate's private keys. When you use your ACM certificate to create a API Gateway custom domain name, API Gateway associates your certificate with Amazon TLS Connection Manager. We do this by creating a grant in Amazon KMS against your Amazon managed key. This grant allows TLS Connection Manager to use Amazon KMS to decrypt your certificate's private key. TLS Connection Manager uses the certificate and the decrypted (plaintext) private key to establish a secure connection (SSL/TLS session) with clients of API Gateway services. When the certificate is disassociated from a API Gateway service, the grant is retired. For more information, see [Grants](https://docs.amazonaws.cn/kms/latest/developerguide/grants.html) in the *Amazon Key Management Service Developer Guide*.

For more information, see [Data encryption at rest in Amazon API Gateway](data-protection-encryption.md#data-protection-at-rest).

## Considerations for private custom domain names
<a name="apigateway-private-custom-domains-considerations"></a>

The following considerations might impact your use of private custom domain names:
+ It takes about 15 minutes for API Gateway to provision your private custom domain name.
+ If you update your ACM certificate, it takes about 15 minutes for API Gateway to complete the update. During this time, your domain name is in the `UPDATING` state, and you can still access it.
+ To invoke a private custom domain name, you must create a domain name access association. After you create a domain name access association, it takes about 15 minutes to be ready.
+ The private custom domain name ARN contains the *account-id* and the *domain-name-id*. When you create a domain name, API Gateway uses the ARN format of `arn:partition:apigateway:region::/domainnames/domain-name`. When you access a private custom domain name, you use the ARN format of `arn:partition:apigateway:region:account-id:/domainnames/domain-name+domain-name-id`. 

  You might need to modify your IAM permissions to allow access to a private domain name after you create it.
+ You can't invoke private custom domain names with the same name from the same VPC endpoint. For example, if you wanted to invoke `arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234` and `arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+xyz000`, associate each private custom domain name with a different VPC endpoint.
+ Wildcard certificates are supported, such as a certificate for `*.private.example.com`.
+ Wildcard custom domain names aren't supported.
+ Only RSA certificates with a 2048-bit key length and ECDSA certificates with 256-bit and 384-bit key lengths are supported.
+ You can't set the IP address type for private APIs to only allow IPv4 addresses to invoke your private API. Only dualstack is supported. For more information, see [IP address types for REST APIs in API Gateway](api-gateway-ip-address-type.md).
+ To send traffic using your private API, you can use all IP address types supported by Amazon VPC. You can send dualstack and IPv6 traffic by configuring the settings on your VPC endpoint. You can't modify this using API Gateway. For more information, see [Add IPv6 support for your VPC](https://docs.amazonaws.cn/vpc/latest/userguide/vpc-migrate-ipv6-add.html).
+ Multi-level base path mapping, such as mapping your private API to `/developers/feature`, isn't supported, but you can use a routing rule to create a multi-level path condition. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).
+ You can’t set a minimum TLS version for your private custom domain name. All private custom domain names have the security policy of `TLS-1-2`.
+ You can use VPC endpoint policy to control access to a private custom domain name. For more information, see examples 4 and 5 in [Use VPC endpoint policies for private APIs in API Gateway](apigateway-vpc-endpoint-policies.md).
+ You must create a separate resource policy for your private API and for your private custom domain name. To invoke a private custom domain name, an API consumer needs access from the private custom domain name resource policy, the private API resource policy, and any VPC endpoint policies or authorization on the private API.

## Considerations for using private custom domain names with other API Gateway resources
<a name="apigateway-private-custom-domains-considerations-for-migration"></a>

The following considerations might impact how you use private custom domain names with other API Gateway resources:
+ You can't send traffic from a private custom domain name to a public API.
+ When a private API is mapped to a private custom domain name, you can't change the API's endpoint type. 
+ You can't migrate a public custom domain name to a private custom domain name.
+ If you have a VPC endpoint that you use to access a public custom domain name, don't use it to create a domain name access association with a private custom domain name.

## Differences between private custom domain names and public custom domain names
<a name="apigateway-private-custom-domains-public-differences"></a>

The following describes the differences between private and public custom domain names:
+ Private custom domain names don’t need to be unique across multiple accounts.
+ A private domain name has a domain name ID. This ID uniquely identifies a private custom domain name and isn't generated for public custom domain names.
+ When you use the Amazon CLI to update or delete your private custom domain name, you must provide the domain name ID. If you have a private custom domain name called `example.com` and a public custom domain name called `example.com` and you don't provide the domain name ID, API Gateway will modify or delete your public custom domain name.

## Next steps for custom domain names for private APIs
<a name="apigateway-private-custom-domains-next-steps"></a>

For information about the tasks of an API provider and an API consumer, see [Tasks of API providers and API consumers for custom domain names for private APIs](apigateway-private-custom-domains-associations.md).

For instructions on creating a private custom domain name that you can invoke in your own Amazon Web Services account, see [Tutorial: Create and invoke a custom domain name for private APIs](apigateway-private-custom-domains-tutorial.md).

For instructions on providing another Amazon Web Services account access to your private custom domain name, see [API provider: Share your private custom domain name using Amazon RAM](apigateway-private-custom-domains-provider-share.md). For instructions on associating your VPC endpoint with a private custom domain name in another Amazon Web Services account, see [API consumer: Associate your VPC endpoint with a private custom domain name shared with you](apigateway-private-custom-domains-consumer-create.md).

# Tasks of API providers and API consumers for custom domain names for private APIs
<a name="apigateway-private-custom-domains-associations"></a>

When you create a private custom domain name, you're an *API provider*. When you invoke a private custom domain name, you're an *API consumer*. You can consume a private custom domain name from your own Amazon Web Services account or from another Amazon Web Services account.

The following section explains the tasks required by the API provider and API consumer to use a private custom domain name. If you want to invoke a private custom domain name in your own Amazon Web Services account, you are both the API provider and the API consumer. If you want to invoke a private custom domain in another Amazon Web Services account, depending on the trust relationship between the API provider and API consumer in Amazon Organizations, Amazon RAM might complete some tasks for you.

## Tasks of an API provider
<a name="apigateway-private-custom-domains-associations-provider"></a>

API providers create private APIs and map them to custom domain names.

 API providers manage two resource policies to protect their private custom domain names. The first policy is for the `execute-api` service and controls which VPC endpoints can invoke your private custom domain name. In the private custom domain name configuration, it's called the `policy`.

The second policy is for the Amazon API Gateway Management service and controls which VPC endpoints in other Amazon Web Services accounts can form a domain name access association with your private custom domain name. A VPC endpoint needs to form a domain name access association with a private custom domain name to invoke it. In the private custom domain name configuration, it's the `managementPolicy`. You can use Amazon RAM or API Gateway to update this policy. If you don't plan on allowing VPC endpoints in other Amazon Web Services accounts to invoke your custom domain name, you don't edit the `managementPolicy`.

If you are an API provider, you must do the following:

1. Create a private API.

1. Update your private API's `policy` to grant your VPC endpoint access to your private API.

1. Create a private custom domain name.

1. Update your private custom domain name's `policy` to grant your VPC endpoint access to your private custom domain name.

1. Create a base path mapping or a routing rule to send traffic from your private API to your private custom domain name. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

If you want to allow API consumers in other Amazon Web Services accounts to access your private custom domain name, do the following:

1. Update the `managementPolicy` of your private custom domain name to allow API consumers in other accounts to associate their VPC endpoints with your private custom domain name. You can do this using the following methods:  
**Amazon RAM**  
With Amazon RAM, if the API provider and the API consumer are in the same organization using Amazon Organizations, the resource share between provider and consumer is automatically accepted. Otherwise, you should wait until the API consumer accepts the resource share. **We recommend that you use Amazon RAM to share your private custom domain name.**   
**API Gateway**  
With API Gateway, only the Amazon CLI is supported. You must update your private custom domain name using a patch operation and provide your own policy document for the `managementPolicy`.

1. Update the `policy` of your private custom domain name and any private APIs mapped to it to grant access to the API consumer's VPC endpoint.

For instructions on how to provide your API to another Amazon Web Services account, see [API provider: Share your private custom domain name using Amazon RAM](apigateway-private-custom-domains-provider-share.md). 

## Tasks of an API consumer
<a name="apigateway-private-custom-domains-associations-consumer"></a>

API consumers associate their VPC endpoints with a domain name ARN to invoke a private custom domain name. API consumers don't need to create an API Gateway API.

If you are an API consumer, do the following:

1. Create a VPC endpoint with private DNS enabled in Amazon VPC.

1. (Optional - if Amazon RAM is used) Accept a private custom domain resource share in Amazon RAM within **12 hours** of the resource share. If you and the API provider are in the same organization, the resource share is automatically accepted.

1. Get the private custom domain name ARN. Because the private custom domain name URL is not unique, you use the private custom domain name ARN to form the domain name access association between your VPC endpoint and the private custom domain name. You can use Amazon RAM to retrieve the private custom domain name ARN.

1. Associate the private custom domain ARN with your VPC endpoint in API Gateway. This creates a secure connection between your VPC endpoint and the private custom domain name. Traffic doesn't leave the Amazon network.

1. Wait for the API provider to grant your VPC endpoint access to the private custom domain name and any private APIs mapped to the private custom domain name. If you're both the API provider and the API consumer, you grant your own VPC endpoint invoke access.

1. Create a Route 53 Private Hosted Zone and a Route 53 record to resolve the private custom domain name in Route 53.

For instructions on how to consume an API in another Amazon Web Services account, see [API consumer: Associate your VPC endpoint with a private custom domain name shared with you](apigateway-private-custom-domains-consumer-create.md).

# Tutorial: Create and invoke a custom domain name for private APIs
<a name="apigateway-private-custom-domains-tutorial"></a>

In this tutorial, you create a private custom domain name that you can invoke in a VPC in your own account. To accomplish this, you are the API provider and the API consumer. You need an existing private API and VPC endpoint to complete this tutorial. If you have a VPC endpoint that you use to access a public custom domain name, don't use it for this tutorial or to create any domain name access associations.

## Step 1: Create a private custom domain name
<a name="apigateway-private-custom-domains-provider-create-domain"></a>

You create your private custom domain name by specifying the domain name, the ACM certificate, and the policy for the `execute-api` service to control which VPC endpoints can invoke it.

------
#### [ Amazon Web Services Management Console ]

**To create a private custom domain name**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose **Add domain name**.

1. For **Domain name**, enter a domain name. 

   Your ACM certificate must cover this domain name, but the domain name doesn't need to be unique.

1. Select **Private**.

1. For **Routing mode**, choose **API mappings only**.

1. For **ACM certificate**, select a certificate.

1. Choose **Add domain name**.

API Gateway provisions a domain name with a `deny` all resource policy. This is the resource policy for the `execute-api` service. You need to update this resource policy to grant access to your VPC endpoints to invoke your private custom domain name.

**To update your resource policy**

1. Choose the **Resource policy** tab, and then choose **Edit resource policy**.

1. Enter the following resource policy in the code editor. Replace the VPC endpoint *vpce-abcd1234efg* with your own VPC endpoint ID.  
****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Principal": "*",
               "Action": "execute-api:Invoke",
               "Resource": [
                   "execute-api:/*"
               ]
           },
           {
               "Effect": "Deny",
               "Principal": "*",
               "Action": "execute-api:Invoke",
               "Resource": [
                   "execute-api:/*"
               ],
               "Condition" : {
                   "StringNotEquals": {
                       "aws:SourceVpce": "vpce-abcd1234"
                   }
               }
           }
       ]
   }
   ```

1. Choose **Save changes**.

------
#### [ Amazon CLI ]

When you create a private custom domain name using the Amazon CLI, you provide a resource policy for the `execute-api` service to grant access to VPC endpoints to invoke your private custom domain name, using the `--policy file://policy.json` parameter. You can modify this policy later.

For this example, you'll attach the following resource policy as the `policy` by loading parameters from a file. Copy and save this file as `policy.json`. This policy only allows incoming traffic to a private custom domain name from the VPC endpoint * `vpce-abcd1234efg`*:

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-abcd1234"
                }
            }
        }
    ]
}
```

The following [create-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/create-domain-name.html) command creates a private custom domain name:

```
aws apigateway create-domain-name \
    --domain-name 'private.example.com' \
    --certificate-arn 'arn:aws:acm:us-west-2:111122223333:certificate/a1b2c3d4-5678-90ab-cdef' \
    --security-policy 'TLS_1_2' \
    --endpoint-configuration '{"types":["PRIVATE"]}' \
    --policy file://policy.json
```

The output will like the following.

```
{
    "domainName": "private.example.com",
    "domainNameId": "abcd1234",
    "domainNameArn": "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
    "certificateArn": "arn:aws:acm:us-west-2:111122223333:certificate/a1b2c3d4-5678-90ab-cdef",
    "certificateUploadDate": "2024-09-10T10:31:20-07:00",
    "endpointConfiguration": {
        "types": [
            "PRIVATE"
        ]
    },
    "domainNameStatus": "AVAILABLE",
    "securityPolicy": "TLS_1_2",
    "routingMode" : "API_MAPPING_ONLY",
    "policy": "..."
}
```

------

## Step 2: Create a base path mapping to map your private API to your private custom domain name
<a name="apigateway-private-custom-domains-base-path-mapping"></a>

After you create your private custom domain name, you map a private API to it. A base path mapping makes an API accessible through the combination of the private custom domain name and an associated base path. We recommend that you use a single private custom domain name as the hostname of multiple private APIs.

All API providers need to create a base path mapping, even if you don't plan on invoking your own API. You also need to grant access for VPC endpoints to invoke any private APIs that you map to your private custom domain name.

------
#### [ Amazon Web Services Management Console ]

**To create a base path mapping**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose a private custom domain name.

1. On the **API mappings** tab, choose **Configure mappings**.

1. Choose **Add new mapping**.

1. Enter an **API**, a **Stage**, and optionally a **Path**.

1. Choose **Save**.

------
#### [ Amazon CLI ]

The following [create-base-path-mapping](https://docs.amazonaws.cn/cli/latest/reference/apigateway/create-base-path-mapping.html) command creates a mapping between a private API and a private custom domain name:

```
aws apigateway create-base-path-mapping \
    --domain-name-id abcd1234 \
    --domain-name 'private.example.com' \
    --rest-api-id a1b2c3 \
    --stage prod \
    --base-path v1
```

The output will look like the following.

```
{
    "basePath": "v1",
    "restApiId": "a1b2c3",
    "stage": "prod"
}
```

------

For more flexibility on how you route traffic to your APIs, you can change the routing mode to `ROUTING_RULE_ONLY` or `ROUTING_RULE_THEN_API_MAPPING` and create a routing rule. For more information, see [Send traffic to your APIs through your custom domain name in API Gateway](rest-api-routing-mode.md).

**Note**  
If you want other Amazon Web Services accounts to invoke your private custom domain name, after you complete this tutorial, follow the steps in [API provider: Share your private custom domain name using Amazon RAM](apigateway-private-custom-domains-provider-share.md).

## Step 3: Create a domain name access association between your custom domain name and a VPC endpoint
<a name="apigateway-private-custom-domains-provider-associate-with-vpce"></a>

Next, you create a domain name access association between your private custom domain name and your VPC endpoint. Your VPC endpoint uses the domain name access association to invoke your private custom domain name while isolated from the public internet.

------
#### [ Amazon Web Services Management Console ]

**To create a domain name access association**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose a private custom domain name.

1. In the **Resource sharing** tab, for **Domain name access associations**, choose **Create domain name access association**.

1. For **Domain name ARN**, select your domain name.

1. For **VPC endpoint ID**, select the VPC endpoint ID you provided access to in step 1.

1. Choose **Domain name access association**.

You can also create your domain name access association using the **Domain name access associations** page of the console.

------
#### [ Amazon CLI ]

The following `create-domain-name-access-association` command creates a domain name access association between your private custom domain name and your VPC endpoint.

```
aws apigateway create-domain-name-access-association \
    --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234 \
    --access-association-source vpce-abcd1234efg \
    --access-association-source-type VPCE \
    --region us-west-2
```

The output will look like the following.

```
{
    "domainNameAccessAssociationARN": "arn:aws:apigateway:us-west-2:111122223333:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg",
    "accessAssociationSource": "vpce-abcd1234efg",
    "accessAssociationSourceType": "VPCE",
    "domainNameARN" : "arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234"
}
```

------

After you create your domain name access association, it takes about 15 minutes to be ready. While you wait, you can proceed with the following steps.

## Step 4: Create a Route 53 hosted zone
<a name="apigateway-private-custom-domains-provider-create-route-53-private-hosted-zone"></a>

After you update your resource policy and associate your private custom domain name with your VPC endpoint, you create a private hosted zone in Route 53 to resolve your custom domain name. A hosted zone is container that holds information about how you want to route traffic for a domain within one or more VPCs without exposing your resources to the internet. For more information, see [Working with private hosted zones](https://docs.amazonaws.cn/Route53/latest/DeveloperGuide/hosted-zones-private.html).

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Creating a private hosted zone](https://docs.amazonaws.cn/Route53/latest/DeveloperGuide/hosted-zone-private-creating.html) in the *Amazon Route 53 Developer Guide*.

For **Name**, use the name of your private custom domain name. For **VPC ID**, use the VPC containing the VPC endpoint that you used in the previous steps.

------
#### [ Amazon CLI ]

The following [create-hosted-zone](https://docs.amazonaws.cn/cli/latest/reference/route53/create-hosted-zone.html) command creates a private hosted zone:

```
aws route53 create-hosted-zone --name private.example.com \
    --caller-reference 2014-04-01-18:47 \
    --hosted-zone-config Comment="command-line version",PrivateZone=true \
    --vpc VPCRegion=us-west-2,VPCId=vpc-abcd1234
```

The output contains the hosted zone ID. You use the hosted zone ID in the following steps.

------

## Step 5: Create a Route 53 DNS record
<a name="apigateway-private-custom-domains-provider-create-route-53-record"></a>

After you create the hosted zone, you create an record to resolve your private custom domain name. You use the hosted zone ID you created in the previous step. In this example, you create an A record type. If you are using IPv6 for your VPC endpoint, create an AAAA record type. If you are using dualstack for your VPC endpoint, create both an AAAA and an A record type.

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Routing traffic to an Amazon API Gateway API by using your domain name](https://docs.amazonaws.cn/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

Use **Quick create** and turn on **Alias**. For endpoint, use the VPC endpoint DNS name.

------
#### [ Amazon CLI ]

To configure your DNS records to map the private custom domain name to its hostname of the given hosted zone ID, you create a JSON file that contains the configuration for setting up a DNS record for the private domain name.

The following `setup-dns-record.json` shows how to create a DNS `A` record to map a private custom domain name to its private hostname. You provide the `DNSName` of your VPC DNS ID, and the hosted zone ID you created in the previous step.

```
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "private.example.com",
        "Type": "A",
        "AliasTarget": {
          "DNSName": "vpce-abcd1234.execute-api.us-west-2.vpce.amazonaws.com",
          "HostedZoneId": "Z2OJLYMUO9EFXC",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}
```

The following [change-resource-record-sets](https://docs.amazonaws.cn/cli/latest/reference/route53/change-resource-record-sets.html) command creates a DNS record for your private custom domain name:

```
aws route53 change-resource-record-sets \
    --hosted-zone-id ZABCDEFG1234 \
    --change-batch file://path/to/your/setup-dns-record.json
```

Replace the`hosted-zone-id` with the Route 53 Hosted Zone ID of the DNS record set in your account. The `change-batch` parameter value points to a JSON file.

------

If you don't plan on invoking your own private custom domain name, after you confirm your private custom domain name is working, you can delete these resources.

## Step 6: Invoke your private custom domain name
<a name="apigateway-private-custom-domains-tutorial-invoke"></a>

You can now invoke your private custom domain name in your own Amazon Web Services account. In your VPC, use the following curl command to access your private custom domain name.

```
curl https://private.example.com/v1
```

For more information about other ways to invoke your private API, see [Invoke a private API using a custom domain name](apigateway-private-api-test-invoke-url.md#apigateway-private-custom-domains-provider-invoke).

## Step 7: Clean up
<a name="apigateway-private-custom-domains-cleanup"></a>

To prevent unnecessary costs, delete the association between your VPC endpoint and your private custom domain name, and then delete your private custom domain name.

------
#### [ Amazon Web Services Management Console ]

**To delete the domain name access association**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Domain name access associations**.

1. Select your domain name access association, and then choose **Delete**.

1. Confirm your choice, and then choose **Delete**.

After you delete your domain name access association, you can delete your private custom domain name.

**To delete your private custom domain name**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose your private custom domain name.

1. Choose **Delete**.

1. Confirm your choice, and then choose **Delete**.

If necessary, you can also delete your VPC endpoint. For more information, see [Delete an interface endpoint](https://docs.amazonaws.cn/vpc/latest/privatelink/delete-interface-endpoint.html).

------
#### [ Amazon CLI ]

**To clean up**

1. The following `delete-access-association` command deletes the domain name access association:

   ```
   aws apigateway delete-domain-name-access-association \
       --domain-name-access-association-arn 'arn:aws:apigateway:us-west-2:111122223333:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg' \
       --region us-west-2
   ```

1. The following `delete-domain-name` command deletes your private custom domain name. This command also removes all base path mappings.

   ```
   aws apigateway delete-domain-name \
       --domain-name test.private.com \
       --domain-name-id abcd1234
   ```

If necessary, you can also delete your VPC endpoint. For more information, see [Delete an interface endpoint](https://docs.amazonaws.cn/vpc/latest/privatelink/delete-interface-endpoint.html).

------

## Best practices
<a name="apigateway-private-custom-domains-best-practices"></a>

We recommend that you use the following best practices when you create your private custom domain name:
+ Use base path mapping or routing rules to send traffic from one private custom domain name to multiple private APIs.
+ When a VPC endpoint no longer needs access to a private custom domain name, delete the association. In addition, remove the VPC endpoint from the `policy` for the `execute-api` service for the private custom domain. 
+ Configure at least two Availability Zones per VPC endpoint.
+ Disable the default endpoint. We recommend that you disable the default endpoint to allow your API consumers to only call your API from the custom domain name. For more information, see [Disable the default endpoint for REST APIs](rest-api-disable-default-endpoint.md).
+ We recommend that you provision a Route 53 private hosted zone and an A-type record when you set up your private custom domain name. If you don't plan on invoking your own private custom domain name, you can delete these resources later.

# Working with cross-account private custom domain names
<a name="apigateway-private-custom-domains-other-accounts"></a>

This section explains how to work with cross-account private custom domain names. You can provide a private custom domain name to another Amazon Web Services account and use another Amazon Web Services account to invoke a private custom domain name.

You can share your private custom domain name to another Amazon Web Services account using Amazon Resource Access Manager or API Gateway. Amazon Resource Access Manager (Amazon RAM) helps you securely share your resources across Amazon Web Services accounts and within your organization or organizational units (OUs). For more information, see [What is Amazon Resource Access Manager](https://docs.amazonaws.cn/ram/latest/userguide/what-is.html).

For instructions on how to share a private custom domain name with another Amazon Web Services account using Amazon RAM, see [API provider: Share your private custom domain name using Amazon RAM](apigateway-private-custom-domains-provider-share.md).

For instructions on how to share a private custom domain name with another Amazon Web Services account using API Gateway, see [API provider: Share your private custom domain name using the API Gateway Amazon CLI](apigateway-private-custom-domains-provider-share-cli.md).

For instructions on how to consume a private custom domain name in another Amazon Web Services account, see [API consumer: Associate your VPC endpoint with a private custom domain name shared with you](apigateway-private-custom-domains-consumer-create.md).

## Best practices for working with cross-account private custom domain names
<a name="apigateway-private-custom-domains-other-accounts-best-practices"></a>

We recommend the following best practices for working with cross-account private custom domain names:
+ Use Amazon RAM to share your private custom domain names. When you use Amazon RAM, you can reduce operational overhead and you don't have to create a `managementPolicy` for the Amazon API Gateway Management service.
+ Use the `resource-owner` parameter when you list your private custom domain names or domain name access associations. Use the `resource-owner` parameter to only list the resources owned by you or by other Amazon Web Services accounts.

  The following example shows how to get all domain name access associations that you own:

  ```
  aws apigateway get-domain-name-access-associations --resource-owner SELF
  ```

  Use `--resource-owner OTHER_ACCOUNTS` to list all the domain name access associations that other accounts have formed with your private custom domain name.

# API provider: Share your private custom domain name using Amazon RAM
<a name="apigateway-private-custom-domains-provider-share"></a>

You can provide API consumers in other Amazon Web Services accounts access to your private custom domain name. In this section, you learn how to share your private custom domain name using Amazon RAM and how to control access to your private custom domain name.

## Considerations for sharing your private custom domain name
<a name="apigateway-private-custom-domains-provider-share-considerations"></a>

The following considerations might impact how you provide access to your private custom domain name using Amazon RAM. To learn how to share your private custom domain name without using Amazon RAM, see [API provider: Share your private custom domain name using the API Gateway Amazon CLI](apigateway-private-custom-domains-provider-share-cli.md).
+ Private custom domain names are shared at the Amazon Web Services Region level. Both the private custom domain name and the VPC endpoint need to be in the same Amazon Web Services Region.
+ You can use one resource share with multiple principals, and after you create the resource share, you can add more principals to it. We recommend that when possible, you reuse your resource share.
+ You always need to grant the API consumer's VPC endpoint access to invoke your private custom domain name and any private APIs mapped to it.
+ If the API consumer and API provider are in the same organization using Amazon Organizations, the resource share is automatically accepted. You still need to create the resource share using Amazon RAM.
+ If the API consumer and API provider are in the same organization using Amazon Organizations and resource sharing within your organization is enabled, any principals in the organization that you share with are automatically granted access to the resource shares. There is no need for an invitation and you can skip the resource share.
+ If the API consumer doesn't accept the resource share within **12 hours**, the API provider must share the resource again.
+ After you create the resource share, Amazon RAM updates the `managementPolicy` for the Amazon API Gateway Management service for your private custom domain name to prevent access to principals without explicit `allow` access. For more information, see [Determining whether a request is allowed or denied within an account](https://docs.amazonaws.cn//IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow) in the IAM User Guide.

  The updated `managementPolicy` will look like the following:

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Id": "abcd1234-1234-abcd-abcd-1234abcdefg",
      "Statement": [
          {
              "Sid": "APIGatewayPrivateDomainNameManagementPolicyDefaultPermission-org",
              "Effect": "Allow",
              "Principal": "*",
              "Action": "apigateway:CreateAccessAssociation",
              "Resource": "arn:aws-cn:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
              "Condition": {
                  "StringEquals": {
                      "aws:PrincipalOrgID": "o-1234abcd"
                  },
                  "StringNotEquals": {
                      "aws:PrincipalAccount": "111122223333"
                  }
              }
          }
      ]
  }
  ```

------

  Amazon RAM has prevented principals without explicit `allow` access to create access associations with your private custom domain name, by adding the following:

  ```
  "StringNotEquals": {
      "aws:PrincipalAccount": "111122223333"
  }
  ```

  You can still use the principal in the Amazon Web Services account who created the private custom domain name to create domain name access associations.

## Allow other accounts to create domain name access associations with your private custom domain name
<a name="apigateway-private-custom-domains-provider-management-policy-update"></a>

First, you grant access to another Amazon Web Services account to create domain name access associations with your private custom domain name.

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Creating a resource share in Amazon RAM](https://docs.amazonaws.cn/ram/latest/userguide/working-with-sharing-create.html) in the *Amazon RAM User Guide*.

For **Select resource type**, choose **API Gateway Private Custom Domains**.

------
#### [ Amazon CLI ]

The following [create-resource-share](https://docs.amazonaws.cn/cli/latest/reference/ram/create-resource-share.html) creates a resource share for your private custom domain name. It can take a few minutes for the resource and principal associations to complete. For principals, provide an account ID or an Organizations ID, such as `arn:aws:organizations::123456789012:organization/o-1234abcd`. You can provide multiple principals for your resource share.

```
aws ram create-resource-share \
    --region us-west-2 \
    --name privateCustomDomain-resource-share \
    --permission-arns arn:aws:ram::aws:permission/APIGatewayPrivateDomainNameManagementPolicyDefaultPermission \
    --resource-arns arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234 \
    --principals 222222222222
```

------

After you have provided access to another Amazon Web Services account, API consumers in that account must create a domain name access association between their VPC endpoint with your private custom domain name. You can't create the domain name access association for them. For more information, see [Associate your VPC endpoint with a shared private custom domain name](apigateway-private-custom-domains-consumer-create.md#apigateway-private-custom-domains-consumer-associate).

## Allow other accounts to invoke your private custom domain name
<a name="apigateway-private-custom-domains-provider-policy-update"></a>

Next, you grant access for the API consumer's VPC endpoint to invoke your private custom domain name and any private APIs mapped to it.

------
#### [ Amazon Web Services Management Console ]

**To allow VPC endpoints in other accounts to invoke your private custom domain name**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose the private custom domain name that you shared with other Amazon Web Services accounts.

1. On the **Resource policy** tab, choose **Edit resource policy**.

1. Add the VPC endpoint ID of the API consumer to your resource policy.

   You can find the VPC endpoint ID of the API consumer on the **Domain name access associations** section of the **Resource sharing** tab on the **Domain details** page of your private custom domain name.

1. Choose **Save changes**.

------
#### [ Amazon CLI ]

The following `policy` for the `execute-api` service allows incoming traffic to a private custom domain name from both VPC endpoint `vpce-abcd1234efg` and `vpce-xyz000abc`.

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ]
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": [
                    "vpce-abcd1234",
                    "vpce-xyzz0000"
                    ]
                }
            }
        }
    ]
}
```

The following [update-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/update-domain-name.html) command uses a patch operation to update the `policy` for a private custom domain name:

```
aws apigateway update-domain-name
    --domain-name private.example.com \
    --domain-name-id abcd1234 \
    --patch-operations op=replace,path=/policy,value='"{\"Version\": \"2012-10-17\",		 	 	 \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"]},{\"Effect\": \"Deny\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"],\"Condition\":{\"StringNotEquals\":[\"vpce-abcd1234efg\", \"vpce-xyz000abc\"]}}}]}"
```

------

# API provider: Stop sharing a private custom domain name using Amazon RAM
<a name="apigateway-private-custom-domains-provider-stop-sharing"></a>

To stop sharing your private custom domain name, first you stop the API consumer from creating more domain name access associations by dissociating the resource share. Then, you reject the domain name access association and remove the API consumer's VPC endpoint from your `policy` for the `execute-api` service. The API consumer can then delete their domain name access association.

## Stop sharing your private custom domain name
<a name="apigateway-private-custom-domains-provider-dissociate-ram"></a>

First, you stop the resource share using Amazon RAM.

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Update a resource share in Amazon RAM](https://docs.amazonaws.cn/ram/latest/userguide/working-with-sharing-update.html).

------
#### [ Amazon CLI ]

The following [disassociate-resource-share](https://docs.amazonaws.cn/cli/latest/reference/ram/disassociate-resource-share.html) disassociates a resource share for your private custom domain name.

```
aws ram disassociate-resource-share \
    --region us-west-2 \
    --resource-arns arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234 \
    --principals 222222222222
```

------

## Reject the domain name access association
<a name="apigateway-private-custom-domains-provider-reject"></a>

After you stop sharing your resource using Amazon RAM, you reject the domain name access association between a VPC endpoint in another account and your private custom domain name. 

**Note**  
You can't reject a domain name access association in your own account. To stop resource sharing, delete the domain name access association. For more information, see [Delete a domain name access association](apigateway-private-custom-domains-tutorial.md#apigateway-private-custom-domains-cleanup).

When you reject a domain name access association with a VPC endpoint, if an API consumer tries to call your private custom domain name, API Gateway rejects the call and returns a `403` status code.

------
#### [ Amazon Web Services Management Console ]

**To reject a domain name access association**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose the private custom domain name that you shared with other Amazon Web Services accounts.

1. On the **Resource sharing**, choose the domain name access association you want to reject.

1. Choose **Reject association**.

1. Confirm your choice, and then choose **Reject**.

------
#### [ Amazon CLI ]

The following `reject-domain-name-access-association` command rejects the domain name access association between the VPC endpoint and your private custom domain name:

```
aws apigateway reject-domain-name-access-association \
    --domain-name-access-association-arn arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg \
    --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234
```

------

## Deny the API provider access to invoke your private custom domain name
<a name="apigateway-private-custom-domains-provider-deny-access"></a>

After you reject the domain name access association, you remove the API consumer's VPC endpoint from your `policy` for the `execute-api` service.

------
#### [ Amazon Web Services Management Console ]

**To remove the API consumer's VPC endpoint from your resource policy**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Custom domain names**.

1. Choose the private custom domain name that you shared with other Amazon Web Services accounts.

1. On the **Resource policy** tab, choose **Edit**.

1. Remove the VPC endpoint from the policy.

1. Choose **Save changes**.

------
#### [ Amazon CLI ]

The following [update-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/update-domain-name.html) command uses a patch operation to update the `policy` for the `execute-api` service for a private custom domain name. This new `policy` removes an additional VPC endpoint ID added in [Allow other accounts to invoke your private custom domain name](apigateway-private-custom-domains-provider-share.md#apigateway-private-custom-domains-provider-policy-update):

```
aws apigateway update-domain-name
    --domain-name private.example.com \
    --domain-name-id abcd1234 \
    --patch-operations op=replace,path=/policy,value='"{\"Version\": \"2012-10-17\",		 	 	 \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"]},{\"Effect\": \"Deny\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\":[\"execute-api:/*\"],\"Condition\":{\"StringNotEquals\":{\"aws:SourceVpce\": \"vpce-abcd1234efg\"}}}]}"
```

------

The API consumer should then delete the domain name access association. You can't delete it for them. For more information, see [API consumer: Delete your domain name access association with a private custom domain name](apigateway-private-custom-domains-consumer-delete-domain-name-access-association.md).

# API provider: Share your private custom domain name using the API Gateway Amazon CLI
<a name="apigateway-private-custom-domains-provider-share-cli"></a>

You can share a private custom domain name using the API Gateway Amazon CLI, but we recommend that you use Amazon RAM to reduce your operational overhead. For instructions on how to use Amazon RAM to share your private custom domain name, see [API provider: Share your private custom domain name using Amazon RAM](apigateway-private-custom-domains-provider-share.md).

To share a private custom domain name using the API Gateway Amazon CLI, you grant other Amazon Web Services accounts access to create domain name access associations and invoke your private custom domain name. You do this by updating the `managementPolicy` for the API Gateway Management service and the `policy` for the `execute-api` service for your private custom domain name. You also need to grant access for the API consumer's VPC endpoint in the resource policy for any private APIs mapped to your private custom domain name.

The API consumer still needs to create a domain name access association in their own account between their VPC endpoint and your private custom domain name. You can't do this for them.

## Grant access to your private custom domain name
<a name="apigateway-private-custom-domains-provider-share-cli-allow"></a>

**To grant access to your private custom domain name**

1. To update the `managementPolicy` for the API Gateway Management service, you create a JSON file that contains the patch operation to update the policy. The following `patch-managementPolicy.json` replaces the current `managementPolicy` with an example policy that grants Amazon Web Services accounts 111122223333 and 444455556666 access to create domain name access associations with the private custom domain name `private.example.com`.

   ```
   [{
       "op": "replace",
       "path": "/managementPolicy",
       "value": "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"arn:aws:iam::111122223333:root\", \"arn:aws:iam::444455556666:root\"]},\"Action\":\"apigateway:CreateAccessAssociation\",\"Resource\":\"arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"}]}"
   }]
   ```

    The following [update-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/update-domain-name.html) command updates the `managementPolicy` using `patch-managementPolicy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-managementPolicy.json
   ```

   Once you grant access, you need to notify the API consumer that they can form the domain name access association. If you use Amazon RAM, Amazon RAM will do this step for you.

1. To update the `policy` for the `execute-api` service, you create a JSON file that contains the patch operation to update the policy. The following `patch-policy.json` replaces the current `policy` with an example policy that grants two VPC endpoints to invoke the private custom domain name `private.example.com`.

   ```
   [{
       "op": "replace",
       "path": "/policy",
       "value": "{\"Version\": \"2012-10-17\",		 	 	 \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\": \"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"},{\"Effect\": \"Deny\",\"Principal\": \"*\",\"Action\": \"execute-api:Invoke\",\"Resource\": \"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\",\"Condition\": {\"StringNotEquals\": {\"aws:SourceVpce\": [\"vpce-abcd1234\",\"vpce-xyzz0000\"]}}}]}"
   }]
   ```

    Use the following [update-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/update-domain-name.html) command to update the `policy` using `patch-policy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-policy.json
   ```

## Deny access to your private custom domain name
<a name="apigateway-private-custom-domains-provider-share-cli-deny"></a>

To stop sharing your private custom domain name, you need to reject the domain name access association between your private custom domain name and the API consumer's VPC endpoint.

**To deny access to your private custom domain name**

1. The following `reject-domain-name-access-association` command rejects the domain name access association.

   ```
   aws apigateway reject-domain-name-access-association \
       --domain-name-access-association-arn arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234 \
       --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234
   ```

1. Modify the `patch-managementPolicy.json` to remove access for the API provider's account to create a domain name access association with your private custom domain name. The following `patch-managementPolicy.json` removes one account from the `managementPolicy`:

   ```
   [{
        "op": "replace",
        "path": "/managementPolicy",
        "value": "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"apigateway:CreateAccessAssociation\",\"Resource\":\"arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"}]}"
   }]
   ```

   The following [update-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/update-domain-name.html) command to updates the `managementPolicy` using `patch-managementPolicy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-managementPolicy.json
   ```

1. Modify the `patch-policy.json` to remove access for the API provider's VPC endpoint to invoke your private custom domain name. The following `patch-policy.json` removes the VPC endpoint ID from the `policy`:

   ```
   [{
       "op": "replace",
       "path": "/policy",
       "value": "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"execute-api:Invoke\",\"Resource\":\"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\"},{\"Effect\":\"Deny\",\"Principal\":\"*\",\"Action\":\"execute-api:Invoke\",\"Resource\":\"arn:aws:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234\",\"Condition\":{\"StringNotEquals\":{\"aws:SourceVpce\":\"vpce-abcd1234\"}}}]}"
   }]
   ```

   The following [update-domain-name](https://docs.amazonaws.cn/cli/latest/reference/apigateway/update-domain-name.html) command updates the `policy` using `patch-policy.json`. 

   ```
   aws apigateway update-domain-name \
       --domain-name private.example.com \
       --domain-name-id abcd1234 \
       --patch-operations file://patch-policy.json
   ```

## Example policies used in this procedure
<a name="apigateway-private-custom-domains-provider-share-cli-policies"></a>

The following section shows the example policies used in the previous procedure.

The following example policy is for the `managementPolicy` for the Amazon API Gateway Management service. This policy grants Amazon Web Services accounts 111122223333 and 444455556666 access to create domain name access associations with the private custom domain name `private.example.com`. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "111122223333",
                    "444455556666"
                ]
            },
            "Action": "apigateway:CreateAccessAssociation",
            "Resource": "arn:aws-cn:apigateway:us-west-2:111122223333:/domainnames/private.example.com+a1b2c3"
        }
    ]
}
```

------

The following example policy is the policy for the `policy` for the `execute-api` service. This policy grants VPC endpoints `vpce-abcd1234` and `vpce-xyzz0000` access to invoke the private custom domain name.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws-cn:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234"
        },
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws-cn:execute-api:us-west-2:111122223333:/domainnames/private.example.com+abcd1234",
            "Condition": {
                "StringNotEquals": {
                    "aws:SourceVpce": [
                        "vpce-abcd1234",
                        "vpce-xyzz0000"
                    ]
                }
            }
        }
    ]
}
```

------

# API consumer: Associate your VPC endpoint with a private custom domain name shared with you
<a name="apigateway-private-custom-domains-consumer-create"></a>

The following procedure shows how to consume a private domain name in another Amazon Web Services account. Depending on your trust relationship with the API provider, Amazon RAM might complete some tasks for you.

When you are in a different Amazon Web Services account from a private custom domain name, you can only associate your VPC endpoint with a private custom domain name and invoke it. You can't view the `policy` or any other parameters of the private custom domain name.

## Prerequisites
<a name="apigateway-private-custom-domains-consumer-prerequisites"></a>

The following prerequisites are required to consume a private custom domain name in another Amazon Web Services account:
+ A VPC and a VPC endpoint for the `execute-api` service. Your VPC must have `enableDnsHostnames` and `enableDnsSupport` set to `true`.
+ We recommend that you configure at least two Availability Zones per VPC endpoint.

## (Optional) Accept the private custom domain resource share
<a name="apigateway-private-custom-domains-consumer-accept-resource-share"></a>

If your API provider used Amazon RAM to create a resource share, you have **12 hours** to accept it. If you are in the same organization using Amazon Organizations as the API provider, the share is automatically accepted. If you are in an organization that has automatic shared resources enabled, the resource is automatically shared with you.

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Accepting and rejecting resource share invitations](https://docs.amazonaws.cn/ram/latest/userguide/working-with-shared-invitations.html) in the *Amazon RAM User Guide*. 

------
#### [ Amazon CLI ]

To find all resources shared with you, use the following [get-resource-share-invitations](https://docs.amazonaws.cn/cli/latest/reference/ram/get-resource-share-invitations.html) command:

```
aws ram get-resource-share-invitations \
    --region us-west-2
```

Use the resulting resource share ARN to accept the resource share invitation. The following [accept-resource-share-invitation](https://docs.amazonaws.cn/cli/latest/reference/ram/accept-resource-share-invitation.html) command accepts the resource share.

```
aws ram accept-resource-share-invitation \
    --resource-share-invitation-arn arn:aws:ram:us-west-2:123456789012:resource-share-invitation/1e3477be-4a95-46b4-bbe0-c4001EXAMPLE \
    --region us-west-2
```

------

## Associate your VPC endpoint with a shared private custom domain name
<a name="apigateway-private-custom-domains-consumer-associate"></a>

Because private custom domain names aren't unique, you associate your VPC endpoint with the unique custom domain name ARN. After you create your domain name access association, it can take up to 15 minutes for your VPC endpoint to successfully invoke your private custom domain name. If you have a VPC endpoint that you use to access a public custom domain name, don't use it to create any domain name access associations. 

------
#### [ Amazon Web Services Management Console ]

**To associate your VPC endpoint with a shared private custom domain name**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Domain name access associations**.

1. Choose **Create domain name access association**.

1. For **Domain name ARN**, select the domain name ARN that the API provider shared with you.

   The domain name ARN might not appear in the dropdown list. You can use the Amazon RAM console to view domain names shared with you and then copy the domain name ARN and enter it into this field.

1. For **VPC endpoint ID**, select the VPC endpoint ID you want to form the domain name access association with.

1. Choose **Create domain name access association**.

------
#### [ Amazon CLI ]

Because private custom domain names aren't unique, you associate your VPC endpoint with the unique custom domain name ARN. To find the domain name ARN, use one of the following commands.

1.   
**Amazon RAM**  
The following [list-resources](https://docs.amazonaws.cn/cli/latest/reference/ram/list-resources.html) command lists resources that are shared with you. The API provider must have used Amazon RAM to share their private custom domain with you to use this command.  

   ```
   aws ram list-resources \
       --resource-owner OTHER-ACCOUNTS \
       --region us-west-2
       --resource-type apigateway:Domainnames
   ```  
**API Gateway**  
The following `get-domain-names` command lists all private custom domain names owned by other Amazon Web Services accounts that you can form domain name access associations with.  

   ```
   aws apigateway get-domain-names \
       --resource-owner OTHER_ACCOUNTS \
       --region us-west-2
   ```

1.  After your retrieve the ARN, use API Gateway to create the domain name access association between your VPC endpoint and a shared private custom domain name. Use the following `create-domain-name-access-association` command:

   ```
   aws apigateway create-domain-name-access-association \
       --access-association-source-type VPCE \
       --access-association-source 'vpce-1a2b3c4d5e6f1a2b3' \
       --domain-name-arn arn:aws:apigateway:us-west-2:111122223333:/domainnames/private.example.com+abcd1234"
   ```

   The output will look like the following.

   ```
   {
       "domainNameAccessAssociationARN": "arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg", 
       "accessAssociationSource": "vpce-1a2b3c4d5e6f1a2b3",
       "accessAssociationSourceType": "VPCE",
       "domainNameARN" : "arn:aws:apigateway:us-west-1:111122223333:/domainnames/private.example.com+a1b2c3"
   }
   ```

------

After you associate your VPC endpoint with the private custom domain name, confirm that your API provider has updated the policy of their private custom domain name to allow your VPC endpoint to invoke their domain name. For more information, see [Allow other accounts to invoke your private custom domain name](apigateway-private-custom-domains-provider-share.md#apigateway-private-custom-domains-provider-policy-update).

## Create a Route 53 hosted zone
<a name="apigateway-private-custom-domains-consumer-create-route-53-private-hosted-zone"></a>

To resolve the private custom domain name, you need to create a Route 53 private hosted zone. A hosted zone is container that holds information about how you want to route traffic for a domain within one or more VPCs without exposing your resources to the internet. For more information, see [Working with private hosted zones](https://docs.amazonaws.cn/Route53/latest/DeveloperGuide/hosted-zones-private.html).

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Creating a private hosted zone](https://docs.amazonaws.cn/Route53/latest/DeveloperGuide/hosted-zone-private-creating.html) in the *Amazon Route 53 Developer Guide*.

For **Name**, use the name of the private custom domain name. For **VPC ID**, use the VPC containing the VPC endpoint that you used for your domain name access association.

------
#### [ Amazon CLI ]

The following [create-hosted-zone](https://docs.amazonaws.cn/cli/latest/reference/route53/create-hosted-zone.html) command creates a private hosted zone:

```
aws route53 create-hosted-zone --name private.example.com \
    --caller-reference 2014-04-01-18:47 \
    --hosted-zone-config Comment="command-line version",PrivateZone=true \
    --vpc VPCRegion=us-west-2,VPCId=vpc-abcd1234
```

The output contains the hosted zone ID. You use the hosted zone ID in the following steps.

------

## Create a Route 53 DNS record
<a name="apigateway-private-custom-domains-consumer-create-route-53-record"></a>

After you create the hosted zone, you create an record to resolve the private custom domain. In this example, you create an A record type. If you are using IPv6 for your VPC endpoint, create an AAAA record type. If you are using dualstack for your VPC endpoint, create both an AAAA and an A record type.

------
#### [ Amazon Web Services Management Console ]

To use the Amazon Web Services Management Console, see [Routing traffic to an Amazon API Gateway API by using your domain name](https://docs.amazonaws.cn/Route53/latest/DeveloperGuide/routing-to-api-gateway.html).

Use **Quick create** and turn on **Alias**. For endpoint, use the VPC endpoint DNS name.

------
#### [ Amazon CLI ]

To configure your DNS records to map the private custom domain name to its hostname of the given hosted zone ID, first create a JSON file that contains the configuration for setting up a DNS record for the private domain name.

The following `setup-dns-record.json` shows how to create a DNS `A` record to map a private custom domain name to its private hostname. You provide the `DNSName` of your VPC DNS ID, and the hosted zone ID you created in the previous step.

```
{
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "private.example.com",
        "Type": "A",
        "AliasTarget": {
          "DNSName": "vpce-abcd1234.execute-api.us-west-2.vpce.amazonaws.com",
          "HostedZoneId": "Z2OJLYMUO9EFXC",
          "EvaluateTargetHealth": false
        }
      }
    }
  ]
}
```

The following [change-resource-record-sets](https://docs.amazonaws.cn/cli/latest/reference/route53/change-resource-record-sets.html) command creates a DNS record for the private custom domain name:

```
aws route53 change-resource-record-sets \
    --hosted-zone-id ZABCDEFG1234 \
    --change-batch file://path/to/your/setup-dns-record.json
```

Replace the`hosted-zone-id` with the Route 53 Hosted Zone ID of the DNS record set in your account. The `change-batch` parameter value points to a JSON file.

------

## Next steps for an API consumer
<a name="apigateway-private-custom-domains-consumer-next-steps"></a>

You can now invoke the private API in your own Amazon Web Services account. In your VPC, you can use the following curl command to access your private custom domain name.

```
curl https://private.example.com/v1
```

For more information about other ways to invoke your private API, see [Invoke a private API using a custom domain name](apigateway-private-api-test-invoke-url.md#apigateway-private-custom-domains-provider-invoke).

# API consumer: Delete your domain name access association with a private custom domain name
<a name="apigateway-private-custom-domains-consumer-delete-domain-name-access-association"></a>

If you are an API consumer, at any time, you can delete the access association resource. The API provider can't delete the domain name access association for you.

We recommend that you always delete a domain name access association when you're no longer using it.

------
#### [ Amazon Web Services Management Console ]

**To delete the domain name access association**

1. Sign in to the API Gateway console at [https://console.amazonaws.cn/apigateway](https://console.amazonaws.cn/apigateway).

1. In the main navigation pane, choose **Domain name access associations**.

1. Select your domain name access association, and then choose **Delete**.

1. Confirm your choice, and then choose **Delete**.

------
#### [ Amazon CLI ]

The following `delete-access-association` command deletes the access association:

```
aws apigateway delete-domain-name-access-association \
    --domain-name-access-association-arn 'arn:aws:apigateway:us-west-2:444455556666:/domainnameaccessassociations/domainname/private.example.com+abcd1234/vpcesource/vpce-abcd1234efg'
```

------

# Create a custom domain name for private APIs using Amazon CloudFormation
<a name="apigateway-private-custom-domains-cfn"></a>

The following example Amazon CloudFormation template creates a private API and a private custom domain name, maps the private API to the custom domain name, and then creates a domain name access association. You need to provide your own VPC endpoint, domain name, and certificate ARN.

The following considerations might impact your use of Amazon CloudFormation to create a private custom domain name:
+ You can't reject a domain name access association using Amazon CloudFormation. To reject a domain name access association, use the Amazon CLI.
+ Use the `AWS::ApiGateway::DomainNameV2` Amazon CloudFormation property to create a private custom domain name.
+ Use the `AWS::ApiGateway:BasePathMappingV2` Amazon CloudFormation property to create a base path mapping.

```
AWSTemplateFormatVersion: 2010-09-09
Parameters:
  EndpointID:
    Type: String
    Default: vpce-abcd1234567efg
    Description: A VPC endpoint with enableDnsHostnames and enableDnsSupport set to true.
  DomainName:
    Type: String
    Default: private.example.com
    Description: A domain name that you own.
  CertificateArn:
    Type: String
    Default: arn:aws:acm:us-west-2:123456789:certificate/abcd-000-1234-0000-000000abcd
    Description: An ACM certificate that covers the domain name.
Resources:
  PrivateApi:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      EndpointConfiguration:
        Types:
          - PRIVATE
        VpcEndpointIds:
          - !Ref EndpointID
      Name: private-api
      Policy:
        Statement:
          - Action: 'execute-api:Invoke'
            Effect: Allow
            Principal: '*'
            Resource: 'execute-api:/*'
          - Action: 'execute-api:Invoke'
            Condition:
              StringNotEquals:
                'aws:SourceVpce': !Ref EndpointID
            Effect: Deny
            Principal: '*'
            Resource: 'execute-api:/*'
        Version: 2012-10-17		 	 	 
  PrivateApiDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    Properties:
      RestApiId: !Ref PrivateApi
      Description: Private API deployment
    DependsOn:
      - PrivateApiMethod
  PrivateApiStage:
    Type: 'AWS::ApiGateway::Stage'
    Properties:
      RestApiId: !Ref PrivateApi
      DeploymentId: !Ref PrivateApiDeployment
      StageName: prod
  PrivateApiMethod: 
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !GetAtt PrivateApi.RootResourceId
      RestApiId: !Ref PrivateApi
      AuthorizationType: NONE
      Integration:
        Type: MOCK
        RequestTemplates:
          application/json: "{\"statusCode\": 200}"
        IntegrationResponses:
          - StatusCode: '200'
      MethodResponses:
        - StatusCode: '200'
  PrivateDomainName:
    Type: AWS::ApiGateway::DomainNameV2
    Properties:
      DomainName: !Ref DomainName
      CertificateArn: !Ref CertificateArn
      EndpointConfiguration:
        Types:
          - PRIVATE
      SecurityPolicy: TLS_1_2
      Policy:
        Statement:
            - Action: 'execute-api:Invoke'
              Effect: Allow
              Principal: '*'
              Resource: 'execute-api:/*'
            - Action: 'execute-api:Invoke'
              Condition:
                StringNotEquals:
                  'aws:SourceVpce': !Ref EndpointID
              Effect: Deny
              Principal: '*'
              Resource: 'execute-api:/*'
        Version: 2012-10-17		 	 	 
  PrivateBasePathMapping:
    Type: AWS::ApiGateway::BasePathMappingV2
    DependsOn:
      - PrivateApiStage
    Properties:
      BasePath: prod
      DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
      RestApiId: !Ref PrivateApi
      Stage: prod
  DomainNameAccessAssociation: 
    Type: AWS::ApiGateway::DomainNameAccessAssociation
    Properties:
      DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
      AccessAssociationSource: !Ref EndpointID
      AccessAssociationSourceType: VPCE
```