IMSS · Contribution weeks

A person's full work history, from their CURP.

The IMSS Certificate of Contributed Weeks through an API. You get the official PDF with folio and digital seal, the job history as JSON, and the signals your risk model needs: tenure, stability and salary evolution.

input: CURP onlyofficial PDF + JSONresult to your webhook
semanas-cotizadasAPI EXAMPLES

Pick a scenario and see what your system receives:

Fictional data with the exact structure the API returns. None of it belongs to a real person.

Where it fits

The whole track record, not just today's snapshot.

Knowing whether someone works today is useful. Knowing how many years they have worked, for how many employers, how much their salary has grown and how long they have been without a job changes a credit decision.

$
Credit originationTenure, stability and historical income as variables for your model, taken from the official document and not from what the person declared.
◈
Hiring and payrollVerify the track record on a résumé: employers, start and end dates, exactly as recorded at IMSS.
⚑
Fraud preventionMade-up histories, jobs that never existed or inflated tenure show up when compared against the certificate.
Available today

We do not ask you to trust us. Check it.

It is common for the contributed weeks certificate to appear in a catalog or in some documentation and not exist when it is time to integrate. So before talking to us, there are three things you can check on your own.

1
The endpoint is publishedWith its route, its inputs and its cost in credits, in the open API reference. No sign-up.See the endpoint ↗
2
Every response has its exampleEvery case it can return, with the full JSON for each one. Not a general description: the contract.See the examples ↗
3
You test it with your own casesWe enable courtesy credits in production. You send your own CURPs and see what comes back, before signing anything.Request access →
What is IMSS's and what is ours

Three layers, always kept apart.

So your risk team and your auditor know exactly where every number comes from, the response separates what comes from the document from what we calculate.

§
1 · The official documentThe full IMSS PDF, with folio and verifiable digital seal. It is the auditable source: everything else is our reading of it. It arrives in files[0].
◈
2 · Official fieldsWhat is printed on the certificate, turned into JSON without changing it: weeks, job history, identity and report details. Only the format of dates and amounts is normalized.
∑
3 · Calculated signalsEverything we calculate lives in one place, derivedSignals, and nowhere else. They are measurable facts —months, counts, percentages—, never a score or a recommendation.
The API response

What each part contains.

What you getFieldOriginWhat it contains
Contributed weekscontributionWeeksOfficialTotal, contributed, discounted and reinstated, exactly as IMSS prints them.
Job historyemploymentHistory[]OfficialOne row per job, most recent first: employer, employer registration, state, start date, end date and base salary.
IdentitypersonalInfo · nssOfficialName, CURP, date of birth and NSS, as IMSS holds them.
Document detailsreportDetailsOfficialFolio, issue date, serial number and IMSS digital seal.
The PDFfiles[0]OfficialThe full official certificate, in base64.
SignalsderivedSignalsCalculatedCurrent status, tenure, stability, salary and salary timeline.

Currently employed? You can tell in two ways. The quick one is the type: SUCCESS if there is a current job, INACTIVE_EMPLOYMENT if there is not. And to know where they work today, it is the history row with no end date (endDate: null). Every field is always present; the ones that do not apply come as null.

How we calculate it

Every signal, with its formula.

No black boxes. These are the four rules that apply to everything, followed by every signal with its exact operation. You can recompute any of them from the official history and get the same number.

1
The reference date is the issue date"Today" is always the date IMSS issued the certificate, not the day you query it. A current job is measured up to that date.
2
A month is 30.44 daysIt is the calendar average. Months are days divided by 30.44, with one decimal. Monthly salary is the daily one times 30.44.
3
Simultaneous jobs are not counted twiceIf two jobs overlap, the time worked is counted once: periods are merged before adding them up.
4
Official weeks are never recalculatedTotal weeks is arithmetic on the numbers IMSS prints. Calendar time is kept separate and does not equal contributed weeks.

An example, step by step

A person with three jobs. The certificate was issued on October 1, 2026.

