Help with RESTful API

I’m trying to use Toggl with my home assistant automations. I’d like certain automations to trigger an API that starts time tracking. For example, if I sit down at my desk I have an automation that triggers and turns on my desk lamp. I’d also like that automation to start a “Studying” timer in Toggl.

But I’m having issues with getting the API to work correctly. I keep getting a 403 error, and I think it’s because my header is incorrect. Would someone mind taking a look and let me know if there’s something missing? The documentation has a !secret header file so it’s not of any help. Thanks!

(Note that the XXXXXXXX is substituted with my API key)

rest_command:
  toggl_start:
    url: https://www.toggl.com/api/v8/time_entries/start
    method: POST
    headers:
      authentication: basic XXXXXXXXXXXX
      accept: application/json
    payload: ‘{“time_entry”:{“description”:”{{description}}”,”tags”:”{{tags}}”,”pid”:”{{pid}}”,”created_with”:”curl”}}’
    content_type: application/json
1 Like

Unless it’s a copy & paste typo, the quote characters in your payload template are the wrong ones. You have the fancy slanted/curly quotes – “ and ‘ – and you need the “normal” ones – " and '.

Don’t know if that’s your problem, or only problem, but worth checking.

A quick look at their API docs show that you should have :api_token following your API key.

rest_command:
  toggl_start:
    url: https://www.toggl.com/api/v8/time_entries/start
    method: POST
    headers:
      authentication: basic XXXXXXXXXXXX:api_token
      accept: application/json
    payload: ‘{“time_entry”:{“description”:”{{description}}”,”tags”:”{{tags}}”,”pid”:”{{pid}}”,”created_with”:”curl”}}’
    content_type: application/json

Hmmm thanks for the suggestions. Neither of those seemed to fix the issue with the 403 error. The API docs show:

curl -v -u 1971800d4d82861d8f2c1651fea4d212:api_token

Is the -u the same thing that gets passed through with the authentication: part of the YAML? I’m just noticing that the -u is not part of the header, so wondering if that’s something different I need to consider.

curl’s -u option I believe is for username & password. You might need to add the rest_command’s username and password config options.

Or maybe your api token is effectively your username, and “api_token” is effectively your password???

Digging a little deeper I found this in their docs:

For HTTP Basic Auth you have to add the Authorization header with the request. The Authorization header is constructed as follows:

  • Username and password are combined into a string username:password or if you use the api token it should be combined xxxx:api_token (xxx indicating user’s personal token)
  • The resulting string literal is then encoded using Base64
  • The authorization method and a space i.e. "Basic " is then put before the encoded string.
  • For example, if the user agent uses ‘Aladdin’ as the username and ‘open sesame’ as the password then the header is formed as follows: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

So you need to Base64 encode your xxxx:api_token string, and then pass that string with the Authorization: Basic header as shown above.

For others coming to this article with the same issue, it seems to work if you use the username and password variables instead.

rest_command:
  toggl_start:
    url: https://www.toggl.com/api/v8/time_entries/start
    method: POST
    username: <<API_CODE>>
    password: api_token
    payload: '{"time_entry":{"pid":<<PROJECT_ID>>,"created_with":"home_assistant"}}'
    content_type: application/json
1 Like

I just wanted to provide a small ‘update’.

In my configuration.yaml:

rest_command: !include_dir_merge_named devices/rest/

And in my devices/rest/toggl.yaml:


# Somebody did the initial work on a 'native' home assistant <-> toggle integration, but
#   as of 2020-11-26, it's quite minimal; only a single 'time tracked all week' sensor.
#
# I need to be able to start and stop timers and, at present, the only way to do this with home assistant is
#   with the native rest_command aka 'curl' integration. Each request is exposed to HA as a SERVICE
#   which means I can create a generic request that can either start or stop a request based on
#   the service data that is fed into it as the payload and URL fields support templating.
#
# See: https://www.home-assistant.io/integrations/rest_command/
# See: https://github.com/fredrikbaberg/ha-toggl/blob/47ef76dded1a547b0e00c549128e72a5c0d4a054/custom_components/toggl/sensor.py
# See: https://community.home-assistant.io/t/help-with-restful-api/92997/2
# See: https://github.com/toggl/toggl_api_docs/blob/43a7b7af20594b42945a1acffad066be05fc4e88/toggl_api.mds
##
# A 'generic' service to start or stop a toggle time entry
start_toggl_time_entry:
  # The start endpoint uses POST
  method: POST
  # Always verify TLS cert!
  verify_ssl: true
  # This HA component has built in support for HTTP/Basic auth.
  # The Toggle API docs are a bit weird about this, though.
  # User name is your API token and password is the string `api_token` 😕 🤷
  ##
  username: !secret toggl_api_token
  password: "api_token"
  # The API accepts only JSON requests.
  # Please make sure you're setting Content-Type: application/json in your request header.
  content_type: application/json
  url: https://www.toggl.com/api/v8/time_entries/start

  ##
  # See: https://github.com/toggl/toggl_api_docs/blob/43a7b7af20594b42945a1acffad066be05fc4e88/chapters/time_entries.md
  # Fortunately, the project ID is pretty easy to discover. It's in the URL on the web interface
  # E.G.: Go to the list of projects in your accouont and click on one, you'll be brought to
  #   a url like this: https://track.toggl.com/3123458/projects/112345626/team
  # So the project is '112345626'
  ##
  payload: '{"time_entry":{"description":"{{description}}","tags":["home_assistant"],"pid":{{pid}},"created_with":"home_assistant"}}'
##
# The Toggl API requires that you send along the exact time entity when making the STOP call.
# Unfortunately, there is no way for us to collect the ID of the created entity when we make the
#   rest call above. The reply from the request is discarded unless there's an error; then, it's only logged.
#
# It may be possible to hack something together using actual `curl` and `jq` to parse out the entity ID and
#   save the ID to a known location, but i'd rather fork the 'native' python extension that `fredrikbaberg`
#   started and implement things 'properly'. So for now, we're just going to implement the START service.
#
# As 'work around', the toggl API seems to automatically stop the current / running time entity when a new
#   one is created, so for most of the use-cases that I want to involve Home Assistant in, this behavior is
#   actually advantageous.
##


And then you just call the rest_command.start_toggl_time_entry service with a few required parameters:

  • pid - the project ID the entity is meant to appear under
  • description - the description / title of the thing.

I can’t make any promises about my ability to fork / work on the initial integration from fredrikbaberg, but the above rest service should get any other lost internet souls started.