HonkIO Auth
Apps
Create sign-in apps, change their settings and branding, verify their domains, rotate secrets, and delete them.
Create an app
POST/v1/auth-apps
Permission: auth_apps: w
Creates a sign-in app on a hostname you own, in your key’s mode. The response lists the DNS records to publish and, for a confidential app, the client secret: it’s shown only here.
Body
| Name | Type | Description |
|---|---|---|
| hostnamerequired | string | A subdomain you control, such as login.acme.ca. It becomes the issuer. To move later, PATCH the app with a new hostname. |
| namerequired | string | The app name shown on the sign-in page, in emails and in texts. |
| redirect_urisrequired | string[] | Where sign-in may return to. Exact match, HTTPS, at most 10; http://localhost on test apps only. A PATCH replaces the list. |
| post_logout_redirect_uris | string[] | Where sign-out may return to. Same rules as redirect_uris. |
| confidential | boolean | true (the default) issues a client secret, shown once. false makes a public client with no secret. |
| plan | "free" | "pro" | "business" | The plan to start on: free (the default), pro or business. A live app on a paid plan pays its first monthly fee from your balance now; one live app per account can be on Free. |
curl -X POST https://api.honkio.ca/v1/auth-apps \
-H "Authorization: Bearer mk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"hostname": "login-dev.acme.ca",
"name": "Acme",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
]
}'{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#2b6cb0",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": null,
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z",
"client_secret": "hka_cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}List apps
GET/v1/auth-apps
Permission: auth_apps: r
Your apps in the key’s mode, newest first.
Query parameters
| Name | Type | Description |
|---|---|---|
| limit | integer | How many to return per page. |
| cursor | string | The next_cursor of the previous page. |
curl https://api.honkio.ca/v1/auth-apps \
-H "Authorization: Bearer mk_test_YOUR_KEY"{
"data": [
{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#2b6cb0",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": null,
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z"
}
],
"next_cursor": null
}Get an app
GET/v1/auth-apps/:id
Permission: auth_apps: r
One app, with its domain status and DNS records.
curl https://api.honkio.ca/v1/auth-apps/APP_ID \
-H "Authorization: Bearer mk_test_YOUR_KEY"{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#2b6cb0",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": null,
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z"
}Update an app
PATCH/v1/auth-apps/:id
Permission: auth_apps: m
Changes the fields you send. At least one sign-in method must stay on, and texts need Pro or Business and a verified number. A new hostname is sent on its own and waits in pending_hostname until its records check out; then the app switches to it.
Body
| Name | Type | Description |
|---|---|---|
| hostname | string | Moves the app to a new hostname you own. Send it on its own. The app keeps its users, client ID and secret, and keeps serving on its current hostname while the new one waits in pending_hostname: publish its DNS records, then verify. When its certificate is active the app switches: the issuer changes, every session ends, and passkeys made for a domain the new hostname doesn’t share stop working. hostname_change in the answer says how many. Needs a step-up from a dashboard session. |
| name | string | The app name shown on the sign-in page, in emails and in texts. |
| brand_color | string | A hex colour such as #2b6cb0. |
| redirect_uris | string[] | Where sign-in may return to. Exact match, HTTPS, at most 10; http://localhost on test apps only. A PATCH replaces the list. |
| post_logout_redirect_uris | string[] | Where sign-out may return to. Same rules as redirect_uris. |
| email_enabled | boolean | Sign-in by email code or link. |
| passkeys_enabled | boolean | Sign-in with a passkey. |
| texts_enabled | boolean | Sign-in by text code. Pro and Business, with sms_from_number_id set. A test app sends no texts and needs no number. |
| passkey_scope | "domain" | "hostname" | domain (the default) ties passkeys to your whole domain; hostname to the sign-in hostname alone. Changing it retires existing passkeys until you switch back; the answer gives their number in passkeys_retired. |
| sms_from_number_id | string | null | The ID of your verified HonkIO number that sends sign-in texts. |
| send_from_email_domain_id | string | null | The ID of a verified email sending domain to send sign-in email from; null uses signin.honkio.ca. |
curl -X PATCH https://api.honkio.ca/v1/auth-apps/APP_ID \
-H "Authorization: Bearer mk_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"brand_color": "#0f766e",
"passkeys_enabled": true
}'{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#0f766e",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": null,
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z"
}Upload a logo
PUT/v1/auth-apps/:id/logo
Permission: auth_apps: m
Replaces the logo on the sign-in page. Send PNG, JPEG, WebP or GIF up to 1 MB. HonkIO re-encodes it to PNG or WebP and serves it from a separate static origin; SVG isn’t accepted. A logo close to a protected brand goes to review.
Body: multipart/form-data with one file part named logo.
curl -X PUT https://api.honkio.ca/v1/auth-apps/APP_ID/logo \
-H "Authorization: Bearer mk_test_YOUR_KEY" \
-F "logo=@logo.png"{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#2b6cb0",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": "https://assets.signin.honkio.ca/logos/xxxxxxxxxxxx.webp",
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z"
}Remove the logo
DELETE/v1/auth-apps/:id/logo
Permission: auth_apps: d
The sign-in page goes back to the brand-colour mark. Returns the app.
curl -X DELETE https://api.honkio.ca/v1/auth-apps/APP_ID/logo \
-H "Authorization: Bearer mk_test_YOUR_KEY"{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#2b6cb0",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": null,
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z"
}Rotate the client secret
POST/v1/auth-apps/:id/rotate-secret
Permission: auth_apps: w
Issues a new client secret; the old one stops working at once. A public client answers AUTH_APP_PUBLIC_CLIENT.
curl -X POST https://api.honkio.ca/v1/auth-apps/APP_ID/rotate-secret \
-H "Authorization: Bearer mk_test_YOUR_KEY"{
"client_secret": "hka_cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}Verify the domain
POST/v1/auth-apps/:id/domain/verify
Permission: auth_apps: w
Checks the TXT and CNAME records and moves the app along: PENDING_DNS, PENDING_CERT, ACTIVE. A waiting hostname change is checked in the same call (pending_hostname); the app switches to it once its certificate is active. Call it as often as you like.
curl -X POST https://api.honkio.ca/v1/auth-apps/APP_ID/domain/verify \
-H "Authorization: Bearer mk_test_YOUR_KEY"{
"domain_status": "PENDING_CERT",
"found": {
"txt": true,
"cname": true
}
}Cancel a hostname change
DELETE/v1/auth-apps/:id/hostname-change
Permission: auth_apps: d
Drops the hostname the app was moving to, and its certificate. The app keeps its current hostname, issuer, sessions and passkeys. 404 when no change is waiting, including one that has already switched.
curl -X DELETE https://api.honkio.ca/v1/auth-apps/APP_ID/hostname-change \
-H "Authorization: Bearer mk_test_YOUR_KEY"{
"id": "clxxxappxxxxxxxxxxxxxxxxx",
"hostname": "login-dev.acme.ca",
"issuer": "https://login-dev.acme.ca",
"domain_status": "PENDING_DNS",
"dns_records": [
{
"type": "TXT",
"name": "_honkio-auth.login-dev.acme.ca",
"value": "honkio-auth=xxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"type": "CNAME",
"name": "login-dev.acme.ca",
"value": "edge.signin.honkio.ca"
}
],
"client_id": "hka_xxxxxxxxxxxx",
"redirect_uris": [
"http://localhost:3000/auth/callback"
],
"post_logout_redirect_uris": [
"http://localhost:3000/"
],
"mode": "test",
"brand_color": "#2b6cb0",
"name": "Acme",
"plan": "free",
"confidential": true,
"logo_url": null,
"name_review": "clear",
"email_enabled": true,
"passkeys_enabled": true,
"texts_enabled": false,
"passkey_scope": "hostname",
"sms_from_number_id": null,
"send_from_email_domain_id": null,
"pending_hostname": null,
"pending_txt_missing_since": null,
"previous_hostname": null,
"hostname_changed_at": null,
"created_at": "2026-11-02T15:04:05.000Z"
}Delete an app
DELETE/v1/auth-apps/:id
Permission: auth_apps: d
Deletes the app and releases its hostname at once; its sign-in page stops being served.
curl -X DELETE https://api.honkio.ca/v1/auth-apps/APP_ID \
-H "Authorization: Bearer mk_test_YOUR_KEY"204 · No content.
HonkIO