Skip to main content
Solved

Restful API Report digesting JSON

  • March 13, 2025
  • 0 replies
  • 446 views

JimHarrison
Forum|alt.badge.img+18

I really want to batch UPSERT to a unique field in Pipelines.

I am using RestfulAPI to get a report ~ the data is filtered at the source. 
ChatGPT has shown me {{b.json.metadata.totalRecords > 0 }} is how I know my report has values.

I want to iterate over the JSON, Restful API returns JSON ... I cannot select the Restful API as an input for the iterate step. 

Why must I add a FetchJSON step in front of the iterate step and essentially move the values from the Restful output to the fetch and then to the iterate?

 

Best answer by JimHarrison

Here is my working solution, I need to test it and verify it works all the time. 

First use a Restful API Report step to get the data>

I used these API call below in this recipe. 
api.quickbase.com/v1/reports/369/run?tableId=bje35c29w

https://422a9c520eb5b465e7b32cf16982ed96.m.pipedream.net

https://api.quickbase.com/v1/records

Above is the report QID, below is the output.

Type:action

Channel:quickbase

Index:b

Pipeline:HR: Employees: PG Onboarding: Clear Dates

Step:Restful API Report

Run timestamp:Thu Mar 13 2025 08:41:46 GMT-0700 (Pacific Daylight Time)

 

Input

url:https://api.quickbase.com/v1/reports/369/run?tableId=bje35c29w

method:POST

 

headers

 

name:QB-Realm-Hostname

value:hardermech.quickbase.com

content_type:application/json

disable_ssl_verification:false

 

Output

url:https://api.quickbase.com/v1/reports/369/run?tableId=bje35c29w

status:200

content:{"data":[{"16":{"value":true},"3":{"value":15845},"338":{"value":true},"343":{"value":"Air Products at PBF - Martinez"},"369":{"value":true},"370":{"value":"2025-02-26"},"383":{"value":"2025-02-26"},"469":{"value":true},"471":{"value":"2025-02-24"},"478":{"value":"User , QuickBase Test - 15845"},"758":{"value":true}}],"fields":[{"id":3,"label":"Record ID#","type":"recordid"},{"id":343,"label":"Project Name","type":"text"},{"id":478,"label":"Full Name - HMC ID","type":"rich-text"},{"id":16,"label":"Active","type":"checkbox"},{"id":370,"label":"Email Payroll Date","type":"date"},{"id":383,"label":"Verification Email Date","type":"date"},{"id":471,"label":"Instructions Send Date","type":"date"},{"id":369,"label":"Email Payroll Trigger","type":"checkbox"},{"id":338,"label":"Email Verification Trigger","type":"checkbox"},{"id":469,"label":"send_instructions_trigger","type":"checkbox"},{"id":758,"label":"PG Onboarding Clear Dates","type":"checkbox"}],"metadata":{"numFields":11,"numRecords":1,"skip":0,"totalRecords":1}}

 

elapsed:0.99378

json

data

Below is what the data looks like for humans.

3

value:15845

16

value:true

338

value:true

343

value:Air Products at PBF - Martinez

369

value:true

370

value:2025-02-26

383

value:2025-02-26

469

"value":true

471

"value":"2025-02-24"

478

"value":"User , QuickBase Test - 15845"

758

"value":true

 

id:3

label:Record ID#

type:recordid

id:343

label:Project Name

type:text

id:478

label:Full Name - HMC ID

type:rich-text

id:16

label:Active

type:checkbox

id:370

label:Email Payroll Date

type:date

id:383

label:Verification Email Date

type:date

id:471

label:Instructions Send Date

type:date

id:369

label:Email Payroll Trigger

type:checkbox

id:338

label:Email Verification Trigger

type:checkbox

id:469

label:send_instructions_trigger

type:checkbox

id:758

label:PG Onboarding Clear Dates

type:checkbox

 

metadata

recordrecordnumFields:11

numRecords:1

skip:0

totalRecords:1

 

Info has this but it's not very helpful.

*Hint:* you can use `to_json` filter like `{{a|to_json}}` or `{{a.attribute|to_json}}` to obtain json representation of an object. You can even combine objects exported from several steps, like `{{ {'trello_card': a, 'salesforce_task': b}|to_json }}`

 

ChatGPT ask how to find the number of records returned in the report

{{ b.json.metadata.totalRecords > 0 }}

This informs the IF step to go no go.

 

Now I want to get the values for ID 3:

I start looking for solutions. I try parse JSON, iterate JSON but none of these are working. I asked Quickbase Support and after weeks of back and forth they said iterate would work. I don't see how without adding a loop. 

Going back to what I know works, I can use the API's

First step is to see if I can update one or more records using API. First thought about API_ImportFromCSV but decided to use Restful JSON API since the output of step a is JSON. Here is the Restful API URL.

