Whitelabeling

Whitelabeling is one of the core functionality of the Kazoo which allows to make your own brand.

Schema

Whitelabel settings

KeyDescriptionTypeDefaultRequiredSupport Level
commland.downloads.debCommland debian download URL for the accountstring()false
commland.downloads.macCommland mac download URL for the accountstring()false
commland.downloads.rpmCommland rpm download URL for the accountstring()false
commland.downloads.windowsCommland windows download URL for the accountstring()false
commland.downloadsThe URLs of commland downloads related to the accountobject()false
commlandProperties related to commlandobject()false
company_nameThe company name to display to usersstring()falsesupported
conference_public_domainThis is the whitelabeled domain that conference participants can use to reach the conference through webphonestring()falsesupported
dkim_selectorThis is the selector that the receiving server should use to look up the DNS recordstring()falsesupported
domainThis is the whitelabeled domain that users will be entering to reach the UIstring()falsesupported
fake_api_urlThis is a whitelabeled API URL, primarily used by the developer applicationstring()falsebeta
hide_creditsWhen checked this hides the creditsboolean()falsefalsebeta
hide_poweredWhen checked this hides the powered by 2600Hz on the bottom rightboolean()falsefalsesupported
hide_registrationWhen checked this hides the ability to register for a new accountboolean()falsefalsebeta
inbound_trunks_priceThe price to show for inbound trunks, this is currently only for display purposesstring()falsebeta
nav.helpThe URL to use when the help link is clickedstring()falsesupported
nav.learn_moreThe URL to use when the ‘Learn More!’ link is clickedstring()falsesupported
navProperties related to navigation in the UIobject()false
outbound_trunks_priceThe price to show for outbound trunks, this is currently only for display purposesstring()falsebeta
port.authorityThe account ID to be used for administrating port requestsstring()falsesupported
port.featuresThe URL to use when the features link is clickedstring()falsesupported
port.loaThe URL to use when the LOA link is clickedstring()falsesupported
port.resporgThe URL to use when the resporg link is clickedstring()falsesupported
port.support_emailThe support email address to display to the userstring()falsesupported
port.termsThe URL to use when the terms and conditions link is clickedstring()falsesupported
portParameters related to white-labeling port requestsobject()false
twoway_trunks_priceThe price to show for twoway trunks, this is currently only for display purposesstring()falsebeta

Create a Whitelabel for an Account

PUT /v2/accounts/{ACCOUNT_ID}/whitelabel

curl -v -X PUT \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -d '{"data": {"company_name":"My VoIP Reseller Company", "domain":"mydomain.com"} }' \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel
{
    "data": {
        "company_name": "My VoIP Reseller Company",
        "domain": "mydomain.com",
        "hide_credits": false,
        "hide_powered": false,
        "hide_registration": false,
        "id": "whitelabel"
    },
    "status": "success"
}

You may fetch the whitelabel with GET:

GET /v2/accounts/{ACCOUNT_ID}/whitelabel

curl -v -X GET \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel

Response is same as create API.

Delete it:

DELETE /v2/accounts/{ACCOUNT_ID}/whitelabel

curl -v -X DELETE \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel

Response is same as create API.

Or modify it:

POST /v2/accounts/{ACCOUNT_ID}/whitelabel

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -d '{"data": {"company_name":"My VoIP Reseller Company", "domain":"mydomain.com"} }' \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel

Request and Response are same as create API.

Fetch Domains

GET /v2/accounts/{ACCOUNT_ID}/whitelabel/domains

When you whitelabel Kazoo’s services, DNS settings are needed to make sure your hostname maps appropriate for the various DNS entries (CNAM, A, NAPTR, etc). If the system admin has configured their settings on the backend, you can query Crossbar to show you what your settings should map to.

You have two options on the request for what domain to use:

  1. If you’ve already configured your whitelabel domain for the account, the API will use that value.
  2. If you specify domain=some.realm.com on the request, some.realm.com will be used instead.
curl -v -X GET \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/domains?domain=some.realm.com

OR

curl -v -X GET \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -d '{"data": {"domain": "some.realm.com"}}' \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/domains

Assuming your whitelabel domain is “mydomain.com” you should receive a payload similar to:

