ITR Verification

5 endpoints · Core API

Retrieve a taxpayer's filed income tax returns (ITR) using the taxpayer's own income tax e-filing portal user ID (PAN), password and consent. The ITR-V (Income Tax Return Verification) is the receipt that confirms a return was filed; it summarises income, tax liability and taxes paid, which makes these returns a reliable source for loan underwriting, income assessment and financial onboarding.

Five endpoints are listed below: a recommended asynchronous fetch (POST /api/v1/itr/requests) with two status reads, a synchronous call (POST /api/v1/itr/verify) and a deprecated one (POST /api/v1/itr/fetch). The cards under the description say which to use when.

What you can do

Quick Access to Tax Records: Retrieve filed returns for timely insight into a taxpayer's filing status, income, liabilities and taxes paid.

Know at once when it fails: wrong credentials, a locked account, an OTP or captcha request, or an unavailable portal are reported in the same response, with a retry time where one applies.

Never miss a result: if a webhook does not reach you, read the result from the status API.

Enhanced Financial Assessment and Compliance Tracking: Use aggregated tax data to evaluate income and financial standing and to verify tax filing status.

Which endpoint should I use?

Pick a card to jump to that endpoint.

Webhook payload

When the request has a webhook_url, SignCare POSTs the outcome there. The x-signcare-event header is itr.fetch.completed or itr.fetch.failed. The body is the status API envelope plus an event_id that stays the same on every retry of the delivery, so use it to ignore a repeat. Reply with any 2xx to acknowledge. Retries run after 30 seconds, 2 minutes and 10 minutes.

FieldTypeMeaning
event_idstringUnique per outcome. Identical on every retry. Deduplicate on it.
successbooleantrue when the returns were fetched.
statusCodeinteger200 on success, otherwise the HTTP status of the failure (400 invalid credentials, 403 locked, 404 no returns, 422 OTP or captcha, 503 portal unavailable, 504 timeout).
messagestringA readable summary. For failures it says what to do next.
data.request_idstringSignCare's id for the request. Use it with the status API.
data.reference_idstringYour own reference, or the one generated for you.
data.statusstringCOMPLETED or FAILED in a webhook.
data.error_codestringFailures only. See ITR Fetch errors.
data.usernamestringThe taxpayer's user ID with all but the last four characters masked.
data.rangeintegerNumber of years delivered.
data.years_foundstring[]Every year the portal listed for the taxpayer, newest first.
data.years_downloadedstring[]The years in result.
data.years_missingobject[]Requested years not delivered, each with a reason of NOT_FILED or DOWNLOAD_FAILED. The request is still COMPLETED.
data.resultobjectThe filed returns keyed by financial year, newest first. Each holds the filing details and the portal's full ITR JSON in itr.

Completed

The itr object is shortened here. In the real payload it holds the portal's complete return.

{
  "event_id": "5d0c7a52-3b1e-4f6a-9c1d-2a7e8b9f0c11",
  "success": true,
  "statusCode": 200,
  "message": "Data Found",
  "messages": [],
  "request_id": "3f1c9b7e-6a52-4d1e-9a0b-2d7c5e8f1a44",
  "data": {
    "request_id": "3f1c9b7e-6a52-4d1e-9a0b-2d7c5e8f1a44",
    "reference_id": "LOAN-12345",
    "status": "COMPLETED",
    "username": "******234F",
    "range": 2,
    "years_found": ["2024-2025", "2023-2024", "2022-2023"],
    "years_downloaded": ["2024-2025", "2023-2024"],
    "years_missing": [],
    "result": {
      "2024-2025": {
        "panNumber": "******234F",
        "filingYear": "2024-2025",
        "assessmentYear": "2025-26",
        "filingDate": "28/07/2025",
        "filingSection": "139(1)",
        "itrType": "1",
        "filingType": "Original",
        "acknowledgementNumber": "123456780280725",
        "filedBy": "",
        "itrFilingStatus": [
          { "statusDescription": "Successfully e-verified", "activityDate": "28/07/2025" },
          { "statusDescription": "Return filed", "activityDate": "28/07/2025" }
        ],
        "itr": { "itR1": { "creationInfo": { "swVersionNo": "1.0" } } }
      },
      "2023-2024": { "...": "same shape as above" }
    }
  }
}

