Jacuzzi - Arctic Spas API

Hi I am Paul, and I’d love to be able to finally access my spas API key. I know your probably sick of people asking but if you could send me your contacts email address I’d really appreciate it. Thank you

1 Like

They have added more functionality to the API now, I’ve added a couple of gauges for pH and chlorine levels now as well.

CL Low : orp below 400
CL Low-OK : orp in the range between 400 and 500
CL OK : orp in the range between 500 and 750
CL OK-High : orp in the range of 750 and 900
CL High : orp greater than 900

pH Low : below 680
pH Low-OK : 680 to 720
pH OK : 720 to 780
pH OK-High : 780 to 820
pH High : greater than 820

configuration.yaml

rest:
  - resource: https://api.myarcticspa.com/v2/spa/status
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    method: GET
    scan_interval: 60
    sensor:
      - name: "Spa PH level"
        value_template: "{{ value_json.ph }}"
      - name: "Spa PH status"
        value_template: "{{ value_json.ph_status }}"
      - name: "Spa chlorine level"
        value_template: "{{ value_json.orp }}"
      - name: "Spa chlorine status"
        value_template: "{{ value_json.orp_status }}"

Gauge cards

type: gauge
entity: sensor.spa_ph_level
name: Spa pH level
max: 8.8
min: 6.2
needle: true
segments:
  - from: 6.2
    color: '#db4437'
  - from: 6.8
    color: '#ffa600'
  - from: 7.2
    color: '#43a047'
  - from: 7.8
    color: '#ffa600'
  - from: 8.2
    color: '#db4437'

type: gauge
entity: sensor.spa_chlorine_level
name: Spa chlorine level
max: 950
min: 350
needle: true
segments:
  - from: 350
    color: '#db4437'
  - from: 400
    color: '#ffa600'
  - from: 500
    color: '#43a047'
  - from: 750
    color: '#ffa600'
  - from: 900
    color: '#db4437'

This is great, do you mind posting your entire config for the tub. I could would also appreciate the contact to request the API key access.

Thank you.

Sent the mail address by PM.

configuration.yaml

rest:
  - resource: https://api.myarcticspa.com/v2/spa/status
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    method: GET
    scan_interval: 60
    sensor:
      - name : "Spa Temperature"
        value_template: "{{ ((value_json.setpointF -32)|float(0) * 0.5556)|round(0)|int(0) }}"
        unit_of_measurement: "°C"
        device_class: temperature
      - name: "Spa Temperature Setpoint"
        value_template: "{{ ((value_json.setpointF -32)|float(0) * 0.5556)|round(0)|int(0) }}"
        unit_of_measurement: '°C'
        device_class: temperature
      - name: "Spa PH level"
        value_template: "{{ value_json.ph }}"
      - name: "Spa PH status"
        value_template: "{{ value_json.ph_status }}"
      - name: "Spa chlorine level"
        value_template: "{{ value_json.orp }}"
      - name: "Spa chlorine status"
        value_template: "{{ value_json.orp_status }}"
    binary_sensor:
      - name: "Spa Status"
        value_template: "{{ value_json.connected }}"
        device_class: connectivity
      - name: "Spaboy Status"
        value_template: "{{ value_json.spaboy_connected }}"
        device_class: connectivity
      - name: "Spa Lights"
        value_template: "{{ value_json.lights|bool }}"
        device_class: power
      - name: "Spa Pump 1 Low"
        value_template: "{{ value_json.pump1 == 'low' }}"
        device_class: power
      - name: "Spa Pump 1"
        value_template: "{{ value_json.pump1 == 'high' }}"
        device_class: power
      - name: "Spa Pump 2"
        value_template: "{{ value_json.pump2 == 'high' }}"
        device_class: power
      - name: "Spa Pump 3"
        value_template: "{{ value_json.pump3 == 'high' }}"
        device_class: power
      - name: "Spa Pump 4"
        value_template: "{{ value_json.pump4 == 'high' }}"
        device_class: power
      - name: "Spa SDS"
        value_template: "{{ value_json.sds }}"
        device_class: power

rest_command:
  spa_lights_on:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_lights_off:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_sds_on:
    url: "https://api.myarcticspa.com/v2/spa/sds"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_sds_off:
    url: "https://api.myarcticspa.com/v2/spa/sds"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_1_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_1_low:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "low"}'

  spa_pump_1_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_2_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/2"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_2_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/2"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_3_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/3"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_3_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/3"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_4_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/4"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_4_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/4"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_set_temperature:
    url: "https://api.myarcticspa.com/v2/spa/temperature"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"setpointF": {{ (states("input_number.spa_set_temperature")|float(0) * 1.8 + 32 )|round(0)|int(0) }} }'

