Missing-required-parameter for post query with parameters

I am doing a post query to Metabase for a question which takes parameters. However, the query does not complete due to a missing-required-parameter error. Instead, the returned information from Metabase (some data omitted) is
{"database_id":X,"started_at":"2021-07-02T15:32:01.569753Z","error_type":"missing-required-parameter","json_query":{"constraints":null,"type":"native","middleware":{"skip-results-metadata?":true,"format-rows?":false,"js-int-to-string?":true},"native":{"template-tags":{"param1":{"id":"XXX","name":"param1","display-name":"param1","type":"number","required":false}},"query":"XXXX","database":X,"parameters":null,"async?":true,"cache-ttl":null},"status":"failed",................"context":"json-download","error":"Cannot run the query: missing required parameters: #{\"param1\"}","row_count":0,"running_time":0,"ex-data":{"type":"missing-required-parameter","missing":["param1"]},"data":{"rows":[],"cols":[]}}

I have reviewed Metabase forum posts 8113 and 11331 (apologies I cannot post links due to "new member limitations") discussing this issue, in addition to the docs to determine what causes the failure. It appears my syntax is correct, but perhaps I am missing something.

To run the query, I do the following after obtaining ${token} (in a bash script):
curl -X POST
-H "Content-Type: application/json"
-H "X-Metabase-Session: ${token}"
-d '{"parameters":[{"type":"category","target":["variable",["template-tag","param1"]],"value":"2064"}]}'

The format of the parameters data is identical to that in the "json_query" observed when running the Metabase query in the online UI in my browser's developer mode. At this point, I do not know why Metabase sees parameters as null. Any help is kindly appreciated, thank you!

Hi @rfen
The best way to learn the API, is to just use Metabase while having your browser developer Network-tab open and looking at the request, and what data is being send/received. You can right-click requests and copy directly as cURL.

Notice the Content-Type header, since it's a download, and the very different data encoding.

curl 'https://metabase.XXXXX.com/api/card/218/query/json' --compressed
-H 'Content-Type: application/x-www-form-urlencoded'
-H 'X-Metabase-Session: ${token}'
--data-raw 'parameters=%5B%7B%22type%22%3A%22category%22%2C%22value%22%3A%222064%22%2C%22target%22%3A%5B%22variable%22%2C%5B%22template-tag%22%2C%22param1%22%5D%5D%7D%5D'

Hi @flamber, thank you for the speedy reply. I just checked my browser developer Network tab again. I copied the request and pasted as cURL. The result is pasted here.

curl 'https://metabase.XXXXX.com/api/card/218/query' \
-H 'authority: metabase.XXXXX.com' \
-H 'sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"' \
-H 'accept: application/json' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36' \
-H 'content-type: application/json' \
-H 'origin: https://metabase.XXXXX.com' \
-H 'sec-fetch-site: same-origin' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-dest: empty' \
-H 'referer: https://metabase.XXXXX.com/question/218?param1=2064' \
-H 'accept-language: en-US,en;q=0.9' \
-H 'cookie: .......' \
--data-raw '{"ignore_cache":true,"parameters":[{"type":"category","target":["variable",["template-tag","param1"]],"value":"2064"}]}' \

Using the --data-raw and --compressed flags, and changing the Content-Type did not fix the issue for me. However, changing the URL to https://metabase.XXXXX.com/api/card/218/query did fix the issue. In fact, my original code works when I change the URL. For example this works (change bolded):

curl -X POST
-H "Content-Type: application/json"
-H "X-Metabase-Session: ${token}"
-d '{"parameters":[{"type":"category","target":["variable",["template-tag","param1"]],"value":"2064"}]}'

Are there any limitations with this and/or is .../query/json or ../query/csv supposed to work?

@rfen Post "Diagnostic Info" from Admin > Troubleshooting.

You are talking about two different endpoints - if you want the export, then it's this:
And read the note:

Note that this expects the parameters as serialized JSON in the 'parameters' parameter

I don't know what you are trying to do, but look in your browser console. There's nothing you can do in the Metabase GUI that isn't handled through the API, so you just copy those requests as cURL.

Thanks @flamber! I have solved the problem which is due (as usual) to a misunderstanding of the UI and API. The cURL request that I posted above does not specify an export-format and was the query captured when running the Metabase query in the browser via the Metabase UI. However, if I choose "Download Full Results" and select "CSV" from the Metabase UI, a different query is generated, one that specifies the export format. This query, as @flamber noted above is:
curl URL/query/csv
-H 'content-type: application/x-www-form-urlencoded'
--data-raw 'parameters=%5B%7B%22type%22%3A%22category%22%2C%22target%22%3A%5B%22variable%22%2C%5B%22template-tag%22%2C%22param1%22%5D%5D%2C%22value%22%3A%222064%22%7D%5D'
Note the different content-type, specification of export format /csv in the URL, and most importantly: the parameters in serialized JSON format, with all special characters escaped (with the exception of "parameters="). In Javascript, escaping can be performed on a stringified piece of JSON by using the encodeURIComponent() function. I consider the problem solved.