Post: https://api.quickbase.com/v1/records is perfect. All that is needed is the table dbid and a data array with key value pairs in the format below.

{
  "to": "bnb2ikxvn",
  "data": [
    {
      "3": {"value": 10},
      "7": {"value": true},
    }
  ]
}

First test I use 3 = 3 record_id ~ I know I can use any uniquified field I want. This goes into the body of a Pipeline step named Make request (Make an HTTP or REST API request.). Method is POST. Headers name = QB-Realm-Hostname, Value = realm.quickbase.com ~ handles authentication.

One record test sample body into testable 5.0 below.

{"to": "bnb2ikxvn",

"data": [{

"3": {"value": 10},

"7": {"value": false}

}],

"fieldsToReturn": [7]}

 

Works!

Many record test sample body below.

 

{"to": "bnb2ikxvn",

"data": [

{"3": {"value": 10}, "7": {"value": true}},

{"3": {"value": 58}, "7": {"value": true}},

{"3": {"value": 3464}, "7": {"value": true}},

{"3": {"value": 3465}, "7": {"value": true}},

{"3": {"value": 3466}, "7": {"value": true}},

{"3": {"value": 3467}, "7": {"value": true}}

],

"fieldsToReturn": [7]}

Success! By changing true to false, I can check and uncheck the check box in all the records in one batch upsert. I am hand coding the record_id values. I can use "fields to return" to handle errors? Need to investigate.

Now I have to make something that can generate the JSON above for each value returned in the first GET step. Below are some of the jinja I tried to get data.

{{a.content | to_json}} ~ returns entire body