{
    "auth_token": "{AUTH_TOKEN}",
    "data": {
        "A": {
            "us-central.mydomain.com": {
                "mapping": [
                    "166.78.105.67"
                ],
                "name": "Secondary Proxy",
                "zone": "us-central"
            },
            "us-east.mydomain.com": {
                "mapping": [
                    "8.36.70.3"
                ],
                "name": "Primary Proxy",
                "zone": "us-east"
            },
            "us-west.mydomain.com": {
                "mapping": [
                    "8.30.173.3"
                ],
                "name": "Tertiary Proxy",
                "zone": "us-west"
            }
        },
        "CNAM": {
            "api.mydomain.com": {
                "mapping": [
                    "api.zswitch.net"
                ],
                "name": "API"
            },
            "portal.mydomain.com": {
                "mapping": [
                    "ui.zswitch.net"
                ],
                "name": "Web GUI"
            }
        },
        "MX": {},
        "NAPTR": {
            "proxy-central.mydomain.com": {
                "mapping": [
                    "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.proxy-central.mydomain.com."
                ],
                "name": "Central NAPTR"
            },
            "proxy-east.mydomain.com": {
                "mapping": [
                    "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.proxy-east.mydomain.com."
                ],
                "name": "East NAPTR"
            },
            "proxy-west.mydomain.com": {
                "mapping": [
                    "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.proxy-west.mydomain.com."
                ],
                "name": "West NAPTR"
            }
        },
        "SRV": {
            "_sip._udp.proxy-east.mydomain.com": {
                "mapping": [
                    "10 10 7000 us-east.mydomain.com.",
                    "15 15 7000 us-central.mydomain.com.",
                    "20 20 7000 us-west.mydomain.com."
                ],
                "name": "East SRV"
            }
        },
        "TXT": {}
    },
    "request_id": "{REQUEST_ID}",
    "revision": "{REVISION}",
    "status": "success"
}

Here you can see which DNS records are supported and where they should point to access the Kazoo cluster.

Testing your domains

POST /v2/accounts/{ACCOUNT_ID}/whitelabel/domains

Kazoo will attempt to validate your whitelabel settings if you send it a POST to do so:

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/domains

Similar to the GET, you can include a domain= parameter in the request to test your domains before you create the whitelabel document. A sample response is below:

{
    "auth_token": "{AUTH_TOKEN}",
     "data": {
         "A": {
             "us-central.r1.244.com": {
                 "actual": [
                     "{IP_ADDRESS}"
                 ],
                 "expected": [
                     "166.78.105.67"
                 ],
                 "name": "Secondary Proxy"
             },
             "us-east.r1.244.com": {
                 "actual": [
                     "{IP_ADDRESS}"
                 ],
                 "expected": [
                     "8.36.70.3"
                 ],
                 "name": "Primary Proxy"
             },
             "us-west.r1.244.com": {
                 "actual": [
                     "{IP_ADDRESS}"
                 ],
                 "expected": [
                     "8.30.173.3"
                 ],
                 "name": "Tertiary Proxy"
             }
         },
         "CNAM": {
             "api.r1.244.com": {
                 "actual": [],
                 "expected": [
                     "api.zswitch.net"
                 ],
                 "name": "API"
             },
             "portal.r1.244.com": {
                 "actual": [],
                 "expected": [
                     "ui.zswitch.net"
                 ],
                 "name": "Web GUI"
             }
         },
         "MX": {},
         "NAPTR": {
             "proxy-central.r1.244.com": {
                 "actual": [],
                 "expected": [
                     "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.proxy-central.r1.244.com."
                 ],
                 "name": "Central NAPTR"
             },
             "proxy-east.r1.244.com": {
                 "actual": [],
                 "expected": [
                     "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.proxy-east.r1.244.com."
                 ],
                 "name": "East NAPTR"
             },
             "proxy-west.r1.244.com": {
                 "actual": [],
                 "expected": [
                     "10 100 \"S\" \"SIP+D2U\" \"\" _sip._udp.proxy-west.r1.244.com."
                 ],
                 "name": "West NAPTR"
             }
         },
         "SRV": {
             "_sip._udp.proxy-east.r1.244.com": {
                 "actual": [],
                 "expected": [
                     "10 10 7000 us-east.r1.244.com.",
                     "15 15 7000 us-central.r1.244.com.",
                     "20 20 7000 us-west.r1.244.com."
                 ],
                 "name": "East SRV"
             }
         },
         "TXT": {}
     },
     "request_id": "{REQUEST_ID}",
     "revision": "{REVISION}",
     "status": "success"
}

You should be able to compare your hosts in each DNS type against the expected values configured by the system admin and adjust your DNS settings as appropriate.

Configuring the Domains (System Administrators only)

System administrators can set/update the domains object that is used when resellers whitelabel the service. The generic format of the JSON object is:

{
    "{DNS_RECORD_TYPE}":{
        "{WHITELABEL_ABLE_DOMAIN}":{
            "mapping":["{IP_ADDRESS}", "{SRV_RECORD}", "{NAPTR_RECORD}"],
            "name":"Friendly name",
            "zone":"{KAZOO_ZONE}"
        }
     }
    }
  • {DNS_RECORD_TYPE}: In all uppercase, the DNS record type. “CNAM”, “A”, “SRV”, “MX”, etc, that you have defined.
  • {WHITELABEL_ABLE_DOMAIN}: The template for what the hostname will look like when whitelabeled. The only template parameter is {{domain}}, which will be replaced by the whitelabel domain of the reseller.
  • mapping: This is a list of records the reseller should use when configuring their DNS entries for this DNS record type. It could be a list of IP addresses for CNAM or A, or listings of NAPTR/SRV records. Again, the mappings can use the {{domain}} placeholder for the whitelabeled domain.
  • {KAZOO_ZONE}: what zone this host is located in. If using dedicated IPs for the reseller, this will help when building the IP addresses usable by the reseller. Currently, however, this is purely informational.

To set the system domains object, the API is:

