API Docs / Hosting Partner API
Hosting Partner API
The Hosting Partner API lets resellers provision mailboxes and domains for their own clients programmatically — the same actions available in the Partner dashboard, just callable from your own systems. Requires an approved, active or trial Hosting Partner account.
Authentication
Include your API key in the X-API-Key header on every request:
X-API-Key: ker_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Content-Type: application/json
Scopes
Each key is created with one or more scopes. A request 403s if the key is missing a scope it needs — read-only integrations should only request :read scopes.
| Scope | Grants |
|---|---|
| partner:mailboxes:read | List mailboxes |
| partner:mailboxes:write | Create, delete, and renew mailboxes |
| partner:domains:read | List domains and check verification status |
| partner:domains:write | Add, verify, and delete domains |
| partner:addons:read | Read add-on pricing and purchase status |
| partner:addons:write | Purchase domain-slot and storage add-ons |
| partner:stats:read | Read aggregate stats and account summary |
| partner:settings:write | Change account-wide settings (e.g. the default client lapse policy) |
IP restrictions
Optionally lock a key down to specific source IPs (or CIDR ranges) when you create it. Both an allowlist and a blocklist can be set at once — the blocklist is checked first, so an IP that matches both is denied.
- allowed_ips — if set, only these IPs/CIDRs may use the key (everyone else gets
403). Leave unset to allow any IP. - blocked_ips — these IPs/CIDRs are always rejected, even if also present in the allowlist.
POST https://api.kerabie.email/api-keys
{
"name": "Reseller panel integration",
"scopes": ["partner:mailboxes:write", "partner:domains:read"],
"allowed_ips": ["203.0.113.0/24"],
"blocked_ips": ["198.51.100.0/24"]
}Mailboxes
https://api.kerabie.email/v1/hosting/mailboxes| Parameter | Type | Required | Description |
|---|---|---|---|
| domain_id | integer | required | ID of one of your verified domains |
| local_part | string | required | Part before the @ — full address is local_part@domain |
| password | string | required | Initial mailbox password (min 8 chars) |
| display_name | string | optional | Friendly name shown in email clients |
| plan_id | string | required | "pro" (5GB) or "premium" (20GB) — drives the wholesale rate and storage tier |
| funding_mode | string | optional | "slot" (default, draws from your prepaid pool/trial) or "pay_as_you_go" — see the Pay-as-you-go section below |
| return_url | string | optional | Required when funding_mode="pay_as_you_go" — where the client's Bachs checkout redirects after payment |
Request
{
"domain_id": 3,
"local_part": "john",
"password": "SecurePass123!",
"display_name": "John Smith",
"plan_id": "premium"
}Response 201
{
"id": 42,
"email_address": "john@yourclientdomain.com",
"domain": "yourclientdomain.com",
"plan_type": "premium",
"status": "active",
"is_trial": false,
"monthly_rate_usd": 6.0,
"monthly_rate_ngn": 4500.0,
"expires_at": "2026-08-23T18:17:16Z",
"mailu_provisioned": true,
"created_at": "2026-07-23T18:17:12Z"
}https://api.kerabie.email/v1/hosting/mailboxes| Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | optional | Filter by status: trial | active | expired | suspended |
https://api.kerabie.email/v1/hosting/mailboxes/{id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/renewDomains
A client's domain has to be added and pass DNS verification before you can provision mailboxes on it — this proves you (or your client) actually control that domain's DNS, and confirms mail sent to it will actually reach Kerabie's mail servers. New accounts get 2 free domain slots; buy more via the add-ons endpoint.
https://api.kerabie.email/v1/hosting/domains| Parameter | Type | Required | Description |
|---|---|---|---|
| domain_name | string | required | Domain name (e.g. yourclientdomain.com) |
| client_id | integer | optional | Attach to an existing client (see Clients below) — omit to auto-create a new one named after the domain |
Response 201
{
"id": 3,
"domain_name": "yourclientdomain.com",
"status": "pending",
"is_verified": false,
"mailu_added": false,
"dns_records": [
{ "type": "MX", "host": "@", "value": "10 mail.kerabie.email",
"description": "Routes incoming mail for this domain to Kerabie's mail servers.",
"ok": null, "found_value": null, "reason": null },
{ "type": "TXT", "host": "@", "value": "kerabie-verify=5kMm7kfncTQfgIx7lSOuLBU9",
"description": "Proves you control this domain's DNS.",
"ok": null, "found_value": null, "reason": null },
{ "type": "TXT", "host": "@", "value": "v=spf1 mx include:relay.kerabie.email ~all",
"description": "Authorizes Kerabie's mail servers to send email for this domain.",
"ok": null, "found_value": null, "reason": null },
{ "type": "TXT", "host": "_dmarc", "value": "v=DMARC1; p=none; rua=mailto:dmarc@kerabie.email",
"description": "Protects this domain from spoofing and improves deliverability.",
"ok": null, "found_value": null, "reason": null },
{ "type": "TXT", "host": "dkim._domainkey", "value": "v=DKIM1; k=rsa; p=MIIBIjANBgkq...",
"description": "Enables cryptographic signing (DKIM) of outgoing messages to improve delivery.",
"ok": null, "found_value": null, "reason": null }
]
}The DKIM TXT record is generated natively by Mailu the first time the domain is added, and cached. ok/found_value/reason are always null here — nothing has been checked yet. They're populated by the verify call below.
https://api.kerabie.email/v1/hosting/domainshttps://api.kerabie.email/v1/hosting/domains/{id}https://api.kerabie.email/v1/hosting/domains/{id}/verifyResponse 200 — some records still wrong
A real example: 4 of 5 records were configured correctly, but the domain's registrar (Namecheap) had its own Email Forwarding feature still overriding the MX record.reason names the specific problem instead of a generic "not verified" — this is the whole reason these three fields exist.
{
"id": 3,
"domain_name": "yourclientdomain.com",
"status": "failed",
"is_verified": false,
"dns_records": [
{ "type": "MX", "host": "@", "value": "10 mail.kerabie.email",
"ok": false, "found_value": "10 eforward2.registrar-servers.com",
"reason": "Found eforward2.registrar-servers.com instead of mail.kerabie.email — looks like Namecheap Email Forwarding is still enabled for this domain. Disable it (or make sure Custom MX is the selected mail-handling mode) so this record actually takes effect." },
{ "type": "TXT", "host": "@", "value": "kerabie-verify=...",
"ok": true, "found_value": "kerabie-verify=...", "reason": null },
{ "type": "TXT", "host": "@", "value": "v=spf1 mx include:relay.kerabie.email ~all",
"ok": true, "found_value": "v=spf1 mx include:relay.kerabie.email ~all", "reason": null },
{ "type": "TXT", "host": "_dmarc", "value": "v=DMARC1; p=none; ...",
"ok": true, "found_value": "v=DMARC1; p=none; ...", "reason": null },
{ "type": "TXT", "host": "dkim._domainkey", "value": "v=DKIM1; k=rsa; p=...",
"ok": true, "found_value": "v=DKIM1; k=rsa; p=...", "reason": null }
]
}Response 200 — verified
{
"id": 3,
"domain_name": "yourclientdomain.com",
"status": "verified",
"is_verified": true,
"mailu_added": true,
"verified_at": "2026-07-23T18:15:05Z",
"dns_records": null
}dns_records goes back to null once every record checks out — it's non-null whenever there's something worth showing: still pending, or verified but with an SPF/DMARC/DKIM record still wrong (verification itself only requires MX + the ownership token).
https://api.kerabie.email/v1/hosting/domains/{id}Clients
A client is your real-world customer — the entity a domain (and, through it, every mailbox provisioned on that domain) belongs to. One client can own several domains. Every domain is attached to exactly one client; adding a domain without a client_id auto-creates a new single-domain client named after it, so you never have to think about this if you don't need the grouping. Each client also carries its own optional lapse_action_override, which takes priority over your account-wide default (see Settings below) for what happens when one of that client's mailboxes lapses.
https://api.kerabie.email/v1/hosting/clientshttps://api.kerabie.email/v1/hosting/clients| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | required | Display name, e.g. "Acme Corp" |
Response 201
{
"id": 7,
"name": "Acme Corp",
"lapse_action_override": null,
"domain_count": 0,
"mailbox_count": 0,
"created_at": "2026-09-22T10:00:00Z"
}https://api.kerabie.email/v1/hosting/clients/{id}| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | optional | New display name |
| lapse_action_override | string | optional | "suspend" | "downgrade_free" | null — null clears the override, falling back to your account default |
https://api.kerabie.email/v1/hosting/clients/{id}Settings
Account-wide hosting settings. Today this is just the default lapse policy — what happens to a client's mailbox when its trial/prepaid term ends, or a pay-as-you-go payment fails: suspend locks it out entirely (the only behavior before this setting existed), while downgrade_free keeps it reachable on the Free plan instead. A client's own lapse_action_override (see Clients above) takes priority over this default.
https://api.kerabie.email/v1/hosting/settings| Parameter | Type | Required | Description |
|---|---|---|---|
| default_client_lapse_action | string | required | "suspend" or "downgrade_free" |
Request
{ "default_client_lapse_action": "downgrade_free" }White-labeling
An active or trial hosting account can replace Kerabie's own name, logo, and colors with your own — shown on the sign-in page, the logged-in sidebar, and the browser tab icon. It only ever appears on your own custom webmail domain (below); logging in via the shared webmail.kerabie.email always shows plain Kerabie branding, even for your own clients.
Both of these are managed from the dashboard (Settings → Branding and Hosting → Webmail Domain) rather than the API-key surface documented elsewhere on this page — they read from your logged-in session, not an X-API-Key.
Custom webmail domain
Pick a hostname you control — e.g. webmail.yourbrand.com — and point it at Kerabie with a single CNAME record:
CNAME webmail.yourbrand.com → webmail.kerabie.email
Only one domain per account at a time — remove the existing one before adding a replacement. Once DNS resolves correctly the domain flips to verified automatically (checked on a short poll, or immediately via a manual re-check) and a TLS certificate is issued the first time it's actually visited over HTTPS — nothing further to configure.
Branding
Four fields, all optional and independently settable:
- Brand name — replaces "Kerabie WebMail" throughout.
- Logo — a public image URL (upload one from the dashboard and it fills this in for you).
- Primary / secondary color — a hex color (
#7c3aed) or a CSS gradient (linear-gradient(90deg, #7c3aed, #db2777)). Primary drives buttons and accents; secondary is optional and used where a second tone is needed.
Saving branding requires the custom domain condition above (an active/trial hosting account) — attempting to save on a pending or expired account returns 403.
Pay-as-you-go mailboxes
An alternative to buying mailbox slots upfront: the client pays Kerabie directly, on a recurring monthly basis, at a retail price you set — you never pay anything upfront, and instead earn the markup over Kerabie's wholesale rate as a revenue share, credited to your payout balance (GET/POST /partners/me/payouts — same balance and withdrawal flow referral commissions use).
Currently USD and NGN only (matching the rest of the platform's billing), and monthly billing only — the multi-cycle terms (yearly/biennial/triennial) that the prepaid slot pool supports don't apply here.
1. Set your retail price
https://api.kerabie.email/v1/hosting/retail-pricinghttps://api.kerabie.email/v1/hosting/retail-pricing| Parameter | Type | Required | Description |
|---|---|---|---|
| plan_type | string | required | "pro" or "premium" |
| currency | string | required | "usd" or "ngn" |
| retail_price | number | required | Must be ≥ the wholesale rate for this tier/currency |
Request
{ "plan_type": "pro", "currency": "usd", "retail_price": 5.00 }2. Provision with funding_mode="pay_as_you_go"
Same POST /v1/hosting/mailboxes call as any mailbox (see Mailboxes above), with funding_mode: "pay_as_you_go" and a return_url. A retail price must already be set for that plan tier/currency (step 1) or this 400s. The mailbox account is created immediately — the client can see it's ready — but stays disabled and status: "pending_payment" until payment clears. The response includes a checkout_url: send this to your client to complete.
Response 201
{
"id": 8,
"email_address": "client@yourclientdomain.com",
"status": "pending_payment",
"is_pay_as_you_go": true,
"checkout_url": "https://checkout.bachs.io/c/6a5wgGmDy7coMgg"
}3. Get notified when payment clears
Kerabie handles all recurring billing and dunning — you never see a checkout flow or a raw payment status. Instead, listen for these webhook events (see Webhooks below for signature verification):
| Event | Fires when |
|---|---|
| partner_mailbox.payment_confirmed | The client's payment clears — the mailbox is (re-)enabled. Fires on the FIRST payment and on every monthly renewal, not just once. |
| partner_mailbox.payment_failed | A renewal charge fails — the mailbox is disabled until it's paid (Kerabie runs the retry/dunning schedule). |
| partner_mailbox.expired | The client cancels — the mailbox is disabled and marked expired. |
| partner_mailbox.payment_abandoned | The client never completed the FIRST payment and the 7-day grace period (below) ran out — the mailbox and its account are gone, not just disabled. |
Use partner_mailbox.payment_confirmed to verify a client actually paid — don't rely on the browser reaching your return_url alone, since a client can close the tab before the redirect, or the checkout page can be revisited without a real payment.
4. Polling, as an alternative to webhooks
If you'd rather poll than expose a webhook receiver, GET /v1/hosting/mailboxes/{id} returns the same status a webhook would tell you about, and — while status is still "pending_payment" — re-returns the same checkout_url from step 2, in case the client lost the link before you had a chance to save it.
https://api.kerabie.email/v1/hosting/mailboxes/{id}5. Unpaid mailboxes expire automatically
A client who never completes the first payment isn't left provisioned forever: if status is still "pending_payment" 7 days after creation, Kerabie deletes the mailbox and the account behind it automatically and fires partner_mailbox.payment_abandoned. Nothing real ever activated on that account, so there's no customer data to preserve.
This is also why DELETE /v1/hosting/mailboxes/{id} behaves differently depending on whether the mailbox ever got paid: deleting a mailbox that's still "pending_payment" deletes the underlying account too, same as the automatic 7-day cleanup — there's nothing to keep. Deleting any other mailbox (already active, whether pay-as-you-go or slot-funded) only deactivates the account and removes the mailbox/slot; the account's data (subscription, mail, forwarding rules) is left intact in case it needs to be looked up later.
6. Manage a client's subscription
Once a pay-as-you-go mailbox is active, you can check its billing status, cancel it, move the client to a different plan tier, or sell them an add-on — all without them ever needing to log in anywhere themselves. These only work for is_pay_as_you_go: true mailboxes; calling any of them on a slot-funded mailbox returns 400 — manage those with renew/DELETE instead.
https://api.kerabie.email/v1/hosting/mailboxes/{id}/subscriptionResponse 200
{
"mailbox_id": 8,
"plan_type": "premium",
"billing_cycle": "monthly",
"status": "active",
"currency": "usd",
"total_price": 6.0,
"current_period_start": "2026-09-05",
"current_period_end": "2026-10-05",
"next_billing_date": "2026-10-05",
"auto_renew": true,
"payment_provider": "bachs"
}https://api.kerabie.email/v1/hosting/mailboxes/{id}/cancel-subscription| Parameter | Type | Required | Description |
|---|---|---|---|
| immediate | boolean | optional | Cancel right away instead of at period end (default false) |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/upgrade| Parameter | Type | Required | Description |
|---|---|---|---|
| new_plan_type | string | required | "pro" or "premium" — must differ from the mailbox's current plan |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/addons/purchase| Parameter | Type | Required | Description |
|---|---|---|---|
| type | string | required | "extra_mailbox" or "extra_storage" |
| quantity | integer | optional | Default 1 |
| return_url | string | required | Where the client's checkout redirects after payment |
Response 200
{
"payment_method_id": 91,
"checkout_url": "https://checkout.bachs.io/c/9fK2mQwLp0aXcRt",
"status": "pending_payment"
}Mailbox management
The full toolset a client would get if they ever logged into Kerabie directly — forwarding rules, aliases, signature/sender name, contacts, and campaigns — all available on their behalf through your own systems, since there's no end-customer self-service portal. Every endpoint below takes the mailbox's id from Mailboxes above.
Forwarding
https://api.kerabie.email/v1/hosting/mailboxes/{id}/forwardinghttps://api.kerabie.email/v1/hosting/mailboxes/{id}/forwarding| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | The mailbox to forward from (must be this mailbox's address) | |
| forward_to | string | required | Destination email address |
| keep_copy | boolean | optional | Keep a copy in the original mailbox too (default true) |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/forwarding/{rule_id}| Parameter | Type | Required | Description |
|---|---|---|---|
| enabled | boolean | required | Mail only actually forwards while enabled AND confirmed |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/forwarding/{rule_id}Aliases
https://api.kerabie.email/v1/hosting/mailboxes/{id}/aliases| Parameter | Type | Required | Description |
|---|---|---|---|
| page | integer | optional | Default 1 |
| page_size | integer | optional | Default 20, max 100 |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/aliases| Parameter | Type | Required | Description |
|---|---|---|---|
| mailbox | string | required | This mailbox's address (the delivery target) |
| alias_address | string | required | The new alias address |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/aliases/{alias_id}Signature & sender name
https://api.kerabie.email/v1/hosting/mailboxes/{id}/identity| Parameter | Type | Required | Description |
|---|---|---|---|
| display_name | string | optional | Name shown to recipients |
| signature_html | string | optional | HTML signature appended to outgoing mail |
Contacts
Requires the client's plan to include contacts (Pro and Premium both do) — 403s otherwise. Contacts belong to the client's account as a whole, not a specific mailbox.
https://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts| Parameter | Type | Required | Description |
|---|---|---|---|
| group_id | integer | optional | Filter to one group |
| q | string | optional | Search email, name, or company |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts| Parameter | Type | Required | Description |
|---|---|---|---|
| string | required | ||
| name | string | optional | |
| phone | string | optional | |
| company | string | optional | |
| notes | string | optional | |
| group_id | integer | optional |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts/{contact_id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts/{contact_id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts/groupshttps://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts/groups| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | required |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/contacts/groups/{group_id}Campaigns
Requires the client's plan to include campaigns (Pro and Premium both do) — 403s otherwise. A campaign starts as a single-step send; add more steps to turn it into a drip sequence.
https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaignshttps://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns| Parameter | Type | Required | Description |
|---|---|---|---|
| from_email | string | required | Must be this mailbox's address |
| name | string | required | Internal campaign name |
| subject | string | required | |
| body_html | string | required | |
| group_id | integer | optional | Send to one contact group |
| segment_filter | array | optional | Or send to a filtered segment — see the dashboard for the filter shape |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/stepshttps://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/steps| Parameter | Type | Required | Description |
|---|---|---|---|
| delay_hours | integer | optional | Hours after the previous step (default 0) |
| subject | string | required | |
| subject_b | string | optional | A/B variant subject |
| ab_split_percent | integer | optional | 0-100, default 50 |
| body_html | string | required |
https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/steps/{step_id}https://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/sendhttps://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/pausehttps://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/resumehttps://api.kerabie.email/v1/hosting/mailboxes/{id}/campaigns/{campaign_id}/statsAdd-ons
Two purchasable add-ons, billed once via Flutterwave (card or, for NGN accounts, direct bank transfer): extra domain slots, and extra per-mailbox storage. Mailbox count is a separate thing — see the slot pool purchase flow in the Partner dashboard.
https://api.kerabie.email/v1/hosting/addons/pricing{
"currency_code": "NGN",
"domain_slot_unit_price": 4000.0,
"storage_gb_unit_price": 800.0,
"domain_limit": 2,
"domains_used": 1,
"extra_storage_mb": 0
}https://api.kerabie.email/v1/hosting/addons/purchase| Parameter | Type | Required | Description |
|---|---|---|---|
| addon_type | string | required | "domain_slot" or "storage" |
| quantity | integer | required | Number of slots (domain_slot) or GB (storage) |
| payment_method | string | optional | "card" (default) or "bank_transfer" |
| return_url | string | required | Where the card checkout redirects back to |
https://api.kerabie.email/v1/hosting/addons/purchase/verify| Parameter | Type | Required | Description |
|---|---|---|---|
| reference | string | required | The reference returned from the purchase call |
Stats
https://api.kerabie.email/v1/hosting/stats{
"mailboxes_total": 12,
"mailboxes_by_status": { "active": 10, "expired": 2 },
"mailboxes_by_plan": { "pro": 8, "premium": 4 },
"slots_unused": 3,
"slots_assigned": 10,
"slots_expired": 2,
"domains_total": 4,
"domains_verified": 3,
"domains_pending": 1,
"domain_limit": 5,
"extra_storage_mb": 2048,
"pending_domain_setup": [
{ "domain_id": 7, "domain_name": "pending-client.com", "status": "pending", "dns_records": [ /* ... */ ] }
]
}https://api.kerabie.email/v1/hosting/summaryWebhooks
Hosting-partner events use the exact same delivery mechanism as the rest of the platform — HMAC-SHA256 signed, retried with exponential backoff. See the Webhooks docs for signature verification code and the retry schedule. Create endpoints from Partner Dashboard → Developer or POST /webhooks.
| Event | Triggered when |
|---|---|
| partner_mailbox.created | A mailbox is provisioned (dashboard or API) |
| partner_mailbox.deleted | A mailbox is deleted |
| partner_mailbox.renewed | A mailbox's term is renewed |
| partner_mailbox.expiring_soon | A paid mailbox's term ends in ~7 days |
| partner_domain.added | A client domain is claimed |
| partner_domain.verified | A domain passes DNS verification (first time only) |
| partner_domain.verification_failed | A verification check fails |
| partner_pool.purchased | A mailbox-slot pool purchase completes |
| partner_addon.purchased | A domain-slot or storage add-on purchase completes |
| partner_trial.expiring_soon | Your hosting trial ends in ~7 days |
| partner_mailbox.payment_confirmed | A pay-as-you-go client's payment clears (first payment or any renewal) |
| partner_mailbox.payment_failed | A pay-as-you-go client's renewal charge fails |
| partner_mailbox.expired | A pay-as-you-go client cancels |
| partner_mailbox.payment_abandoned | A pay-as-you-go mailbox's first payment was never completed within 7 days — it and its account were deleted |
Errors
| Code | Meaning |
|---|---|
| 400 | Bad request — e.g. invalid domain name, or provisioning on an unverified domain |
| 401 | Missing, invalid, revoked, or expired API key |
| 402 | Payment required — no mailbox slots, or domain limit reached |
| 403 | IP blocked/not allowlisted for this key, missing scope, or hosting account not active/trial |
| 404 | Resource not found (or not yours) |
| 409 | Domain already claimed, mailbox already exists, or domain still has mailboxes on it |