Web Hosting
Web Hosting is a resource that puts a built static website into a Space and serves it at a {subdomain}.weegloo.app address. Take a clothing store as an example: serving the built store site at dailywear-shop.weegloo.app is one Web Hosting.
The order of putting it up is as follows. First, bundle the build output as a ZIP or tar.gz and upload it through the Upload API to get one Upload. Then create a Web Hosting with POST /web-hostings, referencing that Upload. Once the system processes the uploaded files and sys.state becomes COMPLETED, you can reach the site at url. In CMA, a Web Hosting is a sub-resource of Space, and its path is based on /spaces/{spaceId}/web-hostings.
Resource structure
The following is the single-read response for the Web Hosting "DailyWear store site" after processing has finished. Along with sys (system properties), it has the body properties (name, description, isSpa, subdomain, url, pageMetas).
{
"sys": {
"id": "3trmXRM3RqbgSnifyg7PWeb01Examp",
"type": "WebHosting",
"space": { "sys": { "id": "tcq4V2Xb", "type": "Refer", "targetType": "Space" } },
"createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"createdAt": "2026-06-18T11:40:00.000Z",
"updatedAt": "2026-06-18T11:40:05.000Z",
"state": "COMPLETED",
"totalFileSize": 245786,
"originMetas": [
{
"file": "index.html",
"meta": {
"title": "Daily Wear Store",
"description": "Everyday clothing store"
}
}
],
"version": 3
},
"name": "DailyWear store site",
"description": "Static site for the clothing and accessories store",
"isSpa": true,
"subdomain": "dailywear-shop",
"url": "https://dailywear-shop.weegloo.app",
"pageMetas": [
{
"file": "index.html",
"meta": {
"title": "DailyWear - clothes for every day",
"description": "Everyday pieces you can wear to work and on weekends.",
"image": "https://dailywear-shop.weegloo.app/og-cover.png"
}
}
]
}Key properties:
subdomain: The subdomain the site will be served on. In the example above it isdailywear-shop, so the final address becomesdailywear-shop.weegloo.app.url: The site address you can reach once processing has finished.isSpa: Whether it is a single-page app (SPA). Iftrue, every path request is sent toindex.html.state: The deployment-processing state of the uploaded files. Explained in System properties (sys) below.pageMetas: The meta tag values overridden per document.sys.originMetasholds the values as they were before the override. Both are explained in Per-document metadata below.
System properties (sys)
Every Web Hosting carries common system properties in the sys object. space, createdBy, and updatedBy are in the Refer shape ({ "sys": { "id", "type": "Refer", "targetType" } }).
| Property | Type | Description |
|---|---|---|
id | string | Unique resource identifier. It goes into {webHostingId} in the single-read, update, and delete paths. |
type | string | Resource kind. For a Web Hosting this is always "WebHosting". |
space | Refer<Space> | The Space this Web Hosting belongs to. |
createdBy | Refer<User> | The user who created it. |
createdAt | string (date-time) | Creation time. |
updatedBy | Refer<User> | The user who last updated it. |
updatedAt | string (date-time) | Last update time. |
state | string (enum) | Deployment-processing state. One of the four below. |
error | string | The reason when processing fails. Empty when there is no failure. |
totalFileSize | integer | The total size of the uploaded files (in bytes). |
originMetas | PageMeta[] | The meta tag values the documents originally carried. Filled in only for a Web Hosting created by installing a MarketApp. Explained in Per-document metadata below. |
version | integer (≥1) | Resource version. It increases by 1 with every create and update. This is the value you must send in x-weegloo-version on update and partial-update requests. |
state represents the processing stage of deploying the uploaded files. It is not a Content publish status, and a Web Hosting has no concept of publishing or archiving. Once the files are processed and it becomes COMPLETED, the site is reachable at url.
state | Meaning |
|---|---|
PENDING | Waiting to be processed. |
PROCESSING | Being processed. |
COMPLETED | Processing complete. Reachable at url. |
FAILED | Processing failed. The reason is held in sys.error. |
Body properties
The body properties of a Web Hosting are as follows.
| Property | Type | Description |
|---|---|---|
name | string (1-64) | The Web Hosting name. Required on create. |
description | string (≤128) | Description. Optional. |
isSpa | boolean | Whether it is a single-page app. If true, every path request is sent to index.html (for SPA routing). Required on create. |
subdomain | string (3-32) | The serving subdomain. Pattern ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$ (lowercase letters, digits, hyphens; the first and last characters cannot be a hyphen). Required on create. |
upload | Refer<Upload> | A reference to the files to put up. It is a ZIP or tar.gz, must have index.html at the root, and assets must be referenced with relative paths. |
url | string | The access URL after processing finishes. Filled in by the system. |
pageMetas | PageMeta[] | The meta tag values to override per document. Optional. Explained in Per-document metadata below. |
customDomain | string | The connected custom domain. Optional. Explained in Custom domain below. |
Checking a subdomain
Before creating a Web Hosting, you can check whether the subdomain you want to use is free. Pass the subdomain to check as the subdomain query on GET /web-hostings/availability?subdomain=....
The response has the following shape, and if available is true, you can use that subdomain.
{ "subdomain": "dailywear-shop", "available": true }Custom domain
Instead of the default address {subdomain}.weegloo.app, you can connect a domain you own to a Web Hosting. The state of the connected domain is represented by the customDomain object, in the { id, domain, dns, cert } shape. dns and cert are, respectively, the domain-ownership verification (DNS) and certificate-issuance (cert) states, and both are in the { status, txtName, txtContent } shape. txtName and txtContent are the name and value of the DNS TXT record you must register on the domain side.
{
"id": 1024,
"domain": "shop.dailywear.example",
"dns": {
"status": "pending",
"txtName": "_weegloo.shop.dailywear.example",
"txtContent": "weegloo-verify=3trmXRM3RqbgSnifyg7PWebVerifyEx"
},
"cert": {
"status": "pending",
"txtName": "_acme-challenge.shop.dailywear.example",
"txtContent": "acme-verify=3trmXRM3RqbgSnifyg7PWebCertEx"
}
}After registering the TXT records on the domain side, trigger verification with PUT /web-hostings/{webHostingId}/custom-domain/status/verify, and read the current state with GET /web-hostings/{webHostingId}/custom-domain/status. When verification finishes, dns.status becomes active and cert.status becomes ok. Calling the status read on a Web Hosting that has no connected custom domain responds with an error (see Errors).
Per-document metadata
You can override the meta tags in each document's <head> on a site you have put up. The title, description, and image that appear in search results and in messenger link previews change to these values. The point is to change them with one request instead of rebuilding and uploading the files again.
Editing works only on a Web Hosting created by installing a MarketApp. Once you replace the files through upload, editing is no longer possible and sys.originMetas is cleared along with it. A request that breaks the condition is rejected (see Errors).
Values go in the pageMetas array, and one entry targets one document.
| Property | Type | Description |
|---|---|---|
file | string (1-1024) | The relative path of the target document. For example index.html, about/index.html. |
meta | WebHostingMeta | The slot values to apply to that document. |
sys.originMetas has the same shape and holds the values the documents originally carried before the override. To revert, send those values again.
Slots
The keys of meta are called slots. One slot changes several tags together.
| Slot | Max length | Tags changed |
|---|---|---|
title | 200 | <title>, og:title, twitter:title |
description | 500 | description, og:description, twitter:description |
canonical | 2048 | link[rel=canonical], og:url |
image | 2048 | og:image, twitter:image |
siteName | 200 | og:site_name |
favicon | 2048 | link[rel=icon], link[rel="shortcut icon"], link[rel=apple-touch-icon] |
themeColor | 32 | theme-color |
If a tag is missing from the document, it is created and inserted. Five are the exception: twitter:title, twitter:description, twitter:image, link[rel="shortcut icon"], and link[rel=apple-touch-icon] change only when the document already has them, and are not created when it does not.
What each value does
The outcome depends on the shape of the value you send.
| What you put in the request | Result |
|---|---|
| The slot key is absent | The current setting stays as it is. |
The slot key is null | The current setting stays as it is. |
| The slot key is an empty string | That tag is removed from the document. |
| The slot key has a value | It is overwritten with that value. |
A document entry is left out of pageMetas | That document's setting stays as it is. |
pageMetas is absent | Every document's setting stays as it is. |
Pay particular attention to the last two rows. The server merges what you send per document and per slot. So leaving an entry out of the array does not clear a setting; to clear one you must state an empty string on that slot.
An empty string removes the tag rather than restoring the original. A tag the document originally carried disappears with it. To restore the original value, send the value still held in sys.originMetas.
The following request body changes only the title of index.html and removes its description tag.
{
"pageMetas": [
{
"file": "index.html",
"meta": {
"title": "DailyWear - clothes for every day",
"description": ""
}
}
]
}Changing pageMetas starts the processing that applies those values to the actual documents. sys.state returns to PENDING and then comes back to COMPLETED, and updates and deletes are rejected in between.
Errors
These are the codes you meet when working with a Web Hosting. For codes that are common to every resource, see common errors.
| Code | Condition |
|---|---|
WGL422031 | The caller tried to update or delete a Web Hosting while its deployment files were still being processed. Try again once the processing has finished. |
WGL422113 | pageMetas was sent to a Web Hosting whose per-document metadata cannot be edited. Either it was not created by installing a MarketApp, or its files have since been replaced through an upload. |
WGL500039 | The information for the connected custom domain could not be read from the delivery network. |
WGL429001 | The caller tried to attach a custom domain to a Web Hosting that had none, while the Organization had already reached its plan limit on the number of custom domains. Changing a domain that already exists does not raise the count, so that change does not run this check. |
API
The base URL for all endpoints below is https://cma.weegloo.com/v1, and a Bearer token that authenticates against CMA is required in the Authorization header. Update and partial update must also send the X-Weegloo-Version header (the current resource's sys.version) for optimistic concurrency control. Create and delete requests do not carry this header.
Related documents
- Upload API: The request that uploads a static-file ZIP to get an Upload to use when creating a Web Hosting.
- Space: The Space the Web Hosting belongs to.
