Sync All Child Profile Data

Fetching a list of child profiles

Start out by fetching the list of child profiles. The response includes 10 profiles per page, and only the child profile IDs.

curl \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  https://localhost/api/child_profiles
{
    "_links": {
        "find": {
            "href": "/api/child_profiles/{id}",
            "templated": true
        },
        "next": {
            "href": "/api/child_profiles?page=2"
        },
        "self": {
            "href": "/api/child_profiles"
        }
    },
    "child_profiles": [
        { "id": 94154 },
        { "id": 35365 },
        { "id": 94047 },
        { "id": 94155 },
        { "id": 94156 },
        { "id": 94157 },
        { "id": 59373 },
        { "id": 94145 },
        { "id": 59374 },
        { "id": 59375 }
    ],
    "total_entries": 24,
    "total_pages": 3
}

To fetch the second page and on, use the next link provided in the _links object.

curl \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  https://localhost/api/child_profiles?page=2

Load a Detailed Child Profile

Once you have a list of child profiles ids, you can begin fetching the detailed profiles. The index response contains a templated response to fetch the profile. This is RFC 6570. You should use the alternate_id to match records in your local database.

curl \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  https://localhost/api/child_profiles/94156
{
    "_links": {
        "caregiver_profiles": {
            "href": "/api/child_profiles/94156/caregiver_profiles"
        },
        "screenings": {
            "href": "/api/child_profiles/94156/screenings"
        }
    },
    "child_profile": {
        "account": "DEMO Account",
        "address1": "920 19 ST S",
        "address2": null,
        "address3": null,
        "adjusted_age": [
            47,
            5
        ],
        "alternate_id": null,
        "birth_weight": null,
        "city": "ST PETERSBURG",
        "country": "United States",
        "county": null,
        "custom_fields": {
            "Blood Type": null,
            "City": null,
            "County": null,
            "Person Completing the Screening": null,
            "Social Security #": null,
            "Type": null
        },
        "date_of_admission": null,
        "dob": "2012-05-29",
        "ethnicity": null,
        "first_name": "Ford",
        "gender": "Male",
        "id": 94156,
        "last_name": "Betty",
        "medical_risk_factors": "No",
        "middle_initial": null,
        "other_agencies_involved": "No",
        "phone": "727-563-6787",
        "primary_home_language": null,
        "program": "Program A",
        "program_id": 2362,
        "provider": null,
        "secondary_home_language": null,
        "state": "Florida",
        "status": "Active",
        "synchronized_at": null,
        "weeks_premature": 0,
        "zip": "33712"
    }
}

Set the Child Profiles as Synchronized (Optional)

You can update the synchronized timestamp for child profiles by posting to /api/child_profiles/synchronizations with a payload of child profile IDs.

curl \
  --verbose \
  -d '{"ids": [94156]}' \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  http://localhost/api/child_profiles/synchronizations

Using curl’s verbose mode you should see a value on the X-Total-Count header representing how many records were updated and a timestamp in X-Synchronized-At representing the timestamp the ASQ server set for the synchronization.

...
< HTTP/1.1 204 No Content
< ...
< X-Total-Count: 1
< X-Synchronized-At: "2012-06-05T13:43:34.811-05:00"
< ...

You can also provide a synchronized_at parameter as part of a child profile update call to udpate an individual child profile as synchronized.

The synchronization timestamp can also be used when querying the child profile list to retrieve only child profile ids that were last synchronized before the timestamp provided to the API, or those child profiles that have never had their synchronized_at parameter set.

curl \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  https://localhost/api/child_profiles?synchronized_at=2012-06-05T13%3A43%3A34-05%3A00
{
    "_links": {
        "find": {
            "href": "/api/child_profiles/{id}",
            "templated": true
        },
        "next": {
            "href": "/api/child_profiles?page=2&synchronized_at=2012-06-05T13%3A43%3A34.811-05%3A00"
        },
        "self": {
            "href": "/api/child_profiles?synchronized_at=2012-06-05T13%3A43%3A34.811-05%3A00"
        }
    },
    "child_profiles": [
        { "id": 94154 },
        { "id": 35365 },
        { "id": 94047 },
        { "id": 94155 },
        { "id": 94157 },
        { "id": 59373 },
        { "id": 94145 },
        { "id": 59374 },
        { "id": 59375 },
        { "id": 59376 }
    ],
    "total_entries": 23,
    "total_pages": 3
}

