private void makeFirstRequest(final Context context) {

    final RedditAccount user = RedditAccountManager.getInstance(context).getDefaultAccount();
    final CacheManager cm = CacheManager.getInstance(context);

    final URI url;

    if (!isModmail) {
      if (onlyUnread) {
        url = Constants.Reddit.getUri("/message/unread.json?mark=true&limit=100");
      } else {
        url = Constants.Reddit.getUri("/message/inbox.json?mark=true&limit=100");
      }
    } else {
      url = Constants.Reddit.getUri("/message/moderator.json?limit=100");
    }

    // TODO parameterise limit
    request =
        new CacheRequest(
            url,
            user,
            null,
            Constants.Priority.API_INBOX_LIST,
            0,
            CacheRequest.DOWNLOAD_FORCE,
            Constants.FileType.INBOX_LIST,
            CacheRequest.DOWNLOAD_QUEUE_REDDIT_API,
            true,
            true,
            context) {

          @Override
          protected void onDownloadNecessary() {}

          @Override
          protected void onDownloadStarted() {}

          @Override
          protected void onCallbackException(final Throwable t) {
            request = null;
            BugReportActivity.handleGlobalError(context, t);
          }

          @Override
          protected void onFailure(
              final @CacheRequest.RequestFailureType int type,
              final Throwable t,
              final Integer status,
              final String readableMessage) {

            request = null;

            if (loadingView != null) loadingView.setDone(R.string.download_failed);

            final RRError error =
                General.getGeneralErrorForFailure(context, type, t, status, url.toString());
            AndroidApi.UI_THREAD_HANDLER.post(
                new Runnable() {
                  public void run() {
                    notifications.addView(new ErrorView(InboxListingActivity.this, error));
                  }
                });

            if (t != null) t.printStackTrace();
          }

          @Override
          protected void onProgress(
              final boolean authorizationInProgress, final long bytesRead, final long totalBytes) {}

          @Override
          protected void onSuccess(
              final CacheManager.ReadableCacheFile cacheFile,
              final long timestamp,
              final UUID session,
              final boolean fromCache,
              final String mimetype) {
            request = null;
          }

          @Override
          public void onJsonParseStarted(
              final JsonValue value,
              final long timestamp,
              final UUID session,
              final boolean fromCache) {

            if (loadingView != null) loadingView.setIndeterminate(R.string.download_downloading);

            // TODO pref (currently 10 mins)
            // TODO xml
            if (fromCache && RRTime.since(timestamp) > 10 * 60 * 1000) {
              AndroidApi.UI_THREAD_HANDLER.post(
                  new Runnable() {
                    public void run() {
                      final TextView cacheNotif = new TextView(context);
                      cacheNotif.setText(
                          context.getString(R.string.listing_cached)
                              + RRTime.formatDateTime(timestamp, context));
                      final int paddingPx = General.dpToPixels(context, 6);
                      final int sidePaddingPx = General.dpToPixels(context, 10);
                      cacheNotif.setPadding(sidePaddingPx, paddingPx, sidePaddingPx, paddingPx);
                      cacheNotif.setTextSize(13f);
                      notifications.addView(cacheNotif);
                      adapter.notifyDataSetChanged();
                    }
                  });
            }

            // TODO {"error": 403} is received for unauthorized subreddits

            try {
              final JsonBufferedObject root = value.asObject();
              final JsonBufferedObject data = root.getObject("data");
              final JsonBufferedArray children = data.getArray("children");

              for (JsonValue child : children) {

                final RedditThing thing = child.asObject(RedditThing.class);

                switch (thing.getKind()) {
                  case COMMENT:
                    final RedditComment comment = thing.asComment();
                    final RedditParsedComment parsedComment = new RedditParsedComment(comment);
                    final RedditRenderableComment renderableComment =
                        new RedditRenderableComment(parsedComment, null, -100000, false);
                    itemHandler.sendMessage(General.handlerMessage(0, renderableComment));

                    break;

                  case MESSAGE:
                    final RedditPreparedMessage message =
                        new RedditPreparedMessage(
                            InboxListingActivity.this, thing.asMessage(), timestamp);
                    itemHandler.sendMessage(General.handlerMessage(0, message));

                    if (message.src.replies != null
                        && message.src.replies.getType() == JsonValue.TYPE_OBJECT) {

                      final JsonBufferedArray replies =
                          message.src.replies.asObject().getObject("data").getArray("children");

                      for (JsonValue childMsgValue : replies) {
                        final RedditMessage childMsgRaw =
                            childMsgValue.asObject(RedditThing.class).asMessage();
                        final RedditPreparedMessage childMsg =
                            new RedditPreparedMessage(
                                InboxListingActivity.this, childMsgRaw, timestamp);
                        itemHandler.sendMessage(General.handlerMessage(0, childMsg));
                      }
                    }

                    break;

                  default:
                    throw new RuntimeException("Unknown item in list.");
                }
              }

            } catch (Throwable t) {
              notifyFailure(CacheRequest.REQUEST_FAILURE_PARSE, t, null, "Parse failure");
              return;
            }

            if (loadingView != null) loadingView.setDone(R.string.download_done);
          }
        };

    cm.makeRequest(request);
  }