diff --git a/DynamicModel.cc b/DynamicModel.cc
index 10db3a8b9bece10aef9bf2192ac20feb7277b0b4..c05529c48d3ec391b9bf0c761392ee7a20510a33 100644
--- a/DynamicModel.cc
+++ b/DynamicModel.cc
@@ -5342,6 +5342,127 @@ void
 DynamicModel::writeJsonOutput(ostream &output) const
 {
   writeJsonModelEquations(output, false);
+  output << ", ";
+  writeJsonXrefs(output);
+}
+
+void
+DynamicModel::writeJsonXrefs(ostream &output) const
+{
+  output << "\"xrefs\": {"
+         << "\"parameters\": [";
+  for (map<pair<int, int>, set<int> >::const_iterator it = json_xref_param.begin();
+       it != json_xref_param.end(); it++)
+    {
+      if (it != json_xref_param.begin())
+        output << ", ";
+      output << "{\"parameter\": \"" << symbol_table.getName(it->first.first) << "\""
+             << ", \"equations\": [";
+      for (set<int>::const_iterator it1 = it->second.begin();
+           it1 != it->second.end(); it1++)
+        {
+          if (it1 != it->second.begin())
+            output << ", ";
+          output << *it1 + 1;
+        }
+      output << "]}";
+    }
+  output << "]"
+         << ", \"endogenous\": [";
+  for (map<pair<int, int>, set<int> >::const_iterator it = json_xref_endo.begin();
+       it != json_xref_endo.end(); it++)
+    {
+      if (it != json_xref_endo.begin())
+        output << ", ";
+      output << "{\"endogenous\": \"" << symbol_table.getName(it->first.first) << "\""
+             << ", \"shift\": " << it->first.second
+             << ", \"equations\": [";
+      for (set<int>::const_iterator it1 = it->second.begin();
+           it1 != it->second.end(); it1++)
+        {
+          if (it1 != it->second.begin())
+            output << ", ";
+          output << *it1 + 1;
+        }
+      output << "]}";
+    }
+  output << "]"
+         << ", \"exogenous\": [";
+  for (map<pair<int, int>, set<int> >::const_iterator it = json_xref_exo.begin();
+       it != json_xref_exo.end(); it++)
+    {
+      if (it != json_xref_exo.begin())
+        output << ", ";
+      output << "{\"exogenous\": \"" << symbol_table.getName(it->first.first) << "\""
+             << ", \"shift\": " << it->first.second
+             << ", \"equations\": [";
+      for (set<int>::const_iterator it1 = it->second.begin();
+           it1 != it->second.end(); it1++)
+        {
+          if (it1 != it->second.begin())
+            output << ", ";
+          output << *it1 + 1;
+        }
+      output << "]}";
+    }
+  output << "]"
+         << ", \"exogenous_deterministic\": [";
+  for (map<pair<int, int>, set<int> >::const_iterator it = json_xref_exo_det.begin();
+       it != json_xref_exo_det.end(); it++)
+    {
+      if (it != json_xref_exo_det.begin())
+        output << ", ";
+      output << "{\"exogenous_det\": \"" << symbol_table.getName(it->first.first) << "\""
+             << ", \"shift\": " << it->first.second
+             << ", \"equations\": [";
+      for (set<int>::const_iterator it1 = it->second.begin();
+           it1 != it->second.end(); it1++)
+        {
+          if (it1 != it->second.begin())
+            output << ", ";
+          output << *it1 + 1;
+        }
+      output << "]}";
+    }
+  output << "]}" << endl;
+}
+
+void
+DynamicModel::computeJsonXrefs()
+{
+  map<int, ExprNode::JsonEquationInfo> xrefs;
+  int i = 0;
+  for (vector<BinaryOpNode *>::iterator it = equations.begin();
+       it != equations.end(); it++)
+    {
+      ExprNode::JsonEquationInfo ei;
+      (*it)->computeJsonXrefs(ei);
+      xrefs[i++] = ei;
+    }
+
+  i = 0;
+  for (map<int, ExprNode::JsonEquationInfo>::const_iterator it = xrefs.begin();
+       it != xrefs.end(); it++, i++)
+    {
+      computeJsonRevXref(json_xref_param, it->second.param, i);
+      computeJsonRevXref(json_xref_endo, it->second.endo, i);
+      computeJsonRevXref(json_xref_exo, it->second.exo, i);
+      computeJsonRevXref(json_xref_exo_det, it->second.exo_det, i);
+    }
+}
+
+void
+DynamicModel::computeJsonRevXref(map<pair<int, int>, set<int> > &xrefset, const set<pair<int, int> > &eiref, int eqn)
+{
+  for (set<pair<int, int> >::const_iterator it = eiref.begin();
+       it != eiref.end(); it++)
+    {
+      set<int> eq;
+      if (xrefset.find(*it) != xrefset.end())
+        eq = xrefset[*it];
+      eq.insert(eqn);
+      xrefset[*it] = eq;
+    }
 }
 
 void