Failed

A failure has no result. data.error_code says why and message says what to do.

{
  "event_id": "9a41c0de-7b2f-4c83-8e15-6d0f3a2b7c90",
  "success": false,
  "statusCode": 400,
  "message": "The user ID or password was not accepted by the income tax portal. Check them and submit again with a new reference_id.",
  "messages": [],
  "request_id": "3f1c9b7e-6a52-4d1e-9a0b-2d7c5e8f1a44",
  "data": {
    "request_id": "3f1c9b7e-6a52-4d1e-9a0b-2d7c5e8f1a44",
    "reference_id": "LOAN-12345",
    "status": "FAILED",
    "error_code": "INVALID_CREDENTIALS"
  }
}

Delayed (status API only)

If the income tax portal temporarily refuses our logins, the request stays PROCESSING and is retried automatically. No webhook is sent for the delay. The status API shows it:

{
  "success": true,
  "statusCode": 200,
  "data": {
    "request_id": "3f1c9b7e-6a52-4d1e-9a0b-2d7c5e8f1a44",
    "reference_id": "LOAN-12345",
    "status": "PROCESSING",
    "notice": "The income tax portal is temporarily refusing logins from us. The request is not lost: it is retried automatically after 2026-10-27 11:15 UTC. You do not need to submit again.",
    "retry_at": "2026-10-27T11:15:00Z"
  }
}

Polling when no webhook arrives

GET /api/v1/itr/requests/{request_id} returns the same body plus webhook_status (PENDING, RETRYING, DELIVERED or FAILED) and webhook_attempts, so you can see whether a delivery failed. The result stays readable for 7 days. Poll after 30 seconds, 1 minute and 5 minutes, then every 15 minutes.

GET

/api/v1/itr/requests

#

Read the status and result of an ITR Fetch request (by reference_id)

docs.signcare.io/core/api/financial/itr-verification/#get-api-v1-itr-requests

Use this when you kept your own reference_id but not the request_id. It returns the same body as the lookup by request_id.

Scope: use the reference_id you sent, or the one returned in the 202 response when you sent none. Only your own requests are found.

Headers

  • X-API-KEY
    stringrequired
    Your secret API key for the environment you are calling (Stage and Live use different keys).
  • X-API-APP-ID
    stringrequired
    The App ID issued together with the key.

Query parameters

  • reference_id
    stringoptional
    No description.

Responses

