Migrating from the cysmo® API v2 to v3
Welcome to the migration guide for the cysmo® API. This guide walks you through everything that changed between v2 and v3, so you know exactly what to adjust in your integration.
v3 is not a compatible extension of v2. Endpoints moved, objects were restructured, and some fields changed their type. We recommend reading the Getting Started guide as well as the API Specification alongside this document for a deeper understanding.
What Changed at a Glance
Companies are organised in portfolios. When creating a company, you can now sort them into portfolios. Portfolios carry user permissions and optionally a default radar, and rule sets.
The company object is nested. What used to be one flat object is now split into data (name, address, legal form, …), scanOptions (domains and further scan parameters) and latestRating.
Reports are now ratings. Everything under /v2/reports moved to /v3/ratings, and a company can expose its full rating history.
The term “reports” is now solely used for downloadable representations of a rating, like PDFs.
PUT Updates instead of PATCH We removed all convoluted PATCH logic and replaced them with simple PUT logic: You send the whole object in its new state and we replace it entirely. For commonly updated fields (like the customer/interested status or risk question answers) we introduced sub-paths to make things easier.
Turnover and employee count are absolute numbers. The bucket enums are gone.
PDF generation is asynchronous. You request a report, then poll a download endpoint until the file is ready.
Errors follow RFC 9457. All error responses use the same ProblemDetail object.
Authentication
v3 still uses the OAuth2 client credentials flow, but the token URL changed. While the v2 API served an optional redirect URL, we now recommend sending your request to the login server directly.
v2: https://api.cysmo.de/oauth/token
v3: https://login.cysmo.de/realms/cysmo/protocol/openid-connect/tokenObject Changes
Company
In v2 a company was a single flat object. In v3 the fields are grouped by purpose: data holds general data that has no influence on the technical rating, scanOptions controls what is scanned and how, and latestRating gives you an overview of the most recent results.
/v2/companies/{companyId}
// Response
{
"id": "e1c7...",
"name": "My first cysmo company",
"ratingModel": "SIMPLE",
"domains": ["ppi.de"],
"nets": [],
"legalForm": "legalStructure.STOCK_CORP",
"numberOfEmployees": "numberOfEmployees.FROM5000",
"turnover": "turnover.FROM50",
"industry": "A1",
"city": "Hamburg",
"zipCode": "20459",
"country": "DE",
"status": "status.CUSTOMER",
"insuranceId": "CRM-4711",
"clientId": "2a9b...",
"needsAdditionalInformation": false,
"modificationDate": "2026-08-01T10:00:00Z",
"reports": []
}// Response
{
"id": "e1c7...",
"portfolioId": "2a9b...",
"data": {
"name": "My first cysmo company",
"legalForm": "GENERIC__STOCK_CORPORATION",
"numberOfEmployees": 5000,
"turnover": 72000000,
"currency": "EUR",
"industry": "A1",
"city": "Hamburg",
"zipCode": "20459",
"country": "DE",
"customerStatus": "CUSTOMER",
"externalReference": "CRM-4711"
},
"scanOptions": {
"ratingModel": "SIMPLE",
"infrastructureSize": "NORMAL",
"scanTargetDomains": ["ppi.de"],
"scanTargetNets": [],
"associatedDomains": [],
"associatedNets": [],
"ignoredDomains": [],
"ignoredNets": []
},
"dataComplete": true,
"riskQuestionsComplete": false,
"outdated": { "financialLoss": false },
"modifiedOn": "2026-08-01T10:00:00Z",
"latestRating": { }
}| v2 | v3 | Notes |
|---|---|---|
id |
id |
Unchanged. |
name |
data.name |
Moved. |
legalForm |
data.legalForm |
Completely new enum with international and generic variants. See below. |
numberOfEmployees |
data.numberOfEmployees |
Now an integer. |
turnover |
data.turnover |
Now an integer. |
industry |
data.industry |
Moved. NACE codes are unchanged. |
city |
data.city |
Moved. |
zipCode |
data.zipCode |
Moved. Validated against ^[a-zA-Z0-9\- ]{3,10}$. |
country |
data.country |
Moved. Validated as a two-letter code. |
status |
data.customerStatus |
Renamed. The status. prefix is gone. |
insuranceId |
data.externalReference |
Renamed. |
| — | data.currency |
New, read-only. Always EUR for now. |
domains |
scanOptions.scanTargetDomains |
Renamed. |
nets |
scanOptions.scanTargetNets |
Renamed. |
ratingModel |
scanOptions.ratingModel |
Moved. SIMPLE and ASSOCIATED are unchanged. |
| — | scanOptions.infrastructureSize |
New. NORMAL or LARGE. |
| — | scanOptions.associatedDomains / associatedNets |
New, read-only. |
| — | scanOptions.ignoredDomains / ignoredNets |
New. |
| — | portfolioId |
New. Currently only writable on creation. We are working on a way to move companies. |
modificationDate |
modifiedOn |
Renamed. |
modifiedBy |
modifiedBy |
Unchanged. |
createdBy |
createdBy |
Unchanged. |
needsAdditionalInformation |
dataComplete and riskQuestionsComplete |
Replaced by two fields with inverted meaning. |
reports |
latestRating |
Only the latest rating is embedded. Use GET /companies/{companyId}/ratings for the history. |
| — | outdated |
New, read-only. Flags stale financial loss and rule evaluation results. |
answers |
riskQuestionAnswers |
Renamed. |
Note
numberOfEmployees and turnover no longer use buckets. Provide the actual headcount and the annual turnover in full notation without decimals, so 72 million euro becomes 72000000.
The new legalForm enum differentiates between international (DE__) and generic (GENERIC__) legal forms.
We are planning to expand the international variants in the future.
Rating
The v2 Report object became the v3 Rating.
The term Report now only defines a PDF representation of a Rating. These meanings were mixed in our old terminology.
Besides the renamed fields, the deprecated convenience booleans were removed.
Derive the equivalent from state.
Also the smaller rating overview in company.latestRating and
GET /v3/companies/{companyId}/ratings is now more coherent with the complete rating object returned by GET /v3/ratings/{ratingId}.
/v2/reports/{reportId}
{
"id": "9f31...",
"state": "FINISHED",
"finished": true,
"failed": false,
"running": false,
"timedOut": false,
"overflow": false,
"creationDate": "2026-08-01T10:00:00Z",
"endDate": "2026-08-01T10:01:30Z",
"value": 80,
"ratingTerm": "B",
"progress": 100
}/v3/ratings/{ratingId}
{
"id": "9f31...",
"state": "FINISHED",
"companyId": "e1c7...",
"cause": "RE_RATING",
"createdOn": "2026-08-01T10:00:00Z",
"finishedOn": "2026-08-01T10:01:30Z",
"value": 0.8,
"grade": "B",
"progress": 1
}| v2 | v3 | Notes |
|---|---|---|
id |
id |
Unchanged. |
state |
state |
Three values were renamed, see below. |
finished, failed, running, timedOut, overflow |
— | Removed. Evaluate state instead. |
creationDate |
createdOn |
Renamed. |
endDate |
finishedOn |
Renamed. |
ratingTerm |
grade |
Renamed. Values A to F are unchanged. |
progress |
progress |
Now on a scale from 0 to 1. |
valueTech |
value |
Removed extra values for Business and Sales mode. Now on a scale from 0 to 1. |
companyId |
companyId |
Unchanged. |
partialRatings |
partialRatings |
Unchanged in purpose, some renamings. See spec for details. |
cause |
cause |
Unchanged. |
underwritingClassification |
ruleEvaluations.underwriting |
Moved, to have the option of multiple rule sets in the future. |
answers |
riskQuestionAnswers |
Renamed. |
| — | scanOptions |
New. The scan options the rating was created with. |
These rating states were renamed:
| v2 | v3 |
|---|---|
SCORE_TIMEOUT |
FINISHED_WITH_SCORE_TIMEOUT |
ERROR |
FAILED |
OVERFLOW |
INFRASTRUCTURE_TOO_LARGE |
All other states keep their names. Ratings in the states FINISHED and FINISHED_WITH_SCORE_TIMEOUT deliver data. The terminal states are FAILED, FINISHED, FINISHED_WITH_SCORE_TIMEOUT, INFRASTRUCTURE_TOO_LARGE, TIMEOUT, NOT_IN_RATING_ENGINE and INTERNAL_ERROR.
Tip
If a rating ends in INFRASTRUCTURE_TOO_LARGE, mark the company’s infrastructureSize as LARGE. This triggers an automatic re-rating optimized for larger infrastructures. A simple re-rating will not fix the issue.
Please note that LARGE ratings can take longer and might have a longer queue time.
Radar Configuration
The radar object got cleaned up, removing the duplicate nextRating, nextRatingDate and nextRatingTime fields and the new field names should bring more clarity.
Also the timezone now defaults to the more sensible international option UTC instead of Europe/Berlin.
You can of course still set your own.
/v2/companies/{companyId}/radar
// Response
{
"id": "5b90...",
"nextRatingDate": "2026-09-24",
"nextRatingTime": "18:00",
"nextRatingZoneId": "Europe/Berlin",
"endDate": "2026-12-31T00:00:00Z",
"interval": 1,
"intervalUnit": "MONTHS",
"lastModified": "2026-08-01T10:00:00Z"
}{
"nextExecutionDate": "2026-09-24",
"executionTime": "18:00",
"timezone": "Europe/Berlin",
"endDate": "2026-12-31",
"interval": 1,
"intervalUnit": "MONTHS",
"modifiedOn": "2026-08-01T10:00:00Z"
}| v2 | v3 | Notes |
|---|---|---|
id |
— | Removed. |
nextRating |
— | Removed. It was already deprecated and readOnly in v2. |
nextRatingDate |
nextExecutionDate |
Renamed. Required. |
nextRatingTime |
executionTime |
Renamed. Still defaults to 18:00. |
nextRatingZoneId |
timezone |
Renamed. The default changed from Europe/Berlin to UTC. |
endDate |
endDate |
Now a plain date instead of a date-time. Uses end of day based on the provided timezone. |
interval |
interval |
Required, with a minimum frequency of one week. |
intervalUnit |
intervalUnit |
Required. Values are unchanged. |
lastModified |
modifiedOn |
Renamed. |
modifiedBy |
modifiedBy |
Unchanged. |
v2 restricted MONTHS to the values 3 and 6 and YEARS to 1. v3 provides more freedom and allows any interval > 1 week.
Set timezone explicitly so your ratings are scheduled during your off-hours.
Underwriting Result
To accommodate more than one possible rule set in the future, the Underwriting Results have moved from GET /v2/underwriting/{ratingId} to
GET /v3/ratings/{ratingId}/rule-evaluations/underwriting?language=en
and the object got cleaned up quite a bit.
/v2/underwriting/{ratingId}
{
"classification": "RED",
"rules": [
{
"classification": "RED",
"rule": "",
"name": "OpenPortsNoBadFindings",
"score": "attack_resilience.open_ports",
"triggered": true,
"errors": [],
"companyDataRequiredExpand": false,
"riskQuestionAnswersRequired": false,
"labels": {
"en": {
"name": "Critical finding in \"Open Ports\"",
"description": "A critical finding cannot occur in the score \"Open Ports\".",
"question": "Can the ports concerned be made inaccessible from the outside?"
},
"it": {
// ...
}
}
}
]
}{
"overall": "RED",
"rules": [
{
"result": "GREEN",
"key": "OpenPortsCriticalOrWorse",
"legacyName": "OpenPortsNoBadFindings",
"score": "attack_resilience.open_ports",
"labels": {
"description": "A critical finding cannot occur in the score \"Open Ports\".",
"question": "Can the ports concerned be made inaccessible from the outside?"
}
}
]
}| v2 | v3 | Notes |
|---|---|---|
classification |
overall |
Renamed. The values GREEN, RED, UNKNOWN and ERROR are unchanged. |
rules.[].classification |
rules.[].result |
Was always RED in v2. Now is the actual indicator in v3. |
rules.[].triggered |
— | Removed. Check result == 'RED' instead. |
rules.[].name |
rules.[].key |
Renamed. Now a fixed technical key instead of a customizable name. |
rules.[].name |
rules.[].legacyName |
Old value of the v2 name. For your reference during migration. Will be removed when v2 goes EOL. |
rules.[].score |
rules.[].score |
Unchanged. |
rules.[].labels |
rules.[].labels |
Removed the translatable name label, CSV Exports will use the static key in the future instead.Only returns the labels for the language requested in the query parameter |
Tip
Querying any ratings underwriting result returns all rules of that company’s portfolio.
Use that list together with the field legacyName to migrate your rules to the new key identifier.
Errors
Errors in API v3 are RFC 9457 compliant ProblemDetail objects.
You can match on the type name (after the #) to catch and handle different error cases gracefully in your application.
title and detail are meant for human reading, rather than automatic parsing.
If you need to contact cysmo® support in regards to an error message, make sure to include the correlationId, so we can find your case in our logs.
See Possible Error Responses for more details.
Note
Although most errors are already migrated to the new scheme, some errors are still non-compliant. This mostly concerns error messages from our firewall or load balancers rather than application errors.
Old cysmo Error Object
{
"error": "Internal Server Error",
"errorDescription": "An unexpected error occurred."
}RFC 9457 Problem Detail
{
"type": "https://developer.cysmo.de/api/v3/errors#InternalServerError",
"status": 500,
"title": "An unexpected error occurred.",
"instance": "/v3/companies/e1c7...",
"correlationId": "c927af..."
}Endpoint Changes
Companies
| v2 | v3 |
|---|---|
POST /v2/companies |
POST /v3/companies |
GET /v2/companies |
GET /v3/companies or POST /v3/companies/get-filtered |
GET /v2/companies/{id} |
GET /v3/companies/{companyId} |
DELETE /v2/companies/{id} |
DELETE /v3/companies/{companyId} |
PUT /v2/companies/{id} |
see below |
PATCH /v2/companies/{id} |
see below |
| — | POST /v3/companies/count-filtered |
| — | GET /v3/companies/{companyId}/ratings |
| — | POST /v3/companies/{companyId}/ratings |
When creating a company, you need to use the new company object
. The field scanOptions with at least one element in scanTargetDomains or scanTargetNets is required.
The query parameters changed too: acceptSubDomain is now acceptSubdomains, acceptNotReachable no longer exists, and lowPrio=true becomes scanOptions.overridePriority: "LOW".
{
"portfolioId": "2a9b0ad6-e5de-4239-a282-527c92c7c0f1",
"data": {
"name": "My first cysmo company",
"legalForm": "GENERIC__STOCK_CORPORATION",
"industry": "A1",
"numberOfEmployees": 5000,
"turnover": 72000000,
"city": "Hamburg",
"zipCode": "20459",
"country": "DE",
"customerStatus": "CUSTOMER",
"externalReference": "CRM-4711"
},
"scanOptions": {
"scanTargetDomains": ["ppi.de"],
"overridePriority": "LOW"
}
}'Company Updates
The single update endpoint of v2 was split by concern.
Each of these returns 204 No Content, so you no longer get the updated company back.
Since we are using PUT logic, you already have the updated state at hand, with the following exceptions:
modifiedByandmodifiedOnare updated server side- updating scan options triggers a new rating, updating the
latestRatingserver side
If you rely on those fields, you need to fetch the updated company via GET.
| Concern | v3 endpoint |
|---|---|
| General data | PUT /v3/companies/{companyId}/data |
| Scan options | PUT /v3/companies/{companyId}/scan-options |
| Infrastructure size | PUT /v3/companies/{companyId}/scan-options/infrastructure-size |
| Customer status | PUT /v3/companies/{companyId}/data/customer-status |
| Risk question answers | PUT /v3/companies/{companyId}/risk-question-answers |
| Sales story | PUT /v3/companies/{companyId}/sales-story |
Ratings and Reports
| v2 | v3 |
|---|---|
GET /v2/reports/{ratingId} |
GET /v3/ratings/{ratingId} |
GET /v2/reports/{ratingId}/pdf |
POST /v3/ratings/{ratingId}/reports/pdf + see below |
GET /v2/underwriting/{ratingId} |
GET /v3/ratings/{ratingId}/rule-evaluations/underwriting |
GET /v2/reports/{id}/benchmark |
not yet published |
The technical rating is now fully independent from the view mode, thus the query parameter ?dataMode becomes obsolete for fetching a rating.
All sales or underwriting related data is either fetched additionally or included in the rating all the time.
The view mode is only needed for generating PDF reports, where it moved from a query parameter to the request body.
Note
The view mode UNDERWRITING was renamed to RULES.
In the future we plan to add a rule set selector in that view mode, but by default the RULES view mode will keep using your underwriting rule set.
Radar
| v2 | v3 |
|---|---|
GET /v2/companies/{companyId}/radar |
GET /v3/companies/{companyId}/radar |
POST /v2/companies/{companyId}/radar |
PUT /v3/companies/{companyId}/radar |
| — | DELETE /v3/companies/{companyId}/radar |
| — | PUT /v3/companies/radar/set-filtered |
| — | POST /v3/companies/radar/delete-filtered |
| — | GET, PUT, DELETE /v3/portfolios/{portfolioId}/default-radar |
A portfolios default radar config is applied for all newly created companies in that portfolio.
Translations
The v3 translations endpoint supports the optional ratingVersion query parameter, which filters the messages and strips the number prefix from the labels for you.
/v2/values/translations?lang=en
// Response
{
"12.attack_resilience.vulns.critical.potential_risk": "Attackers can and have very likely already taken over the system.",
"12.mailAvailability.high": "High",
"7.mailAvailability.high": "High",
"ratingGrade": "Rating grade",
"tables.name.malicious_as": "AS Reputation",
// ...
}// Response
{
"attack_resilience.vulns.critical.potential_risk": "Attackers can and have very likely already taken over the system.",
"mailAvailability.high": "High",
"ratingGrade": "Rating grade",
"tables.name.malicious_as": "AS Reputation",
// ...
}Status Codes
PUT and DELETE operations now return status 204 No Content with no response body.
| Operation | v2 | v3 |
|---|---|---|
| Update a company | 200 with body |
204 |
| Delete a company | 200 |
204 |
| Set or delete a radar | 200 |
204 |
| Request a PDF report | 200 with the file |
202 Accepted with a status monitoring link |
| Request an export | — | 202 Accepted with a status monitoring link |
Filtering and Pagination
You still have the option to use query parameters (GET /v3/companies?country=DE&country=IT&country=FR&pageSize=100&page=2) but now you also have the option to send your query as a JSON object:
{
"country": [
"DE",
"IT",
"FR"
],
"pageSize": 100,
"page": 2
}This is especially useful for long filter queries, which might exceed URL/Header length limits.
Like in v2, within one property values are OR-joined. Across properties, they are AND-joined.
Some filter parameters were renamed for a more consistent experience:
| v2 | v3 | Changed |
|---|---|---|
name |
name |
|
domain |
domain |
|
country |
country |
|
zipcode |
zipCode |
* |
city |
city |
|
legalform |
legalForm |
* |
industry |
industry |
|
sectorLetter |
industry (now supports both ‘A’ and ‘A1’) |
* |
numberOfEmployees |
numberOfEmployeesMin and numberOfEmployeesMax |
* |
turnover |
turnoverMin and turnoverMax |
* |
insuranceId |
externalReference |
* |
status |
customerStatus |
* |
company |
id |
* |
user |
createdBy |
|
freeText |
freeText, now an array |
* |
dateMin, dateMax |
ratingCreatedOnMin, ratingCreatedOnMax |
* |
valueTechMin, valueTechMax |
ratingValueMin, ratingValueMax |
* |
valueUnderwriting |
underwritingEvaluation |
* |
technicalTrendStatus |
ratingValueTrend |
* |
sort |
sortBy |
* |
sortOrder |
sortOrder |
|
page |
page |
|
pageSize |
pageSize |
|
| — | portfolio |
* |
client |
— | * |
businessTrendStatus |
— | * |
valueBusinessMin, valueBusinessMax |
— | * |
| — | ratingState |
* |
sortBy now has the following options: LATEST_RATING_DATE (default), TREND, COMPANY_NAME, VALUE, FINDINGS and UNDERWRITING_EVALUATION.
Note
pageSize is capped at 100 in v3, where v2 allowed up to 1000. The default also dropped from 100 to 15, so adapt your pageSize if needed.
Rating Priorities
The lowPrio query parameter available in v2’s POST /v2/companies became a Priority enum with the values NORMAL and LOW and is now used in multiple locations.
The defaults differ per operation. Creating a company and update-triggered re-ratings default to NORMAL, so you see the results of your interaction more quickly.
Regular re-ratings default to LOW.
You can use the overridePriority or priority fields respectively to differ from the default behavior.
The priority is not persisted on the company; it will always fall back to its default if not explicitly given in the request.
Important
Priority NORMAL is rate limited (currently to a maximum of 15 ratings at the same time).
Exceeding the rate limit returns 429 with error TooManyHighPriorityRatings.
Use the priority LOW for batch operations.
Reports Are Asynchronous
In v2 you fetched a PDF directly and received the file in the response body. In v3 you request the report, then poll for it.
First, request the report:
The response contains a link to a status endpoint. Poll it until the download link appears:
// Response
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"type": "PDF_REPORT",
"progress": 0,
"expires": "2019-08-24T14:15:22Z",
"ratingId": "e2685a8c-cb0d-4ffd-85d1-e4f8966e7aa9",
"viewMode": "TECH",
"link": "https://api.cysmo.de/v3/downloads/file/T3LwNczqh430YHy2wrbEMr8UdSfz8MpIMXBqxoTb8T1fl9XfCj5dZ01NhYnUUr/Cysmo_Report_Sample%20Company_technical.pdf"
}progress runs from 0 to 1. Once it is complete, link holds the download URL. This usually takes a few seconds and rarely more than a minute.
If error is set, the request has failed for good and you need to request the content again, ideally with different parameters.
The reducedTo parameter moved from the query string into the request body. zoneOffset has no v3 equivalent.
New in v3
Beyond the changes above, v3 adds capabilities that had no v2 counterpart:
-
Portfolios: Full management through
GETandPOST /v3/portfoliosplusGET,PUTandDELETE /v3/portfolios/{portfolioId}. Your “active portfolio” is the default used for company creation and is available throughGETandPUT /v3/users/self/active-portfolio. But we recommend setting the portfolio explicitly in the request body on company creation, to work statelessly. -
Exports:
POST /v3/exportsgenerates aRATING_LISTorRATING_TABLESexport for a filtered set of companies, optionally including historic ratings. A user can only have one running export per type. Download of the generated export is handled like with PDFs. -
Downloads: The new
GET /v3/downloadsandGET /v3/downloads/{downloadId}serve a central place for every asynchronously generated file. The created file download links (/v3/downloads/file/…) hold a secure token, so they can be used without a cysmo session. This enables you to trigger content generation on your application server while handling content download on the users device. -
Sales stories:
GET,PUTandDELETE /v3/companies/{companyId}/sales-story, used to set the pre-selected illustrative story for PDF reports in the sales view mode. -
Infrastructure size:
PUT /v3/companies/{companyId}/scan-options/infrastructure-sizelets you switch a company toLARGEif your previous rating failed with stateINFRASTRUCTURE_TOO_LARGE. An immediate re-rating will be triggered automatically.
Benchmarks
The benchmarks object has been cleaned up and the paths changed a bit, but the purpose stays the same:
You receive a benchmark value for every score, partial rating and the overall rating and you can filter by different scopes (companies of similar industry or turnover).
/v2/reports/{reportId}/benchmark?dataMode=TECH&benchmarkOption={scope}
// With {scope} being any of "ALL", "BRANCH" or "TURNOVER" (case-sensitive)
// Response
{
"version": 12,
"value": 0.8123,
"partialRatings": [
{
"nameKey": "attack_resilience",
"classifications": {
"CRITICAL": 0, // All always 0
"CATASTROPHIC": 0,
"NEUTRAL": 0,
"WARNING": 0,
"GOOD": 0
},
"timedOut": false, // Deprecated. Always false.
"high": null, // Deprecated. Always null.
"low": null,
"value": 0.9,
"scores": [
{
"nameKey": "attack_resilience.open_ports",
"value": 0.753,
// same extra fields as in partial rating
},
// ...
]
},
// ...
]
}// With {scope} being any of "global", "industry" or "turnover" (case-insensitive)
// Response
{
"version": 12,
"value": 0.8123,
"partialRatings": [
{
"nameKey": "attack_resilience",
"value": 0.9,
"scores": [
{
"nameKey": "attack_resilience.open_ports",
"value": 0.753
},
// ...
]
},
// ...
]
}The error responses were updated as well: If no benchmark information is available you receive one of two 404 responses, which you can distinguish by their types:
BenchmarkNotAvailable: You did nothing wrong, cysmo® simply doesn’t have enough comparable data for this rating.ResourceNotFound: Your provided Rating ID doesn’t exist or the rating’s company doesn’t have the necessary data set for the benchmark scope you requested (i.e. industry or turnover is missing).
API v2 End-of-Life Timeline
We are excited to introduce API v3 as the next-generation interface for customer integrations.
API v2 will not receive new features during this period, but existing functionality will remain stable and supported until retirement. We understand that business-critical integrations require careful planning, and we are committed to providing customers with a stable transition window. API v2 will therefore remain stable and supported for one full year following the publication of this migration guide. Prior to retirement, we will notify customers who have not yet migrated with reminder emails and relevant migration information.
Important
The legacy cysmo® API v2 will remain available until September 30, 2027.