@@ -5721,3 +5842,4 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails)
          << ", " << third_derivs1_output.str()
          << "}";
 }
+
diff --git a/DynamicModel.hh b/DynamicModel.hh
index b0828a2b23e6de49aefcd80c2850d5b112b55de3..cec66d97ec233f2289ee9e82907b836c75305fef 100644
--- a/DynamicModel.hh
+++ b/DynamicModel.hh
@@ -62,6 +62,12 @@ private:
   /*! Set by computeDerivIDs() */
   int max_exo_det_lag, max_exo_det_lead;
 
+  //! Cross references WITH lags (for #1387, potentially combine with cross references above upon decision by @michel)
+  map<pair<int, int>, set<int> > json_xref_param;
+  map<pair<int, int>, set<int> > json_xref_endo;
+  map<pair<int, int>, set<int> > json_xref_exo;
+  map<pair<int, int>, set<int> > json_xref_exo_det;
+
   //! Number of columns of dynamic jacobian
   /*! Set by computeDerivID()s and computeDynJacobianCols() */
   int dynJacobianColsNbr;
@@ -189,6 +195,9 @@ private:
   /*! pair< pair<static, forward>, pair<backward,mixed> > */
   vector<pair< pair<int, int>, pair<int, int> > > block_col_type;
 
+  //! Related to public function computeJsonXref
+  void computeJsonRevXref(map<pair<int, int>, set<int> > &xrefset, const set<pair<int, int> > &eiref, int eqn);
+
   //! List for each variable its block number and its maximum lag and lead inside the block
   vector<pair<int, pair<int, int> > > variable_block_lead_lag;
   //! List for each equation its block number
@@ -202,7 +211,10 @@ public:
   //! Adds a variable node
   /*! This implementation allows for non-zero lag */
   virtual VariableNode *AddVariable(int symb_id, int lag = 0);