200OK
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    objectoptional
    The outcome of an ITR Fetch request. Returned (inside the standard response envelope) by the status endpoint and sent as the webhook body.
    14 fields
    • request_id
      stringoptional
      No description.
      nullable
    • reference_id
      stringoptional
      No description.
      nullable
    • status
      stringoptional
      ACCEPTED, QUEUED, PROCESSING, COMPLETED, FAILED, DELIVERED, DELIVERY_FAILED or EXPIRED.
      nullable
    • error_code
      stringoptional
      Set when the request failed: INVALID_CREDENTIALS, ACCOUNT_LOCKED, OTP_REQUIRED, CAPTCHA_REQUIRED, NO_RETURNS_FOUND, PORTAL_UNAVAILABLE, TIMEOUT, INTERNAL_ERROR or INVALID_YEAR_RANGE.
      nullable
    • retry_at
      stringoptional
      Only with `PORTAL_UNAVAILABLE` when the income tax portal blocked the login because of too many recent attempts: the UTC time (ISO 8601) after which a new request is likely to go through. Retrying earlier will most likely be blocked again.
      nullable
    • notice
      stringoptional
      Set while the request is still `PROCESSING` but delayed: the income tax portal is temporarily refusing our logins and the request is retried automatically (see `retry_at`). You do not need to submit again.
      nullable
    • webhook_status
      stringoptional
      Status API only, and only when the request has a webhook_url and has finished: `PENDING` (not sent yet), `RETRYING` (a delivery failed; the next is scheduled), `DELIVERED` or `FAILED` (all attempts failed, so read the result here). Lets a caller whose webhook never arrived see why.
      nullable
    • webhook_attempts
      integer (int32)optional
      Status API only: how many webhook deliveries have been attempted.
      nullable
    • username
      stringoptional
      The taxpayer's user ID with all but the last four characters masked, like `******234F`. Same field name as the synchronous ITR Fetch response. The password is never returned.
      nullable
    • range
      integer (int32)optional
      Number of assessment years delivered.
      nullable
    • years_found
      array<string>optional
      Every year the portal listed for the taxpayer, newest first, labelled like the keys of `result` (e.g. `2024-2025`).
      nullable
    • years_downloaded
      array<string>optional
      The years delivered in `result`: the same labels as its keys, so this list and the keys of `result` are identical.
      nullable
    • years_missing
      array<object>optional
      Requested years that are not in the result. A request with some years missing is still COMPLETED. Reason is NOT_FILED (no return for that year) or DOWNLOAD_FAILED (the portal did not provide the file).
      nullable
      Each item: 3 fields
      • filing_year
        stringoptional
        The year in the same form as the keys of `result` (`2023-2024`), so the lists and `result` can be compared directly. Filled in when the response is built; not stored.
        nullable
      • assessment_year
        stringoptional
        The portal's own label for the same year, e.g. `2024-25` (the form `from_year` / `to_year` use).
        nullable
      • reason
        stringoptional
        NOT_FILED or DOWNLOAD_FAILED.
        nullable
    • result
      objectoptional
      The filed returns, in the same shape as the synchronous ITR Fetch response: an object keyed by assessment year (newest first), each holding `form` and the portal's full ITR JSON in `json`. Each year also says which filing it is (`acknowledgement_number`, `filing_type`, `filing_date`, `filing_section`, `itr_type`). When a year has both an original and a revised return, the latest filing is the one returned.
      nullable
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": { "request_id": "string", "reference_id": "string", "status": "string", "error_code": "string", "retry_at": "string", "notice": "string", "webhook_status": "string", "webhook_attempts": 0, "username": "string", "range": 0, "years_found": [ "string" ], "years_downloaded": [ "string" ], "years_missing": [ { "filing_year": "string", "assessment_year": "string", "reason": "string" } ], "result": {} }, "messages": [ "string" ], "request_id": "string", "isBillable": false }
404Not Found
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    anyoptional
    No description.
    nullable
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": null, "messages": [ "string" ], "request_id": "string", "isBillable": false }
Code samplescurl · Node.js · Python
Stage: uat-ext.signcare.io
curl -X GET 'https://uat-ext.signcare.io/api/v1/itr/requests' \ -H 'X-API-KEY: YOUR_API_KEY' \ -H 'X-API-APP-ID: YOUR_APP_ID'
POST

/api/v1/itr/requests

#

Fetch filed ITRs

docs.signcare.io/core/api/financial/itr-verification/#post-api-v1-itr-requests

Logs in to the income tax e-filing portal with the taxpayer's user ID and password and downloads their latest filed returns. Use this for new integrations. It replaces the deprecated POST /api/v1/itr/fetch.

Answers: in this response if the fetch finishes within about 25 seconds (200 with the result, or the failure with its HTTP status). Otherwise 202 with a request_id, and the result is sent to your webhook_url.

Never miss a result: read it for 7 days with GET /api/v1/itr/requests/{request_id}, which also shows webhook_status when a delivery failed.

Years: range is 1 to 5 (default 3). If fewer returns are filed than you ask for, the request still completes with the years that exist.

Duplicates: send your own reference_id. Sending it again returns the original request, with no second fetch or charge.

Charges: one per request that completes with at least one return. Failed, timed-out and refused requests, and status reads, are free.

Wrong password: never retried, because repeated attempts can lock the taxpayer's account. Submit again with a new reference_id and the right password.

More: every outcome and refusal, webhook retries, portal blocks and privacy are in the ITR Fetch guide.

Headers

  • X-API-KEY
    stringrequired
    Your secret API key for the environment you are calling (Stage and Live use different keys).
  • X-API-APP-ID
    stringrequired
    The App ID issued together with the key.
  • Content-Type
    stringrequired
    application/json

Body parameters

