# Apexly > Custom domains as a service: your customers point a hostname at Apexly and it serves your app there with TLS. These docs cover the API, webhooks, the connect page and every error and status reason. ## API reference - [Apps](/api/apps.md): Your app: the origin every customer domain forwards to, white-label, webhooks and the signing secret. - [Domains](/api/domains.md): Add your customers' hostnames, read the record each one needs and where it stands, re-check it, remove it. - [Errors](/api/errors.md): Every error has the same envelope, and every code has a page that explains it and how to fix it. - [Events](/api/events.md): Everything that happened to your domains, newest first, with webhook deliveries and redelivery. - [Keys](/api/keys.md): API keys. A live key manages live domains; a test key manages test domains, which never contact a certificate authority. ## Updates - [Changelog](/changelog.md): Changes to the API, webhooks and the connect page. Additive changes ship in v1; anything breaking gets a new version. ## Getting started - [Custom domains for SaaS](/concepts/custom-domains-for-saas.md): How a SaaS lets each customer serve your product on their own domain, the five steps behind it, and which of them Apexly runs for you. - [How it works](/concepts/domain-states.md): A domain moves through a handful of states, each with one owner and a fixed check cadence. Every move is recorded, and the ones you act on fire a webhook. - [Quickstart](/quickstart.md): Live domain in five minutes. Six requests, real responses, nothing to install. ## Product - [Connect page](/connect-page.md): A hosted page per domain that walks your customer through adding the record, in plain words, under your app's name. - [Limits and pricing](/limits-and-pricing.md): What each plan includes, what happens at the limit, and the rate limits every API key shares. - [Webhooks](/webhooks.md): A domain created, verified, live, broken, failing issuance, renewed, held, released or deleted fires one signed POST to your endpoint. Verify the signature, reply 2xx, and you never have to poll. ## Troubleshooting - [Why isn't it live?](/troubleshooting/domain-doctor.md): One call runs every check that decides whether a domain serves, and names the one thing to change. - [account_suspended](/errors/account_suspended.md): The account is suspended, so changes are paused. Existing domains keep serving. - [apex_a_mismatch](/troubleshooting/apex_a_mismatch.md): The apex domain's A records don't point to Apexly's addresses. - [apex_txt_missing](/troubleshooting/apex_txt_missing.md): The apex A records are right, but the _apexly TXT record that proves control is missing or different. - [billing_unavailable](/errors/billing_unavailable.md): The billing provider did not answer. - [ca_rate_limited](/troubleshooting/ca_rate_limited.md): The certificate authority is rate-limiting new certificates for this registrable domain. - [ca_unreachable](/troubleshooting/ca_unreachable.md): We couldn't reach the certificate authority to issue the certificate. - [caa_blocks_issuance](/troubleshooting/caa_blocks_issuance.md): A CAA record on the customer's domain doesn't allow our certificate authority to issue for it. - [card_declined](/errors/card_declined.md): The card was declined. - [card_required](/errors/card_required.md): A paid plan needs a card on file. - [dns_provider_permission_missing](/errors/dns_provider_permission_missing.md): The API token cannot edit DNS records for this domain. - [dns_provider_token_invalid](/errors/dns_provider_token_invalid.md): The DNS provider did not accept that API token. - [dns_provider_unavailable](/errors/dns_provider_unavailable.md): The DNS provider did not answer or asked us to slow down. - [dns_provider_zone_not_found](/errors/dns_provider_zone_not_found.md): The API token cannot see this domain at the DNS provider. - [dns_record_mismatch](/troubleshooting/dns_record_mismatch.md): The hostname has a record, but it points somewhere other than Apexly. - [dns_record_missing](/troubleshooting/dns_record_missing.md): We looked for the record and there is nothing there yet. - [dns_records_conflict](/errors/dns_records_conflict.md): Records already on these names would stop the domain from verifying. - [dns_resolvers_disagree](/troubleshooting/dns_resolvers_disagree.md): Some resolvers see the new record and some don't yet. The change is still spreading. - [domain_limit_reached](/errors/domain_limit_reached.md): The plan does not allow more domains. - [forbidden](/errors/forbidden.md): This credential is not allowed to do that. - [held_lookalike](/troubleshooting/held_lookalike.md): The hostname looks like a well-known brand's, so it is paused for review before a certificate is issued. - [hostname_held](/errors/hostname_held.md): This hostname is held for review. - [hostname_is_apexly](/errors/hostname_is_apexly.md): Hostnames under Apexly zones cannot be added. - [hostname_is_public_suffix](/errors/hostname_is_public_suffix.md): That hostname is a public suffix, so nobody can prove control of it. - [idempotency_key_in_use](/errors/idempotency_key_in_use.md): A request with this Idempotency-Key is still being processed. - [idempotency_key_reused](/errors/idempotency_key_reused.md): This Idempotency-Key was already used with a different request. - [internal_error](/errors/internal_error.md): Something went wrong on our side. - [invalid_hostname](/errors/invalid_hostname.md): That is not a valid hostname. - [invalid_request](/errors/invalid_request.md): The request could not be read. - [not_found](/errors/not_found.md): Nothing exists at this path, or it belongs to another app. - [origin_not_allowed](/errors/origin_not_allowed.md): That origin cannot be used. - [payload_too_large](/errors/payload_too_large.md): The request body is larger than 100 KB. - [plan_required](/errors/plan_required.md): This feature is not included in the current plan. - [rate_limited](/errors/rate_limited.md): Too many requests. - [unauthorized](/errors/unauthorized.md): The API key is missing, invalid or revoked. - [validation_failed](/errors/validation_failed.md): The request did not pass validation. - [whitelabel_unverified](/troubleshooting/whitelabel_unverified.md): The customer's CNAME is right, but your white-label host no longer points to Apexly. ## Guides - [Build it with AI](/guides/ai-prompt.md): Copy one prompt into Claude Code, Cursor or ChatGPT and your coding agent wires Apexly into your codebase end to end, from the customer's hostname to webhooks and signature checks. - [Django](/guides/django.md): Serve every customer domain from one Django project. Replace the ALLOWED_HOSTS check with the Apexly signature and resolve the tenant from the host. - [Embed the connect flow in your app](/guides/embed-connect.md): Put Apexly's connect flow inside your own settings page with a script tag or the React component, themed with your brand colour and logo, and hear when the domain goes live. - [Go](/guides/go.md): Serve every customer domain from one Go service with net/http middleware that checks the Apexly signature and resolves the tenant. - [Laravel](/guides/laravel.md): Serve every customer domain from one Laravel app with a middleware that checks the Apexly signature and resolves the tenant. - [NestJS](/guides/nestjs.md): Serve every customer domain from one NestJS app with a middleware that checks the Apexly signature and resolves the tenant. - [Next.js quickstart](/guides/nextjs-quickstart.md): Let your customers bring their own domain to a Next.js App Router app in four files. A Server Action creates the domain, proxy.ts checks every request, a Server Component finds the tenant by Host. - [Next.js](/guides/nextjs.md): Serve every customer domain from one Next.js app. Find the tenant from the Host header and trust only requests Apexly signed. - [Rails](/guides/rails.md): Serve every customer domain from one Rails app. Let signed hosts past host authorization and resolve the tenant from request.host. - [Test mode](/guides/test-mode.md): Test keys create test domains that walk every state on a ten-second timer. No DNS record, no certificate authority, no bill. - [Use Apexly from AI agents (MCP)](/guides/mcp.md): Connect Claude Code, Cursor or any MCP client to Apexly's hosted MCP server and let your coding agent add, check, diagnose and remove custom domains with your API key.