-  
+
+  //! For computing cross references for json output (i.e. that contains lag information) #1387
+  void computeJsonXrefs();
+
   //! Execute computations (variable sorting + derivation)
   /*!
     \param jacobianExo whether derivatives w.r. to exo and exo_det should be in the Jacobian (derivatives w.r. to endo are always computed)
@@ -220,6 +232,9 @@ public:
   //! Write JSON Output
   void writeJsonOutput(ostream &output) const;
 
+  //! Write cross reference output if the xref maps have been filed
+  void writeJsonXrefs(ostream &output) const;
+
   //! Write JSON Output representation of dynamic model after computing pass
   void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const;
 
diff --git a/ExprNode.cc b/ExprNode.cc
index 5cc0298bdca44223c3b8b021eee6761b34f09ef7..dfb66d3df551e71634767cee8b456d12fa29e17f 100644
--- a/ExprNode.cc
+++ b/ExprNode.cc
@@ -396,6 +396,11 @@ NumConstNode::computeXrefs(EquationInfo &ei) const
 {
 }
 
+void
+NumConstNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+}
+
 expr_t
 NumConstNode::cloneDynamic(DataTree &dynamic_datatree) const
 {
@@ -1131,6 +1136,34 @@ VariableNode::computeXrefs(EquationInfo &ei) const
     }
 }
 
+void
+VariableNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  switch (type)
+    {
+    case eEndogenous:
+      ei.endo.insert(make_pair(symb_id, lag));
+      break;
+    case eExogenous:
+      ei.exo.insert(make_pair(symb_id, lag));
+      break;
+    case eExogenousDet:
+      ei.exo_det.insert(make_pair(symb_id, lag));
+      break;
+    case eParameter:
+      ei.param.insert(make_pair(symb_id, 0));
+      break;
+    case eTrend:
+    case eLogTrend:
+    case eModelLocalVariable:
+    case eModFileLocalVariable:
+    case eStatementDeclaredVariable:
+    case eUnusedEndogenous:
+    case eExternalFunction:
+      break;
+    }
+}
+
 expr_t
 VariableNode::cloneDynamic(DataTree &dynamic_datatree) const
 {
@@ -2558,6 +2591,12 @@ UnaryOpNode::computeXrefs(EquationInfo &ei) const
   arg->computeXrefs(ei);
 }
 
+void
+UnaryOpNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  arg->computeJsonXrefs(ei);
+}
+
 expr_t
 UnaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
 {
@@ -3994,6 +4033,13 @@ BinaryOpNode::computeXrefs(EquationInfo &ei) const
   arg2->computeXrefs(ei);
 }
 
+void
+BinaryOpNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  arg1->computeJsonXrefs(ei);
+  arg2->computeJsonXrefs(ei);
+}
+
 expr_t
 BinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
 {
@@ -4761,6 +4807,14 @@ TrinaryOpNode::computeXrefs(EquationInfo &ei) const
   arg3->computeXrefs(ei);
 }
 
+void
+TrinaryOpNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  arg1->computeJsonXrefs(ei);
+  arg2->computeJsonXrefs(ei);
+  arg3->computeJsonXrefs(ei);
+}
+
 expr_t
 TrinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
 {
@@ -5644,6 +5698,15 @@ ExternalFunctionNode::computeXrefs(EquationInfo &ei) const
     (*it)->computeXrefs(ei);
 }
 
+void
+ExternalFunctionNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  vector<expr_t> dynamic_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    (*it)->computeJsonXrefs(ei);
+}
+
 expr_t
 ExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
 {
@@ -6044,6 +6107,15 @@ FirstDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const
     (*it)->computeXrefs(ei);
 }
 
+void
+FirstDerivExternalFunctionNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  vector<expr_t> dynamic_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    (*it)->computeJsonXrefs(ei);
+}
+
 SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg,
                                                                  int top_level_symb_id_arg,
                                                                  const vector<expr_t> &arguments_arg,
@@ -6359,6 +6431,15 @@ SecondDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const
     (*it)->computeXrefs(ei);
 }
 
+void
+SecondDerivExternalFunctionNode::computeJsonXrefs(JsonEquationInfo &ei) const
+{
+  vector<expr_t> dynamic_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    (*it)->computeJsonXrefs(ei);
+}
+
 void
 SecondDerivExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number,
                                          bool lhs_rhs, const temporary_terms_t &temporary_terms,
diff --git a/ExprNode.hh b/ExprNode.hh
index e4e5d9bcd0fd7d9d4dc1fbfae070116ac15e1af5..c6dca035285f16b10dee237d014333d32db90d1e 100644
--- a/ExprNode.hh
+++ b/ExprNode.hh
@@ -171,6 +171,14 @@ protected:
     set<int> exo_det;
   };
 
+  struct JsonEquationInfo
+  {
+    set<pair<int, int> > param;
+    set<pair<int, int> > endo;
+    set<pair<int, int> > exo;
+    set<pair<int, int> > exo_det;
+  };
+
 public:
   ExprNode(DataTree &datatree_arg);
   virtual ~ExprNode();
@@ -310,6 +318,7 @@ public:
    */
   //  virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det) const = 0;
   virtual void computeXrefs(EquationInfo &ei) const = 0;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const = 0;
   //! Try to normalize an equation linear in its endogenous variable
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > > &List_of_Op_RHS) const = 0;
 
@@ -497,6 +506,7 @@ public:
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const;
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables);
   virtual int maxEndoLead() const;
@@ -553,6 +563,7 @@ public:
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const;
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   SymbolType
   get_type() const
   {
@@ -652,6 +663,7 @@ public:
   };
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables);
   virtual int maxEndoLead() const;
@@ -756,6 +768,7 @@ public:
   }
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables);
   virtual int maxEndoLead() const;
@@ -841,6 +854,7 @@ public:
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const;
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables);
   virtual int maxEndoLead() const;
@@ -928,6 +942,7 @@ public:
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const = 0;
   virtual expr_t toStatic(DataTree &static_datatree) const = 0;
   virtual void computeXrefs(EquationInfo &ei) const = 0;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const = 0;
   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<pair<int, pair<expr_t, expr_t> > >  &List_of_Op_RHS) const;
   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables);
   virtual int maxEndoLead() const;
@@ -989,6 +1004,7 @@ public:
   virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const;
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
 };
@@ -1030,6 +1046,7 @@ public:
                                              deriv_node_temp_terms_t &tef_terms) const;
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
 };
@@ -1073,6 +1090,7 @@ public:
                                              deriv_node_temp_terms_t &tef_terms) const;
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual void computeXrefs(EquationInfo &ei) const;
+  virtual void computeJsonXrefs(JsonEquationInfo &ei) const;
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
 };
diff --git a/ModFile.cc b/ModFile.cc
index 7ee204ad42bed09eac3225e775a939c01242eca2..ea9cf4e378dc0b8032dc9c6047bb5243d0348b41 100644
--- a/ModFile.cc
+++ b/ModFile.cc
@@ -414,6 +414,9 @@ ModFile::transformPass(bool nostrict)
   // Freeze the symbol table
   symbol_table.freeze();
 
+  //! Need access to this info after transform pass so calculate it here
+  dynamic_model.computeJsonXrefs();
+
   /*
     Enforce the same number of equations and endogenous, except in three cases:
     - ramsey_model, ramsey_policy or discretionary_policy is used