application/json
  • userName
    stringrequired
    Required. The taxpayer's e-filing portal user ID (PAN).
    minLength 1
  • password
    stringrequired
    Required. The taxpayer's e-filing portal password. It is encrypted at once and never stored in readable form.
    minLength 1
  • consent
    booleanrequired
    Required. `"Y"` (or `true`): the taxpayer has authorised the fetch.
  • consent_text
    stringrequired
    Required. The consent wording the taxpayer agreed to (max 1000 characters). Stored with the request.
    minLength 1
  • reference_id
    stringoptional
    Optional. Your unique reference for this request (max 100 characters). Sending the same value again returns the original request instead of starting a second fetch. When omitted, one is generated and returned in the 202 response.
    nullable
  • webhook_url
    stringrequired
    Required. HTTPS URL on a public domain that receives the result (max 500 characters).
    nullable
  • range
    integer (int32)optional
    Optional. How many of the most recent years that have a filed return to fetch: a whole number from 1 to 5. Omit it for the default of 3. Zero, negative numbers and values above 5 are refused (more years take longer and make the response larger).
    nullable
Sample request body
{ "userName": "string", "password": "string", "consent": false, "consent_text": "string", "webhook_url": "string" }

Responses

200OK
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    objectoptional
    The outcome of an ITR Fetch request. Returned (inside the standard response envelope) by the status endpoint and sent as the webhook body.
    14 fields
    • request_id
      stringoptional
      No description.
      nullable
    • reference_id
      stringoptional
      No description.
      nullable
    • status
      stringoptional
      ACCEPTED, QUEUED, PROCESSING, COMPLETED, FAILED, DELIVERED, DELIVERY_FAILED or EXPIRED.
      nullable
    • error_code
      stringoptional
      Set when the request failed: INVALID_CREDENTIALS, ACCOUNT_LOCKED, OTP_REQUIRED, CAPTCHA_REQUIRED, NO_RETURNS_FOUND, PORTAL_UNAVAILABLE, TIMEOUT, INTERNAL_ERROR or INVALID_YEAR_RANGE.
      nullable
    • retry_at
      stringoptional
      Only with `PORTAL_UNAVAILABLE` when the income tax portal blocked the login because of too many recent attempts: the UTC time (ISO 8601) after which a new request is likely to go through. Retrying earlier will most likely be blocked again.
      nullable
    • notice
      stringoptional
      Set while the request is still `PROCESSING` but delayed: the income tax portal is temporarily refusing our logins and the request is retried automatically (see `retry_at`). You do not need to submit again.
      nullable
    • webhook_status
      stringoptional
      Status API only, and only when the request has a webhook_url and has finished: `PENDING` (not sent yet), `RETRYING` (a delivery failed; the next is scheduled), `DELIVERED` or `FAILED` (all attempts failed, so read the result here). Lets a caller whose webhook never arrived see why.
      nullable
    • webhook_attempts
      integer (int32)optional
      Status API only: how many webhook deliveries have been attempted.
      nullable
    • username
      stringoptional
      The taxpayer's user ID with all but the last four characters masked, like `******234F`. Same field name as the synchronous ITR Fetch response. The password is never returned.
      nullable
    • range
      integer (int32)optional
      Number of assessment years delivered.
      nullable
    • years_found
      array<string>optional
      Every year the portal listed for the taxpayer, newest first, labelled like the keys of `result` (e.g. `2024-2025`).
      nullable
    • years_downloaded
      array<string>optional
      The years delivered in `result`: the same labels as its keys, so this list and the keys of `result` are identical.
      nullable
    • years_missing
      array<object>optional
      Requested years that are not in the result. A request with some years missing is still COMPLETED. Reason is NOT_FILED (no return for that year) or DOWNLOAD_FAILED (the portal did not provide the file).
      nullable
      Each item: 3 fields
      • filing_year
        stringoptional
        The year in the same form as the keys of `result` (`2023-2024`), so the lists and `result` can be compared directly. Filled in when the response is built; not stored.
        nullable
      • assessment_year
        stringoptional
        The portal's own label for the same year, e.g. `2024-25` (the form `from_year` / `to_year` use).
        nullable
      • reason
        stringoptional
        NOT_FILED or DOWNLOAD_FAILED.
        nullable
    • result
      objectoptional
      The filed returns, in the same shape as the synchronous ITR Fetch response: an object keyed by assessment year (newest first), each holding `form` and the portal's full ITR JSON in `json`. Each year also says which filing it is (`acknowledgement_number`, `filing_type`, `filing_date`, `filing_section`, `itr_type`). When a year has both an original and a revised return, the latest filing is the one returned.
      nullable
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": { "request_id": "string", "reference_id": "string", "status": "string", "error_code": "string", "retry_at": "string", "notice": "string", "webhook_status": "string", "webhook_attempts": 0, "username": "string", "range": 0, "years_found": [ "string" ], "years_downloaded": [ "string" ], "years_missing": [ { "filing_year": "string", "assessment_year": "string", "reason": "string" } ], "result": {} }, "messages": [ "string" ], "request_id": "string", "isBillable": false }
202Accepted
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    objectoptional
    Returned with 202 Accepted when an ITR Fetch request is queued.
    4 fields
    • request_id
      stringoptional
      No description.
      nullable
    • reference_id
      stringoptional
      No description.
      nullable
    • status
      stringoptional
      ACCEPTED, QUEUED, PROCESSING, COMPLETED, FAILED, DELIVERED, DELIVERY_FAILED or EXPIRED.
      nullable
    • duplicate
      booleanoptional
      True when this reference_id was already submitted; the original request is returned.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": { "request_id": "string", "reference_id": "string", "status": "string", "duplicate": false }, "messages": [ "string" ], "request_id": "string", "isBillable": false }
