Help using state_attr in a REST sensor

This sensor works. (LAT-LON and API key obsfucated):

sensor:
  - platform: rest
    name: Geoapify Reverse Geocoding
    resource: https://api.geoapify.com/v1/geocode/reverse?lat=42.999983935546875&lon=-71.999900413753&format=json&apiKey=abcdefghijklmnopqrstuvwxya123456
    value_template: '{{ value_json.properties.city }} {{ value_json.properties.street }} {{ value_json.properties.housenumber }}'
    scan_interval:
      minutes: 1

I want to use the LAT-LON from the iphone entities in my API call.

In template:

iphone Latitude: {{state_attr('device_tracker.iphone','latitude') }}
iphone Longitude: {{state_attr('device_tracker.iphone','longitude') }}

returns:

iphone Latitude: 42.99995341796875
iphone Longitude: -71.99996355190287

I tried:

sensor:
  - platform: rest
    name: Geoapify Reverse Geocoding
    resource: https://api.geoapify.com/v1/geocode/reverse?lat={{state_attr('device_tracker.iphone','latitude') }}&lon={{state_attr('device_tracker.iphone','longitude') }}&format=json&apiKey=abcdefghijklmnopqwertyetc
    value_template: '{{ value_json.results[0].housenumber }} {{ value_json.results[0].street }}, {{ value_json.results[0].city }}'
    scan_interval:
      minutes: 1

But I am not getting any response.

Any tips would be appreciated.

value_template: "{{ value[:205] }}"

Sets the state to plain text response so you can see what is really being returned with your call. It stays under the state length limit in case the response is longer than that.

Then you can see what is actually coming back. Might show an error.

Thanks- That’s a great tip. Definitely going into my notebook.

Here’s what the result was:
{“statusCode”:400,“error”:“Bad Request”,“message”:“"lat" must be a number”}

Is it possible that state_attr is a string?

I added | float to the state_attr:

resource: https://api.geoapify.com/v1/geocode/reverse?lat={{state_attr('device_tracker.iphone','latitude') |  float}}&lon={{state_attr('device_tracker.iphone','longitude') | float }}&format=json&apiKey=c67cdd7eb310444ebe58c0511b446ae2

But I am still getting the same error.

Absolutely a great tip. Not mine. I just can’t remember who I saw give it first. Maybe troon or one of the masters.

Yes, state is string. Check the docs for the API against what you are sending. Does it only want a certain number of positions after the decimal?

I thought that might be it, but I replaces the state_attr with the actual lat & lon from the iphone entity, and the API works fine.

Since the error message doesn’t tell me what in the number is it that the API doesn’t like, can you think of a way to send it to a website I control instead of the API URL just to examine what non-numerics may lurk in the LAT and LON arguments?

Always start with Developer Tools | Template to see what would be sent by just putting out your states.

You can also use requestcatcher.com. It sets up xxxx.requestcatcher.com. You send your call there and it shows you what is being sent. There are several websites like this. I can’t remember the one I used before. But, this one came up on a Google search.

I’ve done that. This is where I got the lat-lon numbers to paste into the http API call.

How would I use requestcatcher from inside Home Assistant (because there is something wrong with the state_attr attributes)? The problem only appears when I put the state_attr entity attributes into the API call.

Update:
I wrote, with assistance from AI, a js script to tell me what the API call is sending.

With this sensor:

- platform: rest
  name: Geoapify Reverse Geocoding
  resource: http://192.168.1.83:3000/api?lat=42.555555341796875&lon=-71.555556355190287&format=json&apiKey=abcd
  value_template: '{{ value[:500] }}'
  scan_interval:
    minutes: 1

I get from my java script:

{
  lat: '42.55555341796875',
  lon: '-71.55555355190287',
  format: 'json',
  apiKey: 'abcd
}

When I try to send my state_attr attribute values:

- platform: rest
  name: Geoapify Reverse Geocoding
  resource: http://192.168.1.83:3000/api?lat={{state_attr('device_tracker.iphone','latitude') |  float}}&lon={{state_attr('device_tracker.iphone','longitude') | float }}&format=json&apiKey=abcd
  value_template: '{{ value[:500] }}'
  scan_interval:
    minutes: 1

The script returns:

{
  lat: "{{state_attr('device_tracker.iphone','latitude') |  float}}",
  lon: "{{state_attr('device_tracker.iphone','longitude') | float }}",
  format: 'json',
  apiKey: 'abcd'
}

In developer tools, template,

iphone Latitude: {{state_attr('device_tracker.iphone','latitude') | float }}
iphone Longitude: {{state_attr('device_tracker.iphone','longitude') | float}}

Shows this result:

iphone Latitude: 42.55555541796875
iphone Longitude: -71.55555355190287

What is happening here?