EmployerStartEndDaily salaryLength
EMPRESA EJEMPLO UNO2015-03-022017-08-31$250.0030 months
EMPRESA EJEMPLO DOS2018-02-012021-12-15$380.0046.4 months
EMPRESA EJEMPLO TRES2022-03-01current$520.0055 months

Between the first and second job there were 5.1 months without formal employment; between the second and third, 2.5.

SignalHow it is calculatedIn the example
Official weeksContributed − discounted + reinstated, using the numbers printed on the certificate.560 − 4 + 0 = 556
Current status
Employed?Yes, if there is a row with no end date.Yes
Months in current statusEmployed: from the current job's start date to the issue date. Not employed: from the last end date to the issue date.Mar 1, 2022 → Oct 1, 2026 = 55 months
Latest monthly salaryDaily salary of the current (or most recent) job × 30.44.$520.00 × 30.44 = $15,828.80
Salary at the legal capTrue if the daily salary reached the maximum the law allows to be reported: 25 daily UMA, which in 2026 is $2,932.75 per day. The UMA in force on the certificate's issue date is used.$520.00 is below $2,932.75 → No
Tenure
Average per jobSum of each job's length ÷ number of jobs.(30 + 46.4 + 55) ÷ 3 = 43.8 months
Longest and shortest jobThe maximum and minimum of those lengths.55 and 30 months
Months since the first jobFrom the first start date to the issue date.Mar 2, 2015 → Oct 1, 2026 = 139 months
Stability
Jobs and distinct employersRows in the history, and how many different employer registrations appear among them.3 and 3
Average months per employerMonths since the first job ÷ number of jobs.139 ÷ 3 = 46.3 months
Job changesNumber of jobs − 1. In the last 5 years: jobs whose start date falls within 5 years before the issue date.2 total · 1 in 5 years
Periods without a jobEach gap between the end of one worked period and the start of the next. We report how many, their sum, the longest one and how long ago the last one ended.2 gaps · 5.1 + 2.5 = 7.6 months
Months actually employedCalendar time with at least one job, merging the periods that overlap.139 − 7.6 = 131.4 months
% of time employedMonths actually employed ÷ months since the first job.131.4 ÷ 139 = 94.6%
Simultaneous jobsJobs whose period overlaps another one. An end and a start on the same day count as continuity, not as simultaneous.0
Salary
First, latest, highest and lowestDaily salaries in the history, ordered by start date.$250 · $520 · $520 · $250
Change from first to latest(Latest − first) ÷ first × 100.(520 − 250) ÷ 250 = +108%
Employer changes with a raise or a cutEvery time the employer changes, the new salary is compared with the previous one.2 with a raise · 0 with a cut
Salary 1, 3 and 5 years agoThe salary of the job held on that date. If unemployed then, the most recent earlier one. Includes the % change against the current one.$520 · $520 · $380 (+36.8% since then)

These are facts, not a score. We do not return a credit rating or a recommendation: that decision is yours.

Salary has a maximum. What you see is the base salary the employer reports to IMSS, and the law limits it to 25 daily UMA: $2,932.75 per day in 2026, about $89,272.91 per month. Nobody shows a salary above that, no matter how much they earn. So when salaryAtLegalCap is true, the person reached the maximum and their real income may be higher than what you see. The value changes every year, on February 1.

Business cases

Every response already carries its decision.

The type field names the case with a stable code. Your backend runs a switch, it does not interpret text.

typeWhat happenedWhat to do
SUCCESSThe certificate was obtained and the person is currently employed.Proceed. Feed the history and the signals into your model.
INACTIVE_EMPLOYMENTThe certificate was obtained, but there is no current job.Review. You have the full track record and how long they have been without formal employment.
CURP_NOT_FOUNDIMSS could not find that CURP.Review. Check the CURP against RENAPO.
PERSON_WITHOUT_NSSThe CURP exists, but has no NSS assigned.Review. Never registered with IMSS; there is no history.
IMSS_INCONSISTENT_DATAThe CURP exists, but its data is inconsistent at IMSS.Review. The person must clarify it with the institute.
IMSS_OPERATION_LIMITIMSS applied a temporary limit to that query.Retry later.
IMSS_REPORT_UNAVAILABLEIMSS could not generate the report for that record.Retry another day. Not charged.
IMSS_RECORD_ERRORIMSS returned an unexpected error for that record.Retry another day. Not charged.
SERVICE_UNAVAILABLEIMSS is not available.Retry. Not charged.
INVALID_REQUESTThe CURP is malformed or the webhook is missing. Answered immediately, when you create the query.Fix the request. Not charged.
How it works

