You can add a hook to Optimization`NMinimizeDump`converge to capture the errors (in the input xstep and in the objective function fstep):
Internal`InheritedBlock[{Optimization`NMinimizeDump`converge},
PrependTo[DownValues@Optimization`NMinimizeDump`converge,
HoldPattern[Optimization`NMinimizeDump`converge[args__] /; ! TrueQ[$in]] :>
Block[{$in = True},
{xStep, xNew, fStep, fNew, atol, rtol} = {args};
Optimization`NMinimizeDump`converge[args]]
];
NMinimize[Sin[Tan[x]/2], x, AccuracyGoal -> 9, PrecisionGoal -> 8]
]
{xStep, xNew, fStep, fNew, atol, rtol}
% /. {xStep_, xNew_, fStep_, fNew_, atol_, rtol_} :>
{LessEqual[Norm[xStep] / (atol + rtol * Norm[xNew]), 1 / 2]
, LessEqual[Norm[fStep] / (atol + rtol * Norm[fNew]), 1 / 2]
(*,Less[Min[fStep / (1 + fNew + -fStep)], -1000]*)}
(*
{-1., {x -> -1.26263}}
{{0.}, {-1.26263}, {0.}, {-1.}, 1/1000000000, 1/100000000}
{True, True}
*)
The parameter atol ia the absolute tolerance defined by AccuracyGoal and rtol is the relative tolerance defined by PrecisionGoal. The LessEqual comparisons are the criteria for determining convergence. (The commented criterion is the test for divergence.)
Each numerical function uses different criteria, which are implemented each in their own way. See this answer for a general discussion of the ways AccuracyGoal and PrecisionGoal determine convergence criteria. The OP mentioned NMinimize explicitly, which is the command I looked into.