Alright, let’s talk about making your API Gateway look like a proper adult. Because right now, your endpoint is https://a1b2c3d4e5.execute-api.us-east-1.amazonaws.com/prod. That’s not a URL you’d want to put on a business card; it looks like a cat walked across your keyboard. We’re going to fix that with Custom Domain Names and their trusty sidekick, Base Path Mappings. This is how you get a clean, professional-looking endpoint like https://api.your-awesome-company.com.

The Absolute Necessity of the ACM Certificate

First things first: you cannot do this without an SSL certificate from AWS Certificate Manager (ACM). And here’s the first ‘gotcha’— the certificate must be in the us-east-1 region. I know, I know. You’re deploying your API in eu-west-1 because you’re fancy and GDPR-compliant. Tough luck. The API Gateway service itself, for reasons known only to its architects deep inside Amazon, requires the cert to be in us-east-1. It’s a bizarre, seemingly arbitrary rule, but it’s the law of the land. So go get that first.

# You'll do this in the AWS CLI, but just go to the ACM console in us-east-1. Seriously.
aws acm request-certificate --domain-name api.your-awesome-company.com --region us-east-1

Creating the Custom Domain Name Resource

This is the core object we’re creating. It’s the resource that represents the marriage between your domain name and the ACM certificate. You configure this in API Gateway, and it will give you a Target Domain Name—a CloudFront distribution URL—that you’ll use in your DNS.

Here’s how you create it with CloudFormation. Notice the RegionalDomainName output; that’s the golden ticket.

Resources:
  MyCustomDomain:
    Type: AWS::ApiGateway::DomainName
    Properties:
      DomainName: api.your-awesome-company.com
      RegionalCertificateArn: !Ref MyUsEast1Certificate
      EndpointConfiguration:
        Types:
          - REGIONAL # Use EDGE for the older Edge-optimized endpoint type.

Outputs:
  ApiGatewayDomainName:
    Description: The CloudFront domain name to point your DNS to
    Value: !GetAtt MyCustomDomain.RegionalDomainName

The Magic Trick: Base Path Mappings

Here’s where the real power lies. A single custom domain name can front multiple APIs. Why would you want to do this? Maybe you have a users-api, a billing-api, and an inventory-api, all managed separately. Instead of buying three domains, you can use one and map different paths.

This is the Base Path Mapping. It says, “Hey, for my domain api.your-awesome-company.com, any request that comes in to the path /users/* should be forwarded to this specific API stage. Anything to /billing/* goes to that one.”

Resources:
  UsersApiMapping:
    Type: AWS::ApiGateway::BasePathMapping
    Properties:
      DomainName: !Ref MyCustomDomain
      RestApiId: !Ref MyUsersApi # Reference to your API Gateway
      Stage: prod # The stage name to map
      BasePath: users # This can be empty to map the root path

  BillingApiMapping:
    Type: AWS::ApiGateway::BasePathMapping
    Properties:
      DomainName: !Ref MyCustomDomain
      RestApiId: !Ref MyBillingApi
      Stage: prod
      BasePath: billing

With this setup, a request to https://api.your-awesome-company.com/users/profile would hit the prod stage of MyUsersApi, and https://api.your-awesome-company.com/billing/invoice would hit MyBillingApi.

The DNS Tango

You’ve created the domain name, and you’ve got your mappings. The last step is telling the world how to find it. API Gateway gives you that CloudFront domain name (it’ll look like d1234567890.cloudfront.net). In your DNS provider (Route 53 or elsewhere), you create a CNAME record that points your custom domain (api.your-awesome-company.com) to that CloudFront domain.

If you’re using Route 53, you can use an alias record, which is better than a CNAME.

Resources:
  MyDomainDNSRecord:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneName: your-awesome-company.com.
      Name: api.your-awesome-company.com.
      Type: A
      AliasTarget:
        DNSName: !GetAtt MyCustomDomain.RegionalDomainName
        HostedZoneId: !GetAtt MyCustomDomain.RegionalHostedZoneId

The Gotchas and Grey Areas

  1. The Propagation Panic: After you hook up the DNS, go get a coffee. It can take up to 40 minutes for the domain name to change from STATE_PENDING to STATE_AVAILABLE in the API Gateway console. Do not panic. AWS is just moving at its own, glacial pace.
  2. The Empty BasePath Problem: Want to map an API to the root path? You set BasePath: "" (or just omit the property). But you can only have one API mapped to the root path per domain. It’s a first-come, first-serve basis.
  3. WebSocket Quirk: For WebSocket APIs, the concept is similar, but simpler. There are no base paths. A custom domain name for a WebSocket API is dedicated to that single API. It’s a one-to-one relationship.
  4. The Cache of Evil: If you’re testing and changing mappings, be aware that there might be a short-lived DNS or connection cache on your machine. If something isn’t working, try curl from a different network or use dig to see if the DNS is truly propagated. This has wasted more of my hours than I care to admit.

Getting this right is the final polish that makes your API service look professional and intentional. It’s a bit of a hassle, but the moment you see that clean URL working in your client, you’ll feel a profound sense of satisfaction. Now go forth and make that URL presentable.