switch:
  - platform: template
    switches:
      spa_lights:
        friendly_name: Spa Lights
        value_template: "{{ states('binary_sensor.spa_lights') }}"
        turn_on:
          - service: rest_command.spa_lights_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_lights # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_lights_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_lights # force the rest sensor to update rather than waiting for the scan interval
        icon_template: >
          {% if is_state('binary_sensor.spa_lights', 'on') %}
            mdi:lightbulb-on
          {% else %}
            mdi:lightbulb-off
          {% endif %}
      spa_pump_1:
        friendly_name: Spa Pump 1
        value_template: "{{ states('binary_sensor.spa_pump_1') }}"
        turn_on:
          - service: rest_command.spa_pump_1_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1 # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_1_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_1', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_pump_1_low:
        friendly_name: Spa Pump 1 Low
        value_template: "{{ states('binary_sensor.spa_pump_1_low') }}"
        turn_on:
          - service: rest_command.spa_pump_1_low
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1_low # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_1_off
          - delay: 2 # Larger delay because it goes to high before it turns off
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_1_low
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_1', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_pump_2:
        friendly_name: Spa Pump 2
        value_template: "{{ states('binary_sensor.spa_pump_2') }}"
        turn_on:
          - service: rest_command.spa_pump_2_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_2 # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_2_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_2
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_2', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_pump_3:
        friendly_name: Spa Pump 3
        value_template: "{{ states('binary_sensor.spa_pump_3') }}"
        turn_on:
          - service: rest_command.spa_pump_3_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_3 # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_pump_3_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_pump_3
        icon_template: >
          {% if is_state('binary_sensor.spa_pump_3', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
      spa_sds:
        friendly_name: Spa SDS
        value_template: "{{ states('binary_sensor.spa_sds') }}"
        turn_on:
          - service: rest_command.spa_sds_on
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_sds # force the rest sensor to update rather than waiting for the scan interval
        turn_off:
          - service: rest_command.spa_sds_off
          - delay: 1
          - service: homeassistant.update_entity
            entity_id: binary_sensor.spa_sds
        icon_template: >
          {% if is_state('binary_sensor.spa_sds', 'on') %}
            mdi:water
          {% else %}
            mdi:water-off
          {% endif %}
input_number:
  spa_set_temperature:
    name: Spa Set Temperature
    min: 35
    max: 40
    step: 0.5
    unit_of_measurement: "°C"
    icon: mdi:thermometer

from the dashboard:

  - theme: Backend-selected
    icon: mdi:bathtub
    title: Jacuzzi
    path: jacuzzi
    badges: []
    cards:
      - type: vertical-stack
        cards:
          - type: entities
            entities:
              - entity: switch.spa_lights
              - entity: sensor.spa_temperature
              - entity: sensor.spa_ph_status
              - entity: sensor.spa_chlorine_status
              - entity: input_number.spa_set_temperature
              - entity: switch.spa_pump_1
              - entity: switch.spa_pump_1_low
              - entity: switch.spa_pump_2
              - entity: switch.spa_pump_3
              - entity: switch.spa_sds
      - type: gauge
        entity: sensor.spa_ph_level
        name: Spa pH level
        max: 8.8
        min: 6.2
        needle: true
        segments:
          - from: 6.2
            color: '#db4437'
          - from: 6.8
            color: '#ffa600'
          - from: 7.2
            color: '#43a047'
          - from: 7.8
            color: '#ffa600'
          - from: 8.2
            color: '#db4437'
      - type: gauge
        entity: sensor.spa_chlorine_level
        name: Spa chlorine level
        max: 950
        min: 350
        needle: true
        segments:
          - from: 350
            color: '#db4437'
          - from: 400
            color: '#ffa600'
          - from: 500
            color: '#43a047'
          - from: 750
            color: '#ffa600'
          - from: 900
            color: '#db4437'

Great work, thx got it all working except for the PH and Clorine graphs.

What’s the code string to leave it in F and not convert it?

I got everything working except for setting temperature. It will not adjust.

I can give it a shot :slight_smile:

you need to modify the temperature sensor “Spa Temperature” to use the fahrenheit value from the API without modifying it, and change the unit_of_measurement to fahrenheit.

      - name : "Spa Temperature"
        value_template: "{{ value_json.setpointF }}"
        unit_of_measurement: "°F"
        device_class: temperature

You have to modify payload for the spa_set_temperature so it don’t modify the value from the input_number.

  spa_set_temperature:
    url: "https://api.myarcticspa.com/v2/spa/temperature"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"setpointF": {{ (states("input_number.spa_set_temperature") }} }'

You have to modify the input_number spa_set temperature min, max, step should be 1 and unit_of_mesaurement should be fahrenheit.

input_number:
  spa_set_temperature:
    name: Spa Set Temperature
    min: 95
    max: 104
    step: 1
    unit_of_measurement: "°F"
    icon: mdi:thermometer

you also need an automation to update the rest api when changing the value.

alias: Set Spa Temperature
description: ""
trigger:
  - platform: state
    entity_id:
      - input_number.spa_set_temperature
condition: []
action:
  - service: rest_command.spa_set_temperature
    data: {}
mode: single

Playing around with GUI now. I’m using picture element to control the pumps and light.

type: vertical-stack
cards:
  - type: picture-elements
    elements:
      - type: state-icon
        entity: switch.spa_lights
        style:
          top: 48%
          left: 48%
          transform: scale(2,2)
        tap_action:
          action: toggle
      - type: state-icon
        entity: switch.spa_pump_3
        style:
          top: 67%
          left: 30%
          transform: scale(2,2)
        tap_action:
          action: toggle
      - type: state-icon
        entity: switch.spa_sds
        style:
          top: 28%
          left: 30%
          transform: scale(2,2)
        tap_action:
          action: toggle
      - type: state-icon
        entity: switch.spa_pump_1
        style:
          top: 48%
          left: 30%
          transform: scale(2,2)
        tap_action:
          action: toggle
      - type: state-icon
        entity: switch.spa_pump_2
        style:
          top: 28%
          left: 60%
          transform: scale(2,2)
        tap_action:
          action: toggle
    image: /local/arcticspas/kodiak.png
  - type: horizontal-stack
    cards:
      - type: gauge
        entity: sensor.spa_ph_level
        name: Spa pH level
        max: 8.8
        min: 6.2
        needle: true
        segments:
          - from: 6.2
            color: '#db4437'
          - from: 6.8
            color: '#ffa600'
          - from: 7.2
            color: '#43a047'
          - from: 7.8
            color: '#ffa600'
          - from: 8.2
            color: '#db4437'
      - type: gauge
        entity: sensor.spa_chlorine_level
        name: Spa chlorine level
        max: 950
        min: 350
        needle: true
        segments:
          - from: 350
            color: '#db4437'
          - from: 400
            color: '#ffa600'
          - from: 500
            color: '#43a047'
          - from: 750
            color: '#ffa600'
          - from: 900
            color: '#db4437'
  - type: entities
    entities:
      - entity: sensor.spa_temperature
      - entity: input_number.spa_set_temperature
      - entity: weather.my_place
        name: Current Weather
        secondary_info: none

This is awesome! If you can PM me the contact at Arctic for the API access that would be great! I have been looking at ways to integrate since i got my spa 3 months ago.

1 Like

Wow !! Is it possible for you to sent me the whole setup and the contact at arctic so i can get the API access.
Do you have any plans to make a integration in HA

1 Like

Hei :slight_smile:

Vært supert om du vil sende epost til han du fikk API key av!

Mvh Eirik

1 Like

This is great stuff you guys are doing here ! If anyone can PM me the email address to request access to the API, I’d be thankful !

1 Like

Many thanks for all contributors - got this working - here is an extended (more data from the API) and little modified REST part of configuration.yaml (for 2 pump model without SDS:):

rest:
  - resource: https://api.myarcticspa.com/v2/spa/status
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    method: GET
    scan_interval: 60
    sensor:
      - name : "Spa Temperature"
        value_template: "{{ ((value_json.setpointF -32)|float(0) * 0.5556)|round(0)|int(0) }}"
        unit_of_measurement: "°C"
        device_class: temperature
      - name: "Spa Temperature Setpoint"
        value_template: "{{ ((value_json.setpointF -32)|float(0) * 0.5556)|round(0)|int(0) }}"
        unit_of_measurement: '°C'
        device_class: temperature
      - name: "Spa PH level"
        value_template: "{{ value_json.ph }}"
        device_class: water
      - name: "Spa PH status"
        value_template: "{{ value_json.ph_status }}"
        device_class: water
      - name: "Spa chlorine level"
        value_template: "{{ value_json.orp }}"
        device_class: water
      - name: "Spa chlorine status"
        value_template: "{{ value_json.orp_status }}"
        device_class: water
      - name: "Spa filtration status"
        value_template: "{{ value_json.filter_status }}"
        device_class: water
      - name: "Spa filtration duration"
        value_template: "{{ value_json.filtration_duration }}"
        device_class: water
      - name: "Spa filtration frequency"
        value_template: "{{ value_json.filtration_frequency }}"
        device_class: water
    binary_sensor:
      - name: "Spa Connection Status"
        value_template: "{{ value_json.connected }}"
        device_class: connectivity
      - name: "Spaboy Status"
        value_template: "{{ value_json.spaboy_connected }}"
        device_class: connectivity
      - name: "Spaboy producing"
        value_template: "{{ value_json.spaboy_producing }}"
      - name: "Spa Lights"
        value_template: "{{ value_json.lights|bool }}"
        device_class: power
      - name: "Spa Pump 1 Low"
        value_template: "{{ value_json.pump1 == 'low' }}"
        device_class: power
      - name: "Spa Pump 1"
        value_template: "{{ value_json.pump1 == 'high' }}"
        device_class: power
      - name: "Spa Pump 2"
        value_template: "{{ value_json.pump2 == 'high' }}"
        device_class: power
      - name: "Spa filter suspension"
        value_template: "{{ value_json.filter_suspension }}"
rest_command:
  spa_lights_on:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_lights_off:
    url: "https://api.myarcticspa.com/v2/spa/lights"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_1_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_1_low:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "low"}'

  spa_pump_1_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/1"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_pump_2_on:
    url: "https://api.myarcticspa.com/v2/spa/pumps/2"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "on"}'

  spa_pump_2_off:
    url: "https://api.myarcticspa.com/v2/spa/pumps/2"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"state": "off"}'

  spa_set_temperature:
    url: "https://api.myarcticspa.com/v2/spa/temperature"
    method: PUT
    headers: 
      X-API-KEY: !secret arctic_spa_apikey
      Content-Type: application/json
    payload: '{"setpointF": {{ (states("input_number.spa_set_temperature")|float(0) * 1.8 + 32 )|round(0)|int(0) }} }'
