Start with an owned workspace.
These endpoints power the authenticated Newsly dashboard. Public subscription integrations and campaign sending are not available yet.
- Sign in to Newsly and open the dashboard.
- Create or select a tenant.
- Use the owner session from the configured frontend origin.
API origin for this build: https://integration.newsly.dev.
const response = await fetch('https://integration.newsly.dev/v1/tenants', {
credentials: 'include',
});
if (!response.ok) throw new Error('Tenant request failed.');
const { tenants } = await response.json();Your session is your authentication.
All /v1/ endpoints require the WorkOS session cookie __Host-newsly-session. Use credentials: 'include' for browser requests.
The cookie is HTTP-only. Do not read it in JavaScript, put it in source code, or share it in support requests.
POST, PUT, and DELETE require an Origin equal to the configured frontend origin. Browsers supply this header automatically.
Start sign-in at /auth/login?return_to=%2Fdashboard. WorkOS returns to /auth/callback. Sign out with POST /auth/logout.
Failed sign-in returns to the homepage with a fixed error code, a retry action, and a prefilled support action. Provider details and authentication secrets are not included.
Backend subscription keys are separate planned work. These owner endpoints do not accept a bearer API key.
Available endpoints
Replace path parameters such as :id with an owned record ID. A tenant outside your account is not accessible.
Account and health
| Method | Path | Purpose |
|---|---|---|
| GET | /health | Worker health. No sign-in required. |
| GET | /health/db | Database health. No sign-in required. |
| GET | /v1/me | The signed-in owner. |
Sending domains
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/sending-domains | List your claimed sending domains. |
| GET | /v1/sending-domains/:domain/availability | Check availability and existing ownership. |
| POST | /v1/sending-domains | Claim a domain or reuse an existing owned claim. |
| DELETE | /v1/sending-domains/:domain | Release an unused domain claim. |
Tenant workspaces
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/tenants | List your tenant workspaces. |
| POST | /v1/tenants | Create a tenant with its domain and sender identity. |
| GET | /v1/tenants/:id | Get one owned tenant. |
| PUT | /v1/tenants/:id/profile | Save the complete tenant profile. |
| PUT | /v1/tenants/:id/sender | Save both sender identity fields. |
| PUT | /v1/tenants/:id/sending-domain | Save the profile and sending domain together. |
Current subscribers
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/tenants/:id/subscribers | Search and filter the current subscriber list. |
| GET | /v1/tenants/:id/subscribers/export | Export all matching current subscribers as CSV. |
| GET | /v1/tenants/:id/subscribers/analytics | Get current-record counts, sources, and trends. |
| DELETE | /v1/tenants/:id/subscribers/:subscriberId | Permanently remove one current subscriber. |
Add ?includeUsage=true to the domain list for inUse flags. An in-use domain claim cannot be deleted.
Create a tenant
Creation requires a name, sending domain, sender display name, and sender local part. The business name and postal address are optional during creation.
const response = await fetch('https://integration.newsly.dev/v1/tenants', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'The Sunday Letter',
businessName: 'Sunday Studio',
postalAddress: '123 Example Street',
sendingDomain: 'sunday.newsly.dev',
senderDisplayName: 'Sunday Studio',
senderLocalPart: 'hello',
}),
});A successful creation returns HTTP 201 with { "tenant": { ... } }. A list returns { "tenants": [...] }.
The sending domain must use the configured Newsly suffix. An unclaimed domain becomes an owned claim in the same transaction.
A profile update requires name, businessName, and postalAddress. A sender update requires senderDisplayName and senderLocalPart.
A domain update requires the complete profile plus sendingDomain. It retains the sender identity and previous domain claim.
Search the current audience.
The list and export combine all supplied filters. Bounced subscribers remain active and visible. There is no manual creation, import, or email-edit endpoint.
search- A literal email substring, without case or surrounding-space differences.
sourceemail_confirmationorbackend.bouncedtrueorfalse.startDateandendDate- Inclusive UTC dates in
YYYY-MM-DDformat. page- List only. Starts at 1, with at most 50 subscribers per page.
List responses contain subscribers, total, page, pageSize, and timeZone.
Export includes all matching pages. An empty export returns HTTP 404 with NO_SUBSCRIBERS_TO_EXPORT.
Analytics accept period=7, 30, 90, or all. They use UTC calendar boundaries and ignore list filters.
Removal also changes past analytics because all results use current records. Confirm permanent removal before you send a DELETE request.
Errors that tell you what to do next.
Error responses contain an error code. Some also include a message and per-field validation errors.
- 400
- Correct invalid fields, query parameters, or a self-service limit.
- 401
- Sign in again. The owner session is missing or invalid.
- 403
- Use the configured frontend origin for mutations.
- 404
- The record is missing or not owned by you. Exports also use 404 for an empty result.
- 409
- Resolve a duplicate tenant name, unavailable domain, or in-use domain claim.
- 503
- The operation is unavailable. Read the message before you retry.
Each owner can create five tenants and hold five domain claims. Reusing an owned domain does not use another claim slot.
Prepare a support request