You send the CURP. The result arrives at your system.

Gathering a full work history takes longer than it makes sense to keep a request open. So you do not wait for the result: it is delivered to an address of yours, called a webhook, as soon as it is ready.

{ }
You send the CURPwith your webhook address
You get a receiptwith a query ID
✓
The result arrivesat your webhook, with the same ID

First time using a webhook? We explain it step by step →

If your webhook failed

The result is not lost: ask for it with the ID.

We try the delivery three times. If your address could not receive it, for 24 hours you can ask for the result by sending the ID we gave you in the receipt. This query is free.

typeWhat it meansWhat to do
RESULT_FOUNDThe result is ready. It comes complete inside data, identical to the one sent to your webhook.Use it. It is the same result, with no extra charge.
RESULT_PENDINGThe query is still in progress.Wait. The result will be sent to your webhook when it is ready.
RESULT_EXPIREDMore than 24 hours have passed since it resolved.Query the CURP again if you still need the data.
INVALID_REQUESTThe ID does not exist or belongs to another account.Check the ID you stored from the receipt.

It is a fallback, not the normal path: the result is always sent to your webhook, so there is no need to ask again and again to know whether it is ready.

consultar-resultado
const res = await fetch("https://api.origoid.com/mex/social-security/v1/imss-contribution-weeks-results", {
  method: "POST",
  headers: {
    "x-api-key": process.env.ORIGOID_API_KEY,
    "content-type": "application/json",
  },
  // the transaction ID you got in the receipt
  body: JSON.stringify({ transactionId: "975cf12f-f270-51cc-9037-d710134940c9" }),
});

const r = await res.json();
if (r.type === "RESULT_FOUND") process(r.data.type, r.data.data);
curl -X POST https://api.origoid.com/mex/social-security/v1/imss-contribution-weeks-results \
  -H "x-api-key: $ORIGOID_API_KEY" \
  -H "content-type: application/json" \
  -d '{"transactionId": "975cf12f-f270-51cc-9037-d710134940c9"}'
Response
{
  "status": "OK",
  "type": "RESULT_FOUND",
  "data": {
    "type": "SUCCESS",
    "data": { "contributionWeeks": { … }, "employmentHistory": [ … ] },
    "transactionId": "975cf12f-f270-51cc-9037-d710134940c9",
    "billable": true
  },
  "billable": false
}
Raw infrastructure · 100% REST API

One call. One input.

You send the CURP and your webhook address. Same envelope as every OrigoID service.

CURP onlyYou do not need the NSS or any other detail about the person.
3 credits per resolved queryCharged when there is a result. The receipt and the fallback query are free.
Available for 24 hours, then deletedThe result is kept only for that period, as a delivery fallback. We do not use it for anything else.
semanas-cotizadas
const res = await fetch("https://api.origoid.com/mex/social-security/v1/imss-contribution-weeks", {
  method: "POST",
  headers: {
    "x-api-key": process.env.ORIGOID_API_KEY,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    curp: "XEXX010101HNEXXXA4",
    webhook: { url: "https://your-domain.com/hooks/origoid" },
  }),
});

const receipt = await res.json(); // type: "ACCEPTED"
import os, requests