Quote your single line templates. Also it is resource_template if you need template support in the resource option. https://www.home-assistant.io/integrations/sensor.rest#resource_template

 resource_template: "http://192.168.1.83:3000/api?lat={{state_attr('device_tracker.iphone','latitude') |  float}}&lon={{state_attr('device_tracker.iphone','longitude') | float }}&format=json&apiKey=abcd"

Thanks.
I’m not clear what you meant here, but I tried this:

resource: "http://192.168.1.83:3000/api?lat={{state_attr('device_tracker.iphone','latitude') |  float}}&lon={{state_attr('device_tracker.iphone','longitude') | float }}&format=json&apiKey=abcd"

No difference, the api script is getting:

{
  lat: "{{state_attr('device_tracker.iphone','latitude') |  float}}",
  lon: "{{state_attr('device_tracker.iphone','longitude') | float }}",
  format: 'json',
  apiKey: 'efgh'
}

The resource_template never gets to the API endpoint.

Did you stop reading my comment after the first five words?

I even gave you the exact example:

 resource_template: "http://192.168.1.83:3000/api?lat={{state_attr('device_tracker.iphone','latitude') |  float}}&lon={{state_attr('device_tracker.iphone','longitude') | float }}&format=json&apiKey=abcd"

You are still using resource:

Sorry, I’ve been fighting this all day- I do appreciate the help.
Yes, I tried the resource_template you suggested, and in my last line I responded that when using the resource_template the API endpoint is never reached.

I also simplified the API call by only sending the latitude attribute.

resource_template: "http://192.168.1.83:3000/api?lat={{state_attr('device_tracker.iphone','latitude') | float}}&apiKey=abcd"

Here’s some interesting experiments.
I tried using a sensor state:
resource_template: "http://192.168.1.83:3000/api?lat={{states('sensor.4_in_1_sensor_x_humidity') }}&apiKey=abcd"

And it worked.

I added the float filter:
resource_template: "http://192.168.1.83:3000/api?lat={{states('sensor.4_in_1_sensor_x_humidity') | float }}&apiKey=abcd"

And it did not return anything. I remove ‘| float’ and it again works. ???

Bottom line- your suggestions did get me to the solution. Thank you.
Without the float filter, the full API call looks tight.

{
  lat: '42.55555341796875',
  lon: '-71.55556355190287',
  format: 'json',
  apiKey: 'abcd'
}

The float filter was an earlier attempt at a fix since the Geoapify API was returning an error 400 - lat was not a number. It wasn’t until I wrote the js script to see what the API call was getting, and that’s where post #8 information came from. The float filter may not even be needed in the Geoapify API call. That’s my next test.

Again, your input is appreciated.

I thought I was on to a solution… But…
This is my local API call:

- platform: rest
  name: Geoapify Local
  resource_template: "http://192.168.1.83:3000/api?lat={{state_attr('device_tracker.iphone','latitude')}}&lon={{state_attr('device_tracker.iphone','longitude')}}&format=json&apiKey=abcd"
  value_template: '{{ value_json.properties.housenumber }} {{ value_json.properties.street }}, {{ value_json.properties.city }}'
  scan_interval:
    seconds: 10

My API script gets this response:

{
  lat: '42.55555341796875',
  lon: '-71.55556355190287',
  format: 'json',
  apiKey: 'abcd'
}

Looks great. So, I replace my local API call with the Geoapify call and the correct API key:

- platform: rest
  name: Geoapify
  resource_template: "https://api.geoapify.com/v1/geocode/reverse?lat={{state_attr('device_tracker.iphone','latitude')}}&lon={{state_attr('device_tracker.iphone','longitude')}}&format=json&apiKey=xxxxxd7eb310444ebe58c0511b446ae2"
  value_template: '{{ value_json.properties.housenumber }} {{ value_json.properties.street }}, {{ value_json.properties.city }}'
  scan_interval:
    seconds: 10

And. nothing.

Changed the value_template: to
value_template: '{{ value[:200] }}'

And I see the same error that I started with:
{"statusCode":400,"error":"Bad Request","message":"\"lat\" must be a number"}

Sigh. Back to the beginning…

Could you try? The Geoapify API is free for 3000 calls per day, no credit card needed.

What is your end goal here?
Is it just to get the street you are at?

I get that from the Home Assistant app, there is a sensor called geocoded location.
Isn’t that what you need?

1 Like

To wrap this up. Sort of.
@Tom_in_HI, as usual your remarks do lead me to solutions and I appreciate it.

@Hellis81, I made a rookie mistake that I often criticize others for. I neglected to state at the beginning what my end goal was. That you figured out. :flushed:

Not all is lost, however. I learned more about API end points and using state_attr.

But I am still perplexed why this particular API call isn’t working…