ESP32 Google Vision Face Detection request fail

The JSON in their example (with your image) is:

{
  "requests": [
    {
      "image": {
        "source": {
          "imageUri": "http://www.newdesignfile.com/postpic/2010/05/free-stock-photos-people_102217.jpg"
        }
       },
       "features": [
         {
           "maxResults": 10,
           "type": "FACE_DETECTION"
         }
       ]
    }
  ]
}

Put that in a file named "request.json". In that same directory, use the "curl" command to send it:

curl -v -X POST \ 
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://vision.googleapis.com/v1/images:annotate"

I don't have the 'gcloud' application so I end up with an Error 403: "Permission denied" since I don't have an API key but the logging of the messages might be informative:

zsh: command not found: gcloud
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 142.250.176.202...
* TCP_NODELAY set
* Connected to vision.googleapis.com (142.250.176.202) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=upload.video.google.com
*  start date: Aug 30 03:13:58 2021 GMT
*  expire date: Nov 22 03:13:57 2021 GMT
*  subjectAltName: host "vision.googleapis.com" matched cert's "*.googleapis.com"
*  issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1C3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7f8e71010a00)
> POST /v1/images:annotate HTTP/2
> Host: vision.googleapis.com
> User-Agent: curl/7.64.1
> Accept: */*
> Authorization: Bearer 
> Content-Type: application/json; charset=utf-8
> Content-Length: 298
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
* We are completely uploaded and fine
< HTTP/2 403 
< vary: X-Origin
< vary: Referer
< vary: Origin,Accept-Encoding
< content-type: application/json; charset=UTF-8
< date: Sun, 26 Sep 2021 00:25:39 GMT
< server: ESF
< cache-control: private
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< x-content-type-options: nosniff
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
< accept-ranges: none
< 
{
  "error": {
    "code": 403,
    "message": "The request is missing a valid API key.",
    "status": "PERMISSION_DENIED"
  }
}
* Connection #0 to host vision.googleapis.com left intact
* Closing connection 0

You probably just need to figure out what goes in the "Authorization: Bearer" header.