res = requests.post(
    "https://api.origoid.com/mex/social-security/v1/imss-contribution-weeks",
    headers={"x-api-key": os.environ["ORIGOID_API_KEY"]},
    json={
        "curp": "XEXX010101HNEXXXA4",
        "webhook": {"url": "https://your-domain.com/hooks/origoid"},
    },
    timeout=30,
)
receipt = res.json()  # type: "ACCEPTED"
curl -X POST https://api.origoid.com/mex/social-security/v1/imss-contribution-weeks \
  -H "x-api-key: $ORIGOID_API_KEY" \
  -H "content-type: application/json" \
  -d '{"curp": "XEXX010101HNEXXXA4", "webhook": {"url": "https://your-domain.com/hooks/origoid"}}'
Immediate receipt
{
  "status": "OK",
  "type": "ACCEPTED",
  "transactionId": "975cf12f-f270-51cc-9037-d710134940c9",
  "billable": false
}
What arrives at your webhook (abbreviated)
{
  "type": "SUCCESS",
  "data": {
    "contributionWeeks": { "total": 556, "contributed": 560, "discounted": 4, "reinstated": 0 },
    "employmentHistory": [{
      "employerName": "EMPRESA EJEMPLO TRES S.A. DE C.V.",
      "startDate": "2022-03-01", "endDate": null,
      "baseSalary": { "amount": "520.00", "currency": "MXN" }
    }],
    "derivedSignals": {
      "currentStatus": { "employed": true, "monthsInCurrentStatus": 55 },
      "stability": { "percentOfTimeEmployed": 94.6, "jobChanges": 2 }
    },
    "reportDetails": { "folio": "0000…", "digitalSeal": "…" },
    "files": [{ "contentType": "application/pdf", "content": "JVBERi0x…" }]
  },
  "transactionId": "975cf12f-f270-51cc-9037-d710134940c9",
  "billable": true
}
Has your team never used a webhook?

We prepared a guide that explains it without jargon: what it is, what your system needs to receive the result and how to get it working.

See the webhooks guide →
Why OrigoID

The document is IMSS's. What changes is what you do with it.

A PDF certificate is evidence, but it does not go into a risk model. The difference is delivering it already read, with the math done and the origin of every number in plain sight.

§
AuditableYou get the official PDF with folio and digital seal. Any structured value can be checked against the document.
◈
Ready for your modelThe history as JSON and more than thirty signals already calculated. No reading a PDF, no manual entry.
∑
TransparentEvery signal has its formula published. Measurable facts, no score and no black box.
$
Published pricing3 credits per query, and the price per credit drops with your volume. All public. See pricing

OrigoID is not IMSS and does not act on its behalf: it is a technical means of querying and cross-checking against that source. The accuracy and currency of the information depend on the institute itself.

Frequently asked

What people usually ask us.

What is the Certificate of Contributed Weeks?

The official IMSS document that summarizes a person's working life: how many weeks they have contributed and, job by job, with which employer, on which dates and with what base salary.

What do I need to query it?

Only the person's CURP and a webhook address to receive the result. You do not need the NSS.

What do you calculate and what comes from IMSS?

From IMSS come the PDF, the weeks, the job history, the identity and the document details. We calculate only what is in derivedSignals: current status, tenure, stability and salary. Every signal has its formula published on this page.

Do you return a credit score?

No. We return measurable facts —months, counts, percentages and amounts—. The rating and the decision are yours.

Is the salary shown their real pay?

It is the daily base salary the employer reports to IMSS. The monthly equivalent is that salary times 30.44. It has a legal maximum of 25 daily UMA, $2,932.75 per day in 2026: when salaryAtLegalCap is true, the person reached that maximum and their real income may be higher.

How do I receive the result?

At your webhook. When you create the query you get a receipt with an ID; when the result is ready we send it to your address with that same ID. If your webhook failed, you can fetch it for 24 hours.

How much does it cost?

3 credits per resolved query. The receipt, the fallback query and the cases where IMSS could not generate the report are not charged. Plans are published.

Do you store the certificate?

The result stays available for 24 hours as a delivery fallback and is then deleted. We do not use it for any other purpose.

Try it with your own cases.

Courtesy credits to query in production. Access is enabled after a brief validation of your company.

Request access