POST /v2/whitelabel/domains

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -d '{"data": {DOMAINS_OBJECT}}' \
    http://{SERVER}:8000/v2/whitelabel/domains

Where {DOMAINS_OBJECT} is the JSON. If you look at the default domains fixture for a good base JSON object to modify to your needs.

If you receive a 400 when POSTing with a response like:

{
    "auth_token": "{AUTH_TOKEN}",
     "data": {
         "domains": {
             "required": {
                 "message": "The domains schema is missing, unable to validate request"
             }
         }
     },
     "error": "400",
     "message": "invalid data",
     "request_id": "{REQUEST_ID}",
     "status": "error"
    }

You will need to run sup kapps_maintenance refresh system_schemas to ensure the domains schema is available.

POST /v2/accounts/{ACCOUNT_ID}/whitelabel/logo

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: image/png' \
    --data-binary "@/local/path/to/logo.png" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/logo

To tie the logo to a specific domain, rather than the account, use:

POST /v2/whitelabel/{domain}/logo

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: image/png' \
    --data-binary "@/local/path/to/logo.png" \
    http://{SERVER}:8000/v2/whitelabel/mydomain.com/logo

This returns the logo image file data.

GET /v2/accounts/{ACCOUNT_ID}/whitelabel/logo

Or domain specific:

GET /v2/whitelabel/{domain}/logo

Uploading a Custom Icon

POST /v2/accounts/{ACCOUNT_ID}/whitelabel/icon

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: image/png' \
    --data-binary "@/local/path/to/icon.png" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/icon

To tie the icon to a specific domain, rather than the account, use:

POST /v2/whitelabel/{domain}/icon

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: image/png' \
    --data-binary "@/local/path/to/icon.png" \
    http://{SERVER}:8000/v2/whitelabel/mydomain.com/icon

Fetch Custom Icon

This returns the icon image file.

GET /v2/accounts/{ACCOUNT_ID}/whitelabel/icon

Or domain specific:

GET /v2/whitelabel/{domain}/icon

Uploading a Custom Welcome

POST /v2/accounts/{ACCOUNT_ID}/whitelabel/welcome

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: text/html' \
    --data-binary "@/local/path/to/welcome.html" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/welcome

To tie the welcome to a specific domain, rather than the account, use:

POST /v2/whitelabel/{domain}/welcome

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: text/html' \
    --data-binary "@/local/path/to/welcome.html" \
    http://{SERVER}:8000/v2/whitelabel/mydomain.com/welcome

Fetch Custom Welcome

This returns the welcome html file.

GET /v2/accounts/{ACCOUNT_ID}/whitelabel/welcome

Or domain specific:

GET /v2/whitelabel/{domain}/welcome

Uploading the PEM file for DKIM Signing

DKIM (DomainKeys Identified Mail) lets domain owners “sign” emails from their domain. This allows receiving email servers to verify that the email came from the domain it purports to, by fetching the public key from a DNS TXT record and verifying the signature.

DKIM DNS TXT record

The name of a DKIM entry follows the format of [selector]._domainkey.[domain] where selector is what you enter for the dkim_selector in the whitelabel document. domain is, your domain name set in the whitelabel document as well.

The content of the TXT record looks like v=DKIM1; p=[public key]. v is DKIM1 and p is the public key that is the complement to the private key uploaded here.

Read RFC6376 for more on DKIM.

Uploading the DKIM private key

POST /v2/accounts/{ACCOUNT_ID}/whitelabel/dkim_key

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -H 'Content-Type: application/x-pem-file' \
    --data-binary "@/local/path/to/pvt_file.pem" \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/dkim_key

The file should be a plaintext PEM file (like what’s generated from openssl genrsa -out private-key.pem 1024 or similar).

Note

Once the PEM file is uploaded successfully, it will not be fetchable via API again.

Subsequent POSTs to upload another PEM file will cause the existing PEM file to not be available (so most recently uploaded PEM file is the actively used one).

Once the PEM file is uploaded successfully, you can provide a friendly name for the file, using below POST request.

curl -v -X POST \
    -H "X-Auth-Token: {AUTH_TOKEN}" \
    -d '{"data": {"name":"mypemfile"} }' \
    http://{SERVER}:8000/v2/accounts/{ACCOUNT_ID}/whitelabel/dkim_key

Fetch DKIM PEM file information

This returns ONLY the friendly name (name) of the PEM file.

GET /v2/accounts/{ACCOUNT_ID}/whitelabel/dkim_key

Assuming your PEM file name is “mypemfile”, you should receive a payload similar to:

{
  "auth_token": "{AUTH_TOKEN}",
  "data": [
    {
      "name": "mypemfile"
    }
    "..."
  ],
  "timestamp": "{TIMESTAMP}",
  "version": "{VERSION}",
  "node": "{NODE_HASH}",
  "request_id": "{REQUEST_ID}",
  "status": "success"
}

Remove DKIM PEM file information

This removes the PEM file. DKIM signing will no longer be available until a new private key is uploaded.

DELETE /v2/accounts/{ACCOUNT_ID}/whitelabel/dkim_key