400Bad Request
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    anyoptional
    No description.
    nullable
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": null, "messages": [ "string" ], "request_id": "string", "isBillable": false }
402Payment Requiredsame body as 400
403Forbiddensame body as 400
413Content Too Largesame body as 400
429Too Many Requestssame body as 400
503Service Unavailablesame body as 400
Code samplescurl · Node.js · Python
Stage: uat-ext.signcare.io
curl -X POST 'https://uat-ext.signcare.io/api/v1/itr/requests' \ -H 'X-API-KEY: YOUR_API_KEY' \ -H 'X-API-APP-ID: YOUR_APP_ID' \ -H 'Content-Type: application/json' \ -d '{ "userName": "string", "password": "string", "consent": false, "consent_text": "string", "webhook_url": "string" }'
GET

/api/v1/itr/requests/{requestId}

#

Read the status and result of an ITR Fetch request (by request_id)

docs.signcare.io/core/api/financial/itr-verification/#get-api-v1-itr-requests-requestid

Use this when your webhook did not arrive, or to check a request that is still PROCESSING. It returns the same body as the webhook.

Status: ACCEPTED, QUEUED, PROCESSING, COMPLETED, FAILED, DELIVERED, DELIVERY_FAILED or EXPIRED.

Result: a completed request carries the ITR JSON in result, keyed by financial year. It stays readable for 7 days. Reads are not charged.

Polling: after 30 seconds, 1 minute and 5 minutes, then every 15 minutes. See the ITR Fetch guide.

Headers

  • X-API-KEY
    stringrequired
    Your secret API key for the environment you are calling (Stage and Live use different keys).
  • X-API-APP-ID
    stringrequired
    The App ID issued together with the key.

Path parameters

  • requestId
    stringrequired
    No description.

Responses

