Code Samples
Python, Node.js & cURL β All three integration models
Developer resources
Six resources, six purposes. Pick the one that matches where you are in your integration.
SAT Integration Hub
Start here: what the SAT API exposes, how CRiskCo abstracts SOAP/CIEC, and technical FAQ.
Go to pageAPI Integration Guide
End-to-end walkthrough: authentication, integration models (Approve / White-label / Webhook), and the full endpoint catalog.
Go to pageCode Samples
Copy-paste snippets in Python, Node.js, and cURL for every common flow.
Tutorials
Step-by-step beginner guides: first request, authentication, and monitoring.
Go to pageAPI Explorer
Every endpoint and every field in one searchable view. Built for teams evaluating or migrating their integration.
Go to pageAPI Docs
Complete technical reference: every endpoint, parameter, response schema, and error code.
Open docsSetup
import requests
BASE_URL = "https://service.criskco.com/apiservice.svc"
HEADERS = {
"apiId": "YOUR_API_ID",
"apiKey": "YOUR_API_KEY",
"Content-Type": "application/json",
"Accept-Encoding": "gzip, deflate"
}
Model A β Approve API (Full Control)
Step 1 β Validate RFC
def validate_rfc(rfc, name=None, postal=None):
params = {"rfc": rfc}
if name:
params["name"] = name
if postal:
params["postal"] = postal
r = requests.get(f"{BASE_URL}/ValidateRFC", headers=HEADERS, params=params)
return r.json()
result = validate_rfc("GAPXXXXXXXXX", name="GAP", postal="06600")
if not result["Success"]:
raise Exception(f"RFC invalid: {result['message']}")
print(result["message"])
Step 2 β Onboard the Applicant
def onboard_applicant(rfc, ciec_password, email, ref_id=""):
payload = {
"IsAgreeTerms": True,
"DateAgreeTerms": "2026-03-24",
"VersionAgreeTerms": "1",
"Email": email,
"User": rfc,
"Password": ciec_password,
"RefApplicantId": ref_id
}
r = requests.post(
f"{BASE_URL}/OnboardingSatIntegration",
headers=HEADERS, json=payload
)
return r.json()
result = onboard_applicant(
rfc="GAPXXXXXXXXX",
ciec_password="CIEC_PASSWORD",
email="contact@empresa.com",
ref_id="loan-app-00482"
)
Step 3 β Poll for Status and Get applicantId
import time
def wait_for_applicant(tax_id, max_attempts=10, interval=5):
for _ in range(max_attempts):
r = requests.get(
f"{BASE_URL}/get-applicants",
headers=HEADERS,
params={"taxId": tax_id, "onboardingStatus": "true"}
)
applicants = r.json().get("applicant", [])
if applicants and applicants[0].get("status") == "Available":
return applicants[0]["applicantId"]
time.sleep(interval)
raise TimeoutError("Applicant not Available within timeout")
applicant_id = wait_for_applicant("GAPXXXXXXXXX")
Model B β Hosted Page
Redirect the applicant to CRiskCo's onboarding page. No API call needed for onboarding.
Option 1 β General onboarding
Standard page β the applicant enters your reference code during the flow:
https://app.criskco.com/onboarding/#!/app/referrer-es
Option 2 β White-label onboarding
Requires white-label provisioning with CRiskCo:
https://yourbrand.criskco.com/onboarding/#!/app/
Then poll using refApplicantId:
def get_applicant_by_ref(ref_id):
r = requests.get(
f"{BASE_URL}/get-applicants",
headers=HEADERS,
params={"refApplicantId": ref_id, "onboardingStatus": "true"}
)
applicants = r.json().get("applicant", [])
return applicants[0] if applicants else None
applicant = get_applicant_by_ref("loan-app-00482")
if applicant and applicant["status"] == "Available":
applicant_id = applicant["applicantId"]
Model C β Webhooks
Register Your Webhook
def register_webhook(callback_url):
r = requests.post(
f"{BASE_URL}/Subscriptions",
headers=HEADERS,
json={"CallbackUrl": callback_url}
)
result = r.json()
if result.get("success"):
sub = result["ApiSubscriptionData"]
print(f"Subscription {sub['SubscriptionId']} created: {sub['Active']}")
return result
register_webhook("https://yourdomain.com/webhooks/criskco")
Handle Incoming Webhook Events
from flask import Flask, request, jsonify
import json, requests as req
app = Flask(__name__)
@app.route("/webhooks/criskco", methods=["GET"])
def webhook_validation():
return "", 200 # Respond within 2 seconds
@app.route("/webhooks/criskco", methods=["POST"])
def webhook_handler():
event = request.json
applicant_id = event.get("applicantId")
file_type = event.get("FileType")
if file_type == "JSON":
payload = json.loads(event.get("APIResponse", "{}"))
elif file_type == "JSON_LINK":
url = event["DownloadUrlList"][0]
payload = req.get(url).json()
if payload.get("onboardingStatus") == "Available":
print(f"Applicant {applicant_id} ready")
blacklists = payload.get("blackLists", [])
if blacklists:
print(f"WARNING: Blacklist flags: {blacklists}")
return jsonify({"received": True}), 200
Manage Subscriptions
List all active subscriptions and delete by ID.
# List all subscriptions
def list_subscriptions():
r = requests.get(f"{BASE_URL}/Subscriptions", headers=HEADERS)
return r.json()
# Delete a subscription by ID (POST with id query param)
def delete_subscription(subscription_id):
r = requests.post(
f"{BASE_URL}/Subscriptions",
headers=HEADERS,
params={"id": subscription_id}
)
return r.json()
SAT Compliance Data
Tax Status
def get_tax_status(tax_id):
r = requests.get(
f"{BASE_URL}/GetCompanyTaxStatus",
headers=HEADERS,
params={"taxId": tax_id}
)
company = r.json()["CompanyTaxStatus"][0]
print(f"Status: {company['PayingTax']}")
if company["PayingTax"] == "NEGATIVO":
for ob in company.get("CompanyObligationsList", []):
print(f" Obligation: {ob['Obligation']} ({ob['Month']}/{ob['Year']})")
return company
Historical FinScore
def get_finscore_history(tax_id):
r = requests.get(
f"{BASE_URL}/GetHistoricalFinscore",
headers=HEADERS,
params={"taxId": tax_id}
)
scores = r.json().get("HistoricalFinscores", [])
for s in sorted(scores, key=lambda x: (x["Year"], x["Month"])):
print(f"{s['Year']}-{s['Month']:02d}: {s['FinScore']}")
return scores
Financial Data
All Financials in One Call
def get_all_financials(applicant_id):
r = requests.post(
f"{BASE_URL}/grouping/applicant-financials",
headers=HEADERS,
json={"applicantId": applicant_id, "csvInJson": False}
)
return r.json()
# Returns: standardized reports, raw data, documents, analytics
AR Invoices with Date Filter
Query sales invoices filtered by date range for revenue analysis.
def get_ar_invoices(applicant_id, from_date=None, to_date=None):
params = {}
if from_date:
params["fromDate"] = from_date
if to_date:
params["toDate"] = to_date
r = requests.post(
f"{BASE_URL}/ar-transactions/invoices",
headers=HEADERS,
json={"applicantId": applicant_id},
params=params
)
return r.json()
# Example: last 12 months of AR invoices
invoices = get_ar_invoices("1000143693", from_date="2025-03-01", to_date="2026-03-01")
AR Invoices with Line-Item Detail
Returns header + line items per invoice in one call. The same payload works for the sibling endpoints /ar-transactions/invoices-items, /ap-transactions/invoices-by-uuid and /ap-transactions/invoices-items.
def get_ar_invoices_detailed(applicant_id, from_date, to_date):
"""Returns AR invoices with header + line items in a single call.
Sibling endpoints (same payload):
/ar-transactions/invoices-items - items only
/ap-transactions/invoices-by-uuid
/ap-transactions/invoices-items
"""
r = requests.post(
f"{BASE_URL}/ar-transactions/invoices-by-uuid",
headers=HEADERS,
json={"applicantId": applicant_id},
params={"fromDate": from_date, "toDate": to_date}
)
return r.json()
SAT Financial Statement
Consolidated financial statement from filed annual SAT returns β useful as a cross-check against ERP-sourced reports.
def get_financial_statement(tax_id):
"""Pulls the consolidated financial statement filed with SAT."""
r = requests.get(
f"{BASE_URL}/GetCompanyFinancialStatement",
headers=HEADERS,
params={"taxId": tax_id}
)
return r.json()
Monitoring & Bulk Validation
Trigger Monitoring Refresh
def trigger_monitoring(applicant_id):
r = requests.post(
f"{BASE_URL}/RequestMonitoring",
headers=HEADERS,
json={"applicantId": applicant_id, "Source": "API"}
)
result = r.json()
print(f"Monitoring triggered: {result['success']}")
return result
Bulk RFC Validation
def validate_rfc_bulk(rfc_list):
file_content = "\n".join(rfc_list).encode("utf-8")
headers_no_ct = {k: v for k, v in HEADERS.items() if k != "Content-Type"}
r = requests.post(
f"{BASE_URL}/ValidateRFCBulk",
headers=headers_no_ct,
files={"file": ("rfcs.txt", file_content, "text/plain")}
)
return r.text # Results per RFC