{{a.content[0] | to_json}} ~ returns {

ChatGPT says I should do this.

{% for field_id, field_data in data[0].items() %}

    {% if field_id == 3 %}

        {{ field_data.value }}

    {% endif %}

{% endfor %} ~ doesn't work, don't understand why... see explanation below.

{{data}} ~ nothing

{{ a.json.data | to_json}} ~ sends json body

Here is where I figured out the problem ~ and solution.

{{ a.json.data[0]["3"]["value"]}} ~ a.json.data[0][3] fails because it's trying to use an integer key (3), but no integer key exists in the JSON object from Quickbase. ChatGPT mislead me by making [3] an integer, it's a string, ["3"] and magic, it works. I put this into the UPSERT step and sent it to requestbin. Using requestbin, I can look at the actual data being sent to quickbase. It is looking pretty good.

{% if a.json and a.json.data and a.json.data[0] %}

  {% for key, field in a.json.data[0].items() %}

    {% if key == "3" %}

      {{ field.value }}

    {% endif %}

  {% endfor %}

{% else %}

  Data not found

{% endif %} ~ result "body": 15845 which is the record_id of the JSON. I have the record_id now all I need to do is write the field ids and make all the values blank.

First I tried.

{%- if a.json and a.json.data and a.json.data[0] -%}

{

  {% for key, field in a.json.data[0].items() %}

    "{{ key }}": "{{ field.value }}"{% if not loop.last %},{% endif %}

  {% endfor %}

}

{%- else -%}

  {}

{%- endif -%} ~ works for one record.

 

Asked ChatGPT for a loop.


{%- if a.json and a.json.data -%}

[

  {% for record in a.json.data %}

  {

    {% for key, field in record.items() %}

      "{{ key }}": {{ field.value | tojson }}{% if not loop.last %},{% endif %}

    {% endfor %}

  }{% if not loop.last %},{% endif %}

  {% endfor %}

]

{%- else -%}

  []

{%- endif -%} ~ gives me all the values in the JSON.

Asked ChatGPT:

I want to get the values for id 3 and then all the other keys returned make blank.

{%- if a.json and a.json.data -%}

[

  {% for record in a.json.data %}

  {

    {% for key, field in record.items() %}

      {% if key == "3" %}

        "{{ key }}": {{ field.value | tojson }}

      {% else %}

        "{{ key }}": ""

      {% endif %}

      {% if not loop.last %},{% endif %}

    {% endfor %}

  }{% if not loop.last %},{% endif %}

  {% endfor %}

]

{%- else -%}

  []

{%- endif -%}

Asked ChatGPT:

I want to insert the output of the jinja above so it fits in the "data" array required by Restful API_Records UPSERT.

{%- if a.json and a.json.data -%}

{

  "to": "bnb2ikxvn",

  "data": [

    {% for record in a.json.data %}

    {

      {% for key, field in record.items() %}

        {% if key == "3" %}

          "{{ key }}": { "value": {{ field.value | tojson }} }

        {% else %}

          "{{ key }}": { "value": "" }

        {% endif %}

        {% if not loop.last %},{% endif %}

      {% endfor %}

    }{% if not loop.last %},{% endif %}

    {% endfor %}

  ],

  "fieldsToReturn": [7]

}

{%- else -%}

{

  "to": "bnb2ikxvn",

  "data": [],

  "fieldsToReturn": [7]

}

{%- endif -%} ~ Works!

In three steps I can dynamically update all the records returned in a Quickbase report.

JimHarrison
Forum|alt.badge.img+18
  • Author
  • Registered
  • Answer
  • March 14, 2025

Here is my working solution, I need to test it and verify it works all the time. 

First use a Restful API Report step to get the data>

I used these API call below in this recipe. 
api.quickbase.com/v1/reports/369/run?tableId=bje35c29w

https://422a9c520eb5b465e7b32cf16982ed96.m.pipedream.net

https://api.quickbase.com/v1/records

Above is the report QID, below is the output.

Type:action

Channel:quickbase

Index:b

Pipeline:HR: Employees: PG Onboarding: Clear Dates

Step:Restful API Report

Run timestamp:Thu Mar 13 2025 08:41:46 GMT-0700 (Pacific Daylight Time)

 

Input

url:https://api.quickbase.com/v1/reports/369/run?tableId=bje35c29w

method:POST

 

headers

 

name:QB-Realm-Hostname

value:hardermech.quickbase.com

content_type:application/json

disable_ssl_verification:false

 

Output

url:https://api.quickbase.com/v1/reports/369/run?tableId=bje35c29w

status:200

content:{"data":[{"16":{"value":true},"3":{"value":15845},"338":{"value":true},"343":{"value":"Air Products at PBF - Martinez"},"369":{"value":true},"370":{"value":"2025-02-26"},"383":{"value":"2025-02-26"},"469":{"value":true},"471":{"value":"2025-02-24"},"478":{"value":"User , QuickBase Test - 15845"},"758":{"value":true}}],"fields":[{"id":3,"label":"Record ID#","type":"recordid"},{"id":343,"label":"Project Name","type":"text"},{"id":478,"label":"Full Name - HMC ID","type":"rich-text"},{"id":16,"label":"Active","type":"checkbox"},{"id":370,"label":"Email Payroll Date","type":"date"},{"id":383,"label":"Verification Email Date","type":"date"},{"id":471,"label":"Instructions Send Date","type":"date"},{"id":369,"label":"Email Payroll Trigger","type":"checkbox"},{"id":338,"label":"Email Verification Trigger","type":"checkbox"},{"id":469,"label":"send_instructions_trigger","type":"checkbox"},{"id":758,"label":"PG Onboarding Clear Dates","type":"checkbox"}],"metadata":{"numFields":11,"numRecords":1,"skip":0,"totalRecords":1}}

 

elapsed:0.99378

json

data

Below is what the data looks like for humans.

3

value:15845

16

value:true

338

value:true

343

value:Air Products at PBF - Martinez

369

value:true

370

value:2025-02-26

383

value:2025-02-26

469

"value":true

471

"value":"2025-02-24"

478

"value":"User , QuickBase Test - 15845"

758

"value":true

 

id:3

label:Record ID#

type:recordid

id:343

label:Project Name

type:text

id:478

label:Full Name - HMC ID

type:rich-text

id:16

label:Active

type:checkbox

id:370

label:Email Payroll Date

type:date

id:383

label:Verification Email Date

type:date

id:471

label:Instructions Send Date

type:date

id:369

label:Email Payroll Trigger

type:checkbox

id:338

label:Email Verification Trigger

type:checkbox

id:469

label:send_instructions_trigger

type:checkbox

id:758

label:PG Onboarding Clear Dates

type:checkbox

 

metadata

recordrecordnumFields:11

numRecords:1

skip:0

totalRecords:1

 

Info has this but it's not very helpful.

*Hint:* you can use `to_json` filter like `{{a|to_json}}` or `{{a.attribute|to_json}}` to obtain json representation of an object. You can even combine objects exported from several steps, like `{{ {'trello_card': a, 'salesforce_task': b}|to_json }}`

 

ChatGPT ask how to find the number of records returned in the report

{{ b.json.metadata.totalRecords > 0 }}

This informs the IF step to go no go.

 

Now I want to get the values for ID 3:

I start looking for solutions. I try parse JSON, iterate JSON but none of these are working. I asked Quickbase Support and after weeks of back and forth they said iterate would work. I don't see how without adding a loop. 

Going back to what I know works, I can use the API's

First step is to see if I can update one or more records using API. First thought about API_ImportFromCSV but decided to use Restful JSON API since the output of step a is JSON. Here is the Restful API URL.

Post: https://api.quickbase.com/v1/records is perfect. All that is needed is the table dbid and a data array with key value pairs in the format below.

{
  "to": "bnb2ikxvn",
  "data": [
    {
      "3": {"value": 10},
      "7": {"value": true},
    }
  ]
}

First test I use 3 = 3 record_id ~ I know I can use any uniquified field I want. This goes into the body of a Pipeline step named Make request (Make an HTTP or REST API request.). Method is POST. Headers name = QB-Realm-Hostname, Value = realm.quickbase.com ~ handles authentication.

One record test sample body into testable 5.0 below.

{"to": "bnb2ikxvn",

"data": [{

"3": {"value": 10},

"7": {"value": false}

}],

"fieldsToReturn": [7]}

 

Works!

Many record test sample body below.

 

{"to": "bnb2ikxvn",

"data": [

{"3": {"value": 10}, "7": {"value": true}},

{"3": {"value": 58}, "7": {"value": true}},

{"3": {"value": 3464}, "7": {"value": true}},

{"3": {"value": 3465}, "7": {"value": true}},

{"3": {"value": 3466}, "7": {"value": true}},

{"3": {"value": 3467}, "7": {"value": true}}

],

"fieldsToReturn": [7]}

Success! By changing true to false, I can check and uncheck the check box in all the records in one batch upsert. I am hand coding the record_id values. I can use "fields to return" to handle errors? Need to investigate.

Now I have to make something that can generate the JSON above for each value returned in the first GET step. Below are some of the jinja I tried to get data.

{{a.content | to_json}} ~ returns entire body

{{a.content[0] | to_json}} ~ returns {

ChatGPT says I should do this.

{% for field_id, field_data in data[0].items() %}

    {% if field_id == 3 %}

        {{ field_data.value }}

    {% endif %}

{% endfor %} ~ doesn't work, don't understand why... see explanation below.

{{data}} ~ nothing

{{ a.json.data | to_json}} ~ sends json body

Here is where I figured out the problem ~ and solution.

{{ a.json.data[0]["3"]["value"]}} ~ a.json.data[0][3] fails because it's trying to use an integer key (3), but no integer key exists in the JSON object from Quickbase. ChatGPT mislead me by making [3] an integer, it's a string, ["3"] and magic, it works. I put this into the UPSERT step and sent it to requestbin. Using requestbin, I can look at the actual data being sent to quickbase. It is looking pretty good.

{% if a.json and a.json.data and a.json.data[0] %}

  {% for key, field in a.json.data[0].items() %}

    {% if key == "3" %}

      {{ field.value }}

    {% endif %}

  {% endfor %}

{% else %}

  Data not found

{% endif %} ~ result "body": 15845 which is the record_id of the JSON. I have the record_id now all I need to do is write the field ids and make all the values blank.

First I tried.

{%- if a.json and a.json.data and a.json.data[0] -%}

{

  {% for key, field in a.json.data[0].items() %}

    "{{ key }}": "{{ field.value }}"{% if not loop.last %},{% endif %}

  {% endfor %}

}

{%- else -%}

  {}

{%- endif -%} ~ works for one record.

 

Asked ChatGPT for a loop.


{%- if a.json and a.json.data -%}

[

  {% for record in a.json.data %}

  {

    {% for key, field in record.items() %}

      "{{ key }}": {{ field.value | tojson }}{% if not loop.last %},{% endif %}

    {% endfor %}

  }{% if not loop.last %},{% endif %}

  {% endfor %}

]

{%- else -%}

  []

{%- endif -%} ~ gives me all the values in the JSON.

Asked ChatGPT:

I want to get the values for id 3 and then all the other keys returned make blank.

{%- if a.json and a.json.data -%}

[

  {% for record in a.json.data %}

  {

    {% for key, field in record.items() %}

      {% if key == "3" %}

        "{{ key }}": {{ field.value | tojson }}

      {% else %}

        "{{ key }}": ""

      {% endif %}

      {% if not loop.last %},{% endif %}

    {% endfor %}

  }{% if not loop.last %},{% endif %}

  {% endfor %}

]

{%- else -%}

  []

{%- endif -%}

Asked ChatGPT:

I want to insert the output of the jinja above so it fits in the "data" array required by Restful API_Records UPSERT.

{%- if a.json and a.json.data -%}

{

  "to": "bnb2ikxvn",

  "data": [

    {% for record in a.json.data %}

    {

      {% for key, field in record.items() %}

        {% if key == "3" %}

          "{{ key }}": { "value": {{ field.value | tojson }} }

        {% else %}

          "{{ key }}": { "value": "" }

        {% endif %}

        {% if not loop.last %},{% endif %}

      {% endfor %}

    }{% if not loop.last %},{% endif %}

    {% endfor %}

  ],

  "fieldsToReturn": [7]

}

{%- else -%}

{

  "to": "bnb2ikxvn",

  "data": [],

  "fieldsToReturn": [7]

}

{%- endif -%} ~ Works!

In three steps I can dynamically update all the records returned in a Quickbase report.