200OK
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    objectoptional
    The outcome of an ITR Fetch request. Returned (inside the standard response envelope) by the status endpoint and sent as the webhook body.
    14 fields
    • request_id
      stringoptional
      No description.
      nullable
    • reference_id
      stringoptional
      No description.
      nullable
    • status
      stringoptional
      ACCEPTED, QUEUED, PROCESSING, COMPLETED, FAILED, DELIVERED, DELIVERY_FAILED or EXPIRED.
      nullable
    • error_code
      stringoptional
      Set when the request failed: INVALID_CREDENTIALS, ACCOUNT_LOCKED, OTP_REQUIRED, CAPTCHA_REQUIRED, NO_RETURNS_FOUND, PORTAL_UNAVAILABLE, TIMEOUT, INTERNAL_ERROR or INVALID_YEAR_RANGE.
      nullable
    • retry_at
      stringoptional
      Only with `PORTAL_UNAVAILABLE` when the income tax portal blocked the login because of too many recent attempts: the UTC time (ISO 8601) after which a new request is likely to go through. Retrying earlier will most likely be blocked again.
      nullable
    • notice
      stringoptional
      Set while the request is still `PROCESSING` but delayed: the income tax portal is temporarily refusing our logins and the request is retried automatically (see `retry_at`). You do not need to submit again.
      nullable
    • webhook_status
      stringoptional
      Status API only, and only when the request has a webhook_url and has finished: `PENDING` (not sent yet), `RETRYING` (a delivery failed; the next is scheduled), `DELIVERED` or `FAILED` (all attempts failed, so read the result here). Lets a caller whose webhook never arrived see why.
      nullable
    • webhook_attempts
      integer (int32)optional
      Status API only: how many webhook deliveries have been attempted.
      nullable
    • username
      stringoptional
      The taxpayer's user ID with all but the last four characters masked, like `******234F`. Same field name as the synchronous ITR Fetch response. The password is never returned.
      nullable
    • range
      integer (int32)optional
      Number of assessment years delivered.
      nullable
    • years_found
      array<string>optional
      Every year the portal listed for the taxpayer, newest first, labelled like the keys of `result` (e.g. `2024-2025`).
      nullable
    • years_downloaded
      array<string>optional
      The years delivered in `result`: the same labels as its keys, so this list and the keys of `result` are identical.
      nullable
    • years_missing
      array<object>optional
      Requested years that are not in the result. A request with some years missing is still COMPLETED. Reason is NOT_FILED (no return for that year) or DOWNLOAD_FAILED (the portal did not provide the file).
      nullable
      Each item: 3 fields
      • filing_year
        stringoptional
        The year in the same form as the keys of `result` (`2023-2024`), so the lists and `result` can be compared directly. Filled in when the response is built; not stored.
        nullable
      • assessment_year
        stringoptional
        The portal's own label for the same year, e.g. `2024-25` (the form `from_year` / `to_year` use).
        nullable
      • reason
        stringoptional
        NOT_FILED or DOWNLOAD_FAILED.
        nullable
    • result
      objectoptional
      The filed returns, in the same shape as the synchronous ITR Fetch response: an object keyed by assessment year (newest first), each holding `form` and the portal's full ITR JSON in `json`. Each year also says which filing it is (`acknowledgement_number`, `filing_type`, `filing_date`, `filing_section`, `itr_type`). When a year has both an original and a revised return, the latest filing is the one returned.
      nullable
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": { "request_id": "string", "reference_id": "string", "status": "string", "error_code": "string", "retry_at": "string", "notice": "string", "webhook_status": "string", "webhook_attempts": 0, "username": "string", "range": 0, "years_found": [ "string" ], "years_downloaded": [ "string" ], "years_missing": [ { "filing_year": "string", "assessment_year": "string", "reason": "string" } ], "result": {} }, "messages": [ "string" ], "request_id": "string", "isBillable": false }
400Bad Request
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    anyoptional
    No description.
    nullable
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": null, "messages": [ "string" ], "request_id": "string", "isBillable": false }
404Not Foundsame body as 400
Code samplescurl · Node.js · Python
Stage: uat-ext.signcare.io
curl -X GET 'https://uat-ext.signcare.io/api/v1/itr/requests/{requestId}' \ -H 'X-API-KEY: YOUR_API_KEY' \ -H 'X-API-APP-ID: YOUR_APP_ID'
POST

/api/v1/itr/verify

#

Get ITR details (synchronous)

docs.signcare.io/core/api/financial/itr-verification/#post-api-v1-itr-verify

Synchronous: the details come back in the response of this call. For an asynchronous flow with a webhook, a status API and up to five years, use POST /api/v1/itr/requests.

Request body: userName (required) is the taxpayer's e-filing portal user ID (PAN) and password (required) is the portal password. range (optional, integer) is the number of past years to retrieve. consent and consent_text are required; request_id is optional.

Headers

  • X-API-KEY
    stringrequired
    Your secret API key for the environment you are calling (Stage and Live use different keys).
  • X-API-APP-ID
    stringrequired
    The App ID issued together with the key.
  • Content-Type
    stringrequired
    application/json

Body parameters

application/json
  • consent
    stringrequired
    Required. The end user's consent to this verification. Send `Y`.
    minLength 1default Y
  • consent_text
    stringrequired
    Required. The consent statement shown to the end user. Send the default text from the sample.
    minLength 1default I hear by declare my consent agreeme…
  • request_id
    stringoptional
    Optional. Your own id to correlate this call in your logs. A unique id is generated if you leave it out.
    nullable
  • userName
    stringrequired
    Required. User ID of the taxpayer on the income tax e-filing portal, which is the taxpayer's 10-character PAN (AAAAA9999A).
    minLength 1default ABCDE1234F
  • password
    stringrequired
    Required. Password of the taxpayer on the income tax e-filing portal.
    minLength 1default YOUR_PORTAL_PASSWORD
  • range
    integer (int32)optional
    Optional. Number of past years of ITR data to retrieve (integer). Omit to use the service default.
    nullabledefault 3