The synchronized_at parameter is intended (but not required) to be used in concert with the since parameter. To get all the records that have been updated since your last synchronization you can provide the same value to both parameters.

curl \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  https://localhost/api/child_profiles?synchronized_at=2012-06-05T13%3A43%3A34-05%3A00&since=2012-06-05T13%3A43%3A34-05%3A00
{
  "_links": {
    "self": {
      "href": "/api/child_profiles?since=2012-06-05T13%3A43%3A34-05%3A00&synchronized_at=2012-06-05T13%3A43%3A34.811-05%3A00"
    },
    "next": {
      "href": "/api/child_profiles?page=2&since=2012-06-05T13%3A43%3A34-05%3A00&synchronized_at=2012-06-05T13%3A43%3A34.811-05%3A00"
    },
    "find": {
      "href": "/api/child_profiles/{id}",
      "templated": true
    }
  }
  "child_profiles": [
    { "id": 95277 },
    { "id": 96700 },
    { "id": 94807 },
    { "id": 96771 },
    { "id": 96772 },
    { "id": 96773 },
    { "id": 96770 },
    { "id": 96741 },
    { "id": 96703 },
    { "id": 96709 }
  ],
  "total_entries": 11,
  "total_pages": 2,
}

The unsynchronized parameter is intended to be a different way to get a list of child profiles whose last modification time are after their last synchronization time and can be used on its own or in combination with the above parameters. For example if a child profile had its last changes made yesterday but was last synchronized a month ago, passing the unsynchronized parameter would return that record along with any records that have not yet been marked as synchronized.

curl \
  -H "Accept: application/json" \
  -H "X-Auth-Token: 54f958af0a4e0f272df3a76d63c14f79" \
  https://localhost/api/child_profiles?unsynchronized=true
{
  "_links": {
    "self": {
      "href": "/api/child_profiles??unsynchronized=true"
    },
    "next": {
      "href": "/api/child_profiles?page=2&?unsynchronized=true"
    },
    "find": {
      "href": "/api/child_profiles/{id}",
      "templated": true
    }
  }
  "child_profiles": [
    { "id": 95277 },
    { "id": 96700 },
    { "id": 94807 },
    { "id": 96771 },
    { "id": 96772 },
    { "id": 96773 },
    { "id": 96770 },
    { "id": 96741 },
    { "id": 96703 },
    { "id": 96709 }
  ],
  "total_entries": 11,
  "total_pages": 2,
}

Example Ruby Code

The following code demonstrates getting all the child profiles for available to a given token and their details, and prints out the child profile id of each child that was retrieved.

require 'json'
require 'faraday'
require 'addressable'

class ASQMiddleware < Faraday::Middleware
  def initialize(app, options)
    @app = app
    @token = options[:token]
  end

  def call(env)
    env[:request_headers]["Accept"] = "application/json"
    env[:request_headers]["X-Auth-Token"] = @token
    @app.call(env)
  end
end

class Pager
  include Enumerable

  attr_reader :connection, :path, :key

  def initialize(connection, path, key)
    @connection = connection
    @path = path
    @key = key
  end

  def each
    fetch(path) do |item, links|
      yield item, links
    end
  end

  private

  def fetch(path, &block)
    response = connection.get(path)
    json = JSON.parse(response.body)
    items = json.fetch(key, [])

    links = json.fetch("_links", {})

    items.each do |item|
      yield item, links
    end

    if links.key?("next")
      fetch(links["next"]["href"], &block)
    end
  end
end

def asq_url
  ENV["ASQ_URL"] || "http://localhost"
end

def asq_token
  ENV["ASQ_TOKEN"] || "54f958af0a4e0f272df3a76d63c14f79"
end

connection = Faraday.new(url: asq_url) do |conn|
  conn.use ASQMiddleware, token: asq_token
  conn.adapter Faraday.default_adapter
end

def get_last_run
  # Get the previous timestamp or return nil if not available
end

def set_last_run
  # Save the current timestamp
end

timestamp = get_last_run

# set the path to get child profiles updated since the last run
if timestamp
  path = "/api/child_profiles?since=#{timestamp}"
else
  path = "/api/child_profiles"
end

pager = Pager.new(connection, path, "child_profiles")
pager.each do |child_profile, links|
  template = Addressable::Template.new(links["find"]["href"])
  path = template.expand(id: child_profile["id"]).to_s

  response = connection.get(path)
  raise "Error" unless response.success?
  child_profile = JSON.parse(response.body)
  # Save the profile
  p child_profile["child_profile"]["id"]
end

set_last_run