The Trajectory API, or a subset of it at least. This mirrors the underlying implementation, which ties stories to iterations.
Get all the incomplete stories and iterations for a given user key, account name, and project name. Since stories and iterations are tied together in the underlying API, this produces them as a pair.
It produces an IO of either an error or the stories/iterations pair. The error can come from the HTTP, or from non-JSON input, or from a change to the JSON.
do possibleStories <- getStories "abcdefg" "thoughtbot" "opensource" case possibleStories of (Left error) -> putStrLn $ "got the error: " ++ show error (Right (stories,iterations)) -> putStrLn $ intercalate "\n" $ (map formatStory stories) ++ (map formatIteration iterations)