Sample request body
{ "consent": "Y", "consent_text": "I hear by declare my consent agreement for fetching my information via SignCare API", "userName": "ABCDE1234F", "password": "YOUR_PORTAL_PASSWORD", "range": 3 }

Responses

200OK
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    objectoptional
    Response model containing ITR verification results.
    6 fields
    • userName
      stringoptional
      Gets or sets the username used for verification.
      nullabledefault ABCDE1234F
    • password
      stringoptional
      Gets or sets the password used for verification.
      nullabledefault Test@123
    • sessionId
      stringoptional
      Gets or sets the session identifier for the verification request.
      nullabledefault itr_AmsPPsLuWpGbyOYxAqpX
    • range
      integer (int32)optional
      Gets or sets the range of years for the ITR data retrieved.
      default 3
    • panNumber
      stringoptional
      Gets or sets the PAN number of the taxpayer.
      nullabledefault ABCDE1234F
    • result
      array<object>optional
      Gets or sets the list of ITR verification results for each filing year.
      nullable
      Each item: 5 fields
      • assessmentYear
        stringoptional
        Gets or sets the assessment year for the ITR filing.
        nullabledefault Base64EncodedString
      • panNumber
        stringoptional
        Gets or sets the PAN number associated with the filing.
        nullabledefault ABCDE1234F
      • filingYear
        stringoptional
        Gets or sets the financial year of the filing.
        nullabledefault 2022-2023
      • acknowledgementNumber
        stringoptional
        Gets or sets the acknowledgement number of the ITR filing.
        nullabledefault 462158851291013
      • filingType
        stringoptional
        Gets or sets the type of filing (e.g., Original, Revised).
        nullabledefault Original
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": { "userName": "ABCDE1234F", "password": "Test@123", "sessionId": "itr_AmsPPsLuWpGbyOYxAqpX", "range": 3, "panNumber": "ABCDE1234F", "result": [ { "assessmentYear": "Base64EncodedString", "panNumber": "ABCDE1234F", "filingYear": "2022-2023", "acknowledgementNumber": "462158851291013", "filingType": "Original" } ] }, "messages": [ "string" ], "request_id": "string", "isBillable": false }
400Bad Request
  • data
    objectoptional
    No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • success
    booleanoptional
    No description.
    default false
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • isBillable
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 400
Example
{ "data": {}, "messages": [ "string" ], "request_id": "string", "success": false, "message": "XXXXX", "isBillable": false, "statusCode": 400 }
401Unauthorized
  • data
    objectoptional
    No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • success
    booleanoptional
    No description.
    default false
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • isBillable
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 401
Example
{ "data": {}, "messages": [ "string" ], "request_id": "string", "success": false, "message": "XXXXX", "isBillable": false, "statusCode": 401 }
500Internal Server Error
  • data
    objectoptional
    No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • success
    booleanoptional
    No description.
    default false
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • isBillable
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 500
Example
{ "data": {}, "messages": [ "string" ], "request_id": "string", "success": false, "message": "XXXXX", "isBillable": false, "statusCode": 500 }
Code samplescurl · Node.js · Python
Stage: uat-ext.signcare.io
curl -X POST 'https://uat-ext.signcare.io/api/v1/itr/verify' \ -H 'X-API-KEY: YOUR_API_KEY' \ -H 'X-API-APP-ID: YOUR_APP_ID' \ -H 'Content-Type: application/json' \ -d '{ "consent": "Y", "consent_text": "I hear by declare my consent agreement for fetching my information via SignCare API", "userName": "ABCDE1234F", "password": "YOUR_PORTAL_PASSWORD", "range": 3 }'
POST

/api/v1/itr/fetch

#Deprecated

Get ITR details (deprecated)

This endpoint is deprecated.

docs.signcare.io/core/api/financial/itr-verification/#post-api-v1-itr-fetch

