Estimates
Monthly income, employment status and tenure computed with your own window, sources and date, plus a monthly history.
GET /estimates/{identifier} returns three estimates for an individual: monthly_income, employment_status and tenure. You choose how they are computed:
- how much history to use, from 3 to 24 months
- income from invoices only, or from IMSS/ISSSTE records only
- as of a past date, to backtest against loan outcomes
- a monthly series: what we would have estimated at the end of each month
The values are computed on every request and never stored. The call doesn't create a verification and isn't billed.
All three values are estimates derived from the data available for the identifier. They are not declared or certified figures.
Access
The identifier must be an 18-char CURP with a valid consent and a verification by your company in the last 90 days. Otherwise the call returns 404 verification_not_found. 404 identifier_not_found means we have no data for that CURP.
Parameters
All parameters are optional.
| Parameter | Values | Default | What it does |
|---|---|---|---|
window_months | 3, 6, 9, 12, 24 | 12 | Months of history used: invoices, payroll invoices (nóminas), and maximum age of IMSS/ISSSTE data. |
sources | all, invoices, employments | all | Data used for all three values. invoices = nóminas plus own billing (ingreso minus egreso). employments = IMSS/ISSSTE records only. |
as_of | YYYY-MM-DD | today | Computes the values as of that date, using only data dated on or before it. |
history | true, false | false | Adds a history array with one estimate per month, up to 18 months. |
- Short windows show the current situation.
window_months=3reflects the last three months. The default 12-month window intentionally gives a broader estimate. - Long windows use whatever history exists. If an identifier has 12 months of invoices,
window_months=24divides billing by those 12 months, not by 24, so the income is not understated. as_oflimits. It can't be in the future, andas_ofminuswindow_monthsmust be within the last 24 months. Otherwise the call returns 400invalid_parameter.
Every response includes parameters with all the effective values, defaults included, and computed_at (when the values were computed, UTC). computed_at is not as_of: as_of is the date the values refer to.
Response fields
monthly_income: estimated net monthly income in MXN, as a decimal string.nullwhen there isn't enough data.income_source: wheremonthly_incomecomes from:invoices(nóminas or own billing),employment(IMSS/ISSSTE salary),blended(both) ornone(no estimate).employment_status:employed,self_employed,retired,unemployedorunknown. See Employment Status.tenure: minimum verifiable tenure with the current employer, as a floor bucket.
Tenure
| Value | Meaning |
|---|---|
less_than_3_months | Employed, with evidence of the current employer (a recurring nómina in the last 60 days or an active employment record) that covers less than 3 months. Typical in the first months after a job change. |
3_months_plus, 6_months_plus, 9_months_plus, 12_months_plus | At least that many months can be verified. Always a floor: the real tenure may be longer. |
null | Doesn't apply or unknown: the status isn't employed, or there is no employer-level evidence. |
Tenure is counted with the current employer, so it resets when the person changes employer.
What counts toward monthly_income
monthly_incomemonthly_income is salary (from nóminas or IMSS/ISSSTE records) plus own billing (income invoices minus expense invoices), normalized to a monthly amount over your window_months. In particular:
unemployedhas no income.monthly_incomeisnullandincome_sourceisnone. This only applies as of today, since past dates never returnunemployed.- Severance is discounted. In a payroll invoice that combines regular pay with severance (a finiquito), only the non-severance share counts. Payroll invoices made only of one-off concepts (profit-sharing, year-end bonus, severance) don't count.
- Older payroll counts only if it's ordinary. When salary comes from payroll older than the recent window, extraordinary payroll (type
E, periodicity99) is excluded.
Past dates and IMSS/ISSSTE records
With a past as_of (and in every history month):
- Invoices are exact. Each one has its issue date, so only invoices issued on or before
as_ofcount. - IMSS/ISSSTE records use the current salary. A record counts if it was active on that date (started on or before it and not ended yet), but its salary is the one on the record today: we update these records in place and don't keep past salaries.
- IMSS/ISSSTE records expire. A record counts for status and tenure only if we updated it within
window_months × 30days before the date, and for income only if we updated it within the last year (or the window, if longer). This also applies withas_of= today; withwindow_months=3that is 90 days. - Pensions read as employment in the past. An ISSSTE record that is a pension today (no end date) counts as an active job in earlier months, so a retiree's series reads
employedin past months andretiredin the current one. unemployedandretiredare not returned for past dates. Those signals describe today and can't be dated, so past values areemployed,self_employedorunknown.
Monthly history
With history=true the response adds history: one item per calendar month, ordered from the most recent month to the oldest.
- Each month is computed as of its last day, with the same
window_monthsandsources, using only data dated up to that day. The most recent item is the month ofas_of, computed as ofas_ofitself. - The series only covers months we have: from the identifier's first month with data to the month of
as_of, up to 18 months. An identifier with 6 months of data gets 6 items; one with 21 months gets the most recent 18. - The start date of an IMSS/ISSSTE job counts as data: a job started in 2015 gives 18 items even if invoices start later.
- A month without data inside the series is still returned, with
monthly_income: null,income_source: noneandemployment_status: unknown, so it can't be confused with zero income. - Each month uses today's formula, applied retroactively to the data dated up to that month.
Examples
12-month window (default)
curl https://api.burodeingresos.com/estimates/MAPE850312HDFRRR02 \
-H "X-API-Key: $API_KEY"Invoices only
curl "https://api.burodeingresos.com/estimates/MAPE850312HDFRRR02?sources=invoices" \
-H "X-API-Key: $API_KEY"As of a past date
curl "https://api.burodeingresos.com/estimates/MAPE850312HDFRRR02?as_of=2026-03-31" \
-H "X-API-Key: $API_KEY"Monthly history
curl "https://api.burodeingresos.com/estimates/MAPE850312HDFRRR02?window_months=6&history=true" \
-H "X-API-Key: $API_KEY"{
"identifier": "MAPE850312HDFRRR02",
"computed_at": "2026-10-14T16:20:05Z",
"parameters": { "window_months": 6, "sources": "all", "as_of": "2026-10-14", "history": true },
"monthly_income": "35000.00",
"income_source": "invoices",
"employment_status": "employed",
"tenure": "12_months_plus",
"history": [
{ "month": "2026-10", "monthly_income": "35000.00", "income_source": "invoices", "employment_status": "employed", "tenure": "12_months_plus" },
{ "month": "2026-09", "monthly_income": "35000.00", "income_source": "invoices", "employment_status": "employed", "tenure": "12_months_plus" },
{ "month": "2026-08", "monthly_income": "35000.00", "income_source": "invoices", "employment_status": "employed", "tenure": "9_months_plus" }
]
}Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_parameter | A parameter has an invalid value (window_months other than 3/6/9/12/24, unknown sources, malformed or future as_of, as_of outside the 24 months of history, or an identifier that isn't a CURP). details names the parameter. |
| 401 | Invalid or missing API key. | |
| 404 | verification_not_found | No valid consent and verification by your company in the last 90 days. |
| 404 | identifier_not_found | We have no data for that CURP. |
Updated 3 days ago