input_number:
  spa_set_temperature:
    name: Spa Set Temperature
    min: 33
    max: 40
    step: 0.5
    unit_of_measurement: "°C"
    icon: mdi:thermometer

And jhere a single card yaml for the same config - including more data

title: Arctic spa poreamme
cards:
  - type: entities
    entities:
      - entity: switch.spa_lights
      - entity: sensor.spa_temperature
      - entity: sensor.spa_ph_status
      - entity: sensor.spa_chlorine_status
      - entity: binary_sensor.spaboy_status
      - entity: binary_sensor.spaboy_producing
      - entity: input_number.spa_set_temperature
      - entity: switch.spa_pump_1
      - entity: switch.spa_pump_1_low
      - entity: switch.spa_pump_2
      - entity: sensor.spa_filtration_status
      - entity: sensor.spa_filtration_duration
      - entity: sensor.spa_filtration_frequency
  - type: gauge
    entity: sensor.spa_ph_level
    name: Spa pH level
    max: 8.8
    min: 6.2
    needle: true
    segments:
      - from: 6.2
        color: '#db4437'
      - from: 6.8
        color: '#ffa600'
      - from: 7.2
        color: '#43a047'
      - from: 7.8
        color: '#ffa600'
      - from: 8.2
        color: '#db4437'
  - type: gauge
    entity: sensor.spa_chlorine_level
    name: Spa chlorine level
    max: 950
    min: 350
    needle: true
    segments:
      - from: 350
        color: '#db4437'
      - from: 400
        color: '#ffa600'
      - from: 500
        color: '#43a047'
      - from: 750
        color: '#ffa600'
      - from: 900
        color: '#db4437'

1 Like

I just contacted Arctic Spas support. They contacted my dealer, who confirmed what email address I registered under, and passed it along They will put a link to getting the API key in your account.

I figure this is better than all of us asking to be PM’ed. It took only 1 business day.

2 Likes

Hello all, is anyone figured out how to control blower?
Br J.

My API key does not seem to allow me access to my Spa Boy. Has anyone else found this please? It works fine in the official Arctic Spa app and via the web.

PM me with access contact please

For all those seeking the API key, you can contact Arctic Spa’s support through this page https://www.arcticspas.ca/en/contact/

They’ll reach to you within 24h by email to have the API access activated for your account. You’ll be then able to generate your own API key through the myarcticspa web portal !

I’m considering a purchase of an Arctic Spa and cloudless control is important to me. Is the api.myarcticspa.com DNS for your local spa, or does it require an Internet connection to talk to the cloud-based mothership?

1 Like