Deprecated. Use POST /api/v1/itr/requests (asynchronous, result by webhook or status read). This endpoint keeps working for existing integrations but receives no new features.

Request body: userName (required) is the taxpayer's e-filing portal user ID (PAN) and password (required) is the portal password. This endpoint does not use a range field. consent and consent_text are required; request_id is optional.

Headers

  • X-API-KEY
    stringrequired
    Your secret API key for the environment you are calling (Stage and Live use different keys).
  • X-API-APP-ID
    stringrequired
    The App ID issued together with the key.
  • Content-Type
    stringrequired
    application/json

Body parameters

application/json
  • consent
    stringrequired
    Required. The end user's consent to this verification. Send `Y`.
    minLength 1default Y
  • consent_text
    stringrequired
    Required. The consent statement shown to the end user. Send the default text from the sample.
    minLength 1default I hear by declare my consent agreeme…
  • request_id
    stringoptional
    Optional. Your own id to correlate this call in your logs. A unique id is generated if you leave it out.
    nullable
  • userName
    stringrequired
    Required. User ID of the taxpayer on the income tax e-filing portal, which is the taxpayer's 10-character PAN (AAAAA9999A).
    minLength 1default ABCDE1234F
  • password
    stringrequired
    Required. Password of the taxpayer on the income tax e-filing portal.
    minLength 1default YOUR_PORTAL_PASSWORD
Sample request body
{ "consent": "Y", "consent_text": "I hear by declare my consent agreement for fetching my information via SignCare API", "userName": "ABCDE1234F", "password": "YOUR_PORTAL_PASSWORD" }

Responses

200OK
  • success
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 200
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • data
    objectoptional
    No description.
    6 fields
    • username
      stringoptional
      No description.
      nullable
    • password
      stringoptional
      No description.
      nullable
    • id
      integer (int32)optional
      No description.
    • sessionId
      stringoptional
      No description.
      nullable
    • range
      integer (int32)optional
      No description.
    • result
      anyoptional
      No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • isBillable
    booleanoptional
    Whether this request was charged: true if it was, false if not. Errors always show false. Flows that finish later (ITR Fetch, SHCIL eStamp, DigiLocker, eSign) show false here, because the charge is made when the result is ready. eSign charges each signer when they complete signing. DigiLocker deducts the credit when the link is created and refunds it automatically if the link expires before the user completes it.
Example
{ "success": false, "statusCode": 200, "message": "XXXXX", "data": { "username": "string", "password": "string", "id": 0, "sessionId": "string", "range": 0, "result": null }, "messages": [ "string" ], "request_id": "string", "isBillable": false }
400Bad Request
  • data
    objectoptional
    No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • success
    booleanoptional
    No description.
    default false
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • isBillable
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 400
Example
{ "data": {}, "messages": [ "string" ], "request_id": "string", "success": false, "message": "XXXXX", "isBillable": false, "statusCode": 400 }
401Unauthorized
  • data
    objectoptional
    No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • success
    booleanoptional
    No description.
    default false
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • isBillable
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 401
Example
{ "data": {}, "messages": [ "string" ], "request_id": "string", "success": false, "message": "XXXXX", "isBillable": false, "statusCode": 401 }
500Internal Server Error
  • data
    objectoptional
    No description.
  • messages
    array<string>optional
    No description.
    nullable
  • request_id
    stringoptional
    No description.
    nullable
  • success
    booleanoptional
    No description.
    default false
  • message
    stringoptional
    No description.
    nullabledefault XXXXX
  • isBillable
    booleanoptional
    No description.
  • statusCode
    integer (int32)optional
    No description.
    default 500
Example
{ "data": {}, "messages": [ "string" ], "request_id": "string", "success": false, "message": "XXXXX", "isBillable": false, "statusCode": 500 }
Code samplescurl · Node.js · Python
Stage: uat-ext.signcare.io
curl -X POST 'https://uat-ext.signcare.io/api/v1/itr/fetch' \ -H 'X-API-KEY: YOUR_API_KEY' \ -H 'X-API-APP-ID: YOUR_APP_ID' \ -H 'Content-Type: application/json' \ -d '{ "consent": "Y", "consent_text": "I hear by declare my consent agreement for fetching my information via SignCare API", "userName": "ABCDE1234F", "password": "YOUR_PORTAL_PASSWORD" }'