4.3.1 Vermietungsdaten vom Produkt zum Partner

Dies ist der erste Schritt des Prozesses für Vermietungsdaten, zuerst muss die Datei/Dateien von der CloudApi heruntergeladen werden.

images/download/attachments/268154498/Vermietungsdaten_vom_Produkt_zum_Partner-version-1-modificationdate-1620653767107-api-v2.png

Details über die einzelnen Endpunkte können über das Developer Portal in der Swagger/OpenAPI Dokumentation nachgelesen werden.

Für alle folgenden Prozesse wird vorausgesetzt, dass eine Partner-Lizenz zur Übertragung der jeweiligen Daten existiert und diese bereits erfolgreich aktiviert wurde. (Siehe 5. Sicherheitsmechanismen unter Punkt a. Lizenzaktivierung)

1. Erstellung des Authentifizierungstokens

Um Daten aus der Cloud API empfangen zu können, ist es notwendig, zuvor ein Authentifizierungstoken zu übertragen, dass über den Endpunkt TokenCreate angefragt werden kann. Dafür müssen der grant_type (= „client_credentials“), requesttype (der zu übertragende Requesttype) und der scope (= LicenseIndicatorHash) im Body in URL-Encoded Form mit Content-Type: application/x-www-form-urlencoded übertragen werden.

Das Token ist grundsätzlich 30 Minuten gültig (sollte also ggf. für mehrere Requests wiederverwendet werden) und bezieht sich auf einen Requesttype (hier VermietungsdatenRequest) und dem jeweiligen Kunden mit dem man Daten austauschen möchte.

Der Auth-Token wird dann für weitere Requests im Header „Authentication: Bearer <token>“ genutzt.


POST TokenCreate

HTTP request
POST /CloudApi/V1/api//oauth2/token HTTP/1.1
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Content-Type: application/x-www-form-urlencoded
Accept: */*
Cache-Control: no-cache
Host: api.realestatehub.haufe.io
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 116
 
grant_type=client_credentials&scope=q92qdL0PcKxU2s2xFW0y2bqI-TZx0cupbnAmqgZdfmY1&requesttype=VermietungsdatenRequest
HTTP response
HTTP/1.1 201 Created
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 190
Content-Type: application/json; charset=utf-8
Expires: -1
X-Powered-By: ASP.NET
Date: Wed, 18 Nov 2020 07:41:42 GMT
 
{
"access_token": "99b343dd-c29c-4da5-9281-3412b0060f08",
"token_type": "Bearer",
"expires_in": 1800,
"scope": "q92qdL0PcKxU2s2xFW0y2bqI-TZx0cupbnAmqgZdfmY1",
"requesttype": "VermietungsdatenRequest"
}

2. Daten von einer Gegenstelle empfangen


Für den Empfang eines Datenpakets ist der Endpunkt FileJobsGetItems vorgesehen. Die Response kann hierbei mehrere Jobs auf einmal beinhalten und dementsprechend groß sein . Für den Aufruf des Endpunktes wird ein Authentifizierungstoken im Header benötigt.

GET FileJobsGetItems

HTTP request
GET /CloudApi/V1/api/filejobs HTTP/1.1
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Authorization: Bearer 68ead0ee-0f34-4619-af1f-e4fdb8fdfdee
Accept: */*
Cache-Control: no-cache
Host: api.realestatehub.haufe.io
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP response
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 1301
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Expires: -1
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Date: Tue, 09 Mar 2021 11:11:27 GMT
 
{
"total_count": 1,
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs"
}
},
"_embedded": {
"fileJobs": [
{
"licenseownerid": "{ID}",
"sequencenumber": "1",
"licensecounterpartid": "{ID}",
"deleteflag": false,
"state": {
"FileJobState": 1,
"FileJobStateAsString": "UploadCompleted",
"StateDateTime": "2021-03-09T11:10:38.0725218+00:00",
"PreviousFileJobState": {
"FileJobState": 0,
"FileJobStateAsString": "Created",
"StateDateTime": "2021-03-09T11:08:31.9481959+00:00",
"PreviousFileJobState": null
}
},
"data": " ",
"hasheddata": null,
"response": null,
"responsecode": null,
"IsResponseOk": false,
"LicenseIndicatorHashSender": "{LicenseIndicatorHash}",
"TemporarySharedAccessSignatureUri": "https://prodcloudapifilejobs.blob.core.windows.net/2417147c-f867-40fb-8526-9e88ac6ec50e?sv=2017-04-17&sr=c&sig=b2gwhClrrrn37iUJjQXXa9GfokQAUv9L3kySM%2FwiXDc%3D&se=2021-03-09T11%3A41%3A27Z&sp=rl",
"BlobContainerReference": "2417147c-f867-40fb-8526-9e88ac6ec50e",
"id": "{JobId}",
"requesttype": "VermietungsdatenRequest",
"_links": {
"self": {
"href": null
},
"confirm": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs/confirmations"
}
}
}
]
}
}


3. Blobs auflisten


"Erklärungs-Text" Auflistung von Blobs in einem gegebenen container. Benötigt zusätzlich die query parameter restype=container und comp=list.

GET List Blobs


HTTP request
GET {TemporarySharedAccessSignatureUri aus FileJobGetIteams}&restype=container&comp=list HTTP/1.1
Accept: */*
Cache-Control: no-cache
Host: prodcloudapifilejobs.blob.core.windows.net
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP response
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/xml
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 2b56ad48-501e-0000-63db-144157000000
x-ms-version: 2017-04-17
Date: Tue, 09 Mar 2021 12:00:04 GMT
 
<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults ServiceEndpoint="https://prodcloudapifilejobs.blob.core.windows.net/" ContainerName="2417147c-f867-40fb-8526-9e88ac6ec50e">
<Blobs>
<Blob>
<Name>TestDatei</Name>
<Properties>
<Last-Modified>Tue, 09 Mar 2021 12:00:04 GMT</Last-Modified>
<Etag>0x8D8E2F8CCC7753E</Etag>
<Content-Length>46</Content-Length>
<Content-Type>text/plain</Content-Type>
<Content-Encoding />
<Content-Language />
<Content-MD5>w6akDuFOQCw7y1baUhzGyg==</Content-MD5>
<Cache-Control>no-cache</Cache-Control>
<Content-Disposition />
<BlobType>BlockBlob</BlobType>
<AccessTier>Hot</AccessTier>
<AccessTierInferred>true</AccessTierInferred>
<LeaseStatus>unlocked</LeaseStatus>
<LeaseState>available</LeaseState>
<ServerEncrypted>true</ServerEncrypted>
</Properties>
</Blob>
</Blobs>
<NextMarker />
</EnumerationResults>

4. Blobs herunterladen


SharedAccessSignatureUri aus FileJobsGetItems als Request-Url einfügen.

Nach der GUID (Container-Bezeichnung) und vor dem "?" muss noch die Benennung der heruntergeladenen Datei erfolgen.

Dies geschieht mit einem "/" nach der GUID und die gewünschte Bezeichung der Datei oder aus der Auflistung von Blobs die gewünschte Datei auslesen und vor dem "?" einfügen.

GET Blob Download


HTTP request
GET testcloudapifilejobs.blob.core.windows.net/1138eb61-8f00-4e35-bc13-b18e26276a96/Testdatei.png?sv=2017-04-17&sr=c&sig=9C88RICRluDv8ryjdvXfBj3MCJuW7NRoCPxma0JUa14%3D&se=2021-05-03T10%3A27%3A44Z&sp=cw HTTP/1.1
{TemporarySharedAccessSignatureUri aus FileJobGetIteams mit resource identifier /dateiname aus ListBlobs}
Accept: */*
Cache-Control: no-cache
Host: prodcloudapifilejobs.blob.core.windows.net
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP response
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 46
Content-Type: text/plain
Content-MD5: w6akDuFOQCw7y1baUhzGyg==
Last-Modified: Tue, 09 Mar 2021 12:42:28 GMT
Accept-Ranges: bytes
ETag: "0x8D8E2F8CCC7753E"
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 5886c1e7-301e-0006-29e2-1472e8000000
x-ms-version: 2017-04-17
x-ms-lease-status: unlocked
x-ms-lease-state: available
x-ms-blob-type: BlockBlob
x-ms-server-encrypted: true
Date: Tue, 09 Mar 2021 12:46:53 GMT
 
-> Testdatei.png "Hier ist das Test-Dokument(PDF,jpeg,txt.....)."

5. Datenempfang bestätigen

Bevor die abgeholten Daten verarbeitet werden, muss der Datenempfang in der Cloud API bestätigt werden, dies geschieht mit dem Endpunkt FileJobsConfirmationsCreate. Das soll verhindern, dass ggf. zwei Instanzen derselben Gegenstelle die Daten gleichzeitig bearbeiten. Außerdem wird ein Authentifizierungstoken im Header benötigt.

POST FileJobsConfirmationsCreate


HTTP request
POST /CloudApi/V1/api/filejobs/confirmations HTTP/1.1
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Authorization: Bearer ca4d3bb5-d6b1-4067-a51e-01a626536c46
Content-Type: application/json
Accept: */*
Cache-Control: no-cache
Host: api.realestatehub.haufe.io
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 46
 
[
"{JobId-GUID}",
"{JobId-GUID}",
"{JobId-GUID}",
. ,
. ,
. ,
"{JobId-GUID}"
]


HTTP response
HTTP/1.1 201 Created
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 383
Content-Type: application/json; charset=utf-8
Expires: -1
X-Powered-By: ASP.NET
Date: Tue, 09 Mar 2021 12:10:47 GMT
 
{
"responseCollection": [
{
"id": "{JobId}",
"confirmationId": "{ConfirmationId}",
"remark": "Job {JobId} confirmed."
}
],
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs/confirmations"
},
"respond": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/filejobs/responses"
}
}
}

6. Beantwortung von Requests

Nach der Verarbeitung von Daten aus der Cloud API muss der Empfänger den Request beantworten, sodass der Absender die Information erhält, dass die Daten verarbeitet wurden. Dies geschieht über den Endpunkt FileJobsResponsesCreate. Dazu muss eine JobId mitgegeben werden, welches eine GUID ist. Außerdem wird ein Authentifizierungstoken im Header benötigt.

POST FileJobsResponsesCreate


HTTP request
POST /CloudApi/V1/api/filejobs/{JobId-GUID}/responses HTTP/1.1
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Content-Type: application/json
Authorization: Bearer ca4d3bb5-d6b1-4067-a51e-01a626536c46
Accept: */*
Cache-Control: no-cache
Host: api.realestatehub.haufe.io
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 250
 
{
"Response":"Download der Datei war erfolgreich",
"Responsecode":"TestCode-0001",
"ConfirmationToken":
{
"id": "{JobId-GUID}",
"confirmationId": "{ConfirmationId-GUID}"
},
"IsResponseOk" : "True"
}


HTTP response
HTTP/1.1 201 Created
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 747
Content-Type: application/json; charset=utf-8
Expires: -1
X-Powered-By: ASP.NET
Date: Tue, 09 Mar 2021 12:23:57 GMT
 
{
"id": "{JobId-GUID}",
"requesttype": "VermietungsdatenRequest",
"state": {
"FileJobState": 3,
"FileJobStateAsString": "Processed",
"StateDateTime": "2021-03-09T12:23:58.2257078+00:00",
"PreviousFileJobState": {
"FileJobState": 2,
"FileJobStateAsString": "Confirmed",
"StateDateTime": "2021-03-09T12:10:47.8586793+00:00",
"PreviousFileJobState": {
"FileJobState": 1,
"FileJobStateAsString": "UploadCompleted",
"StateDateTime": "2021-03-09T11:10:38.0725218+00:00",
"PreviousFileJobState": {
"FileJobState": 0,
"FileJobStateAsString": "Created",
"StateDateTime": "2021-03-09T11:08:31.9481959+00:00",
"PreviousFileJobState": null
}
}
}
},
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/responses"
}
}
}



Danach kommt der zweite Schritt des Prozesses für Vermietungsdaten, hier müssen die Vermietungsdaten selber abgeholt werden.

images/download/attachments/268154498/Vermietungsdaten_vom_Produkt_zum_Partner_%28EntityJob%29-version-1-modificationdate-1620654223245-api-v2.png

7. Erstellung des Authentifizierungstokens

siehe Punkt 1.

8. Daten von einer Gegenstelle empfangen


Für den Empfang eines Datenpakets ist der Endpunkt JobsGetItems vorgesehen.

Die Response kann hierbei mehrere Jobs auf einmal beinhalten und dementsprechend groß sein.

Für den Aufruf des Endpunktes wird ein Authentifizierungstoken im Header benötigt.

GET JobsGetItems

HTTP request
GET /CloudApi/V1/api/jobs HTTP/1.1
Host: api.realestatehub.haufe.io
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Authorization: Bearer 8a4267cb-d76e-4fd8-971a-9a1b2ebe448e
Accept: */*
Cache-Control: no-cache
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
HTTP response
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 20827
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Expires: -1
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Date: Fri, 30 Oct 2020 09:24:42 GMT
 
{
"total_count": 1,
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs"
}
},
"_embedded": {
"jobs": [
{
"sequencenumber": "1",
"salt": "54zO/2bCBRXCi84yKe4WeYm3rbYp7Gb/3JjZvaXyxXM=",
"licenseownerid": "37",
"licensecounterpartid": "39",
"deleteflag": false,
"state": {
"JobState": 0,
"JobStateAsString": "New",
"StateDateTime": "2020-10-30T09:25:14.82179+00:00",
"PreviousJobState": {
"JobState": -1,
"JobStateAsString": "Queued",
"StateDateTime": "2020-10-30T09:24:42.4295984+00:00",
"PreviousJobState": null
}
},
"responseSalt": null,
"data": "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",
"hasheddata": "C5EEDDADA83CABADC88F2E54258418A068B1600525499B637B848CA769CF4E69DG312",
"response": null,
"responsecode": null,
"IsResponseOk": true,
"Entities": null,
"EntitiesCount": {
"MandantEntity": 1,
"UnternehmenEntity": 1,
"WirtschaftseinheitEntity": 1,
"GebaeudeEntity": 1,
"HausEntity": 1,
"NutzungseinheitEntity": 1,
"VermietungEntity": 1,
"AusstattungsgruppeEntity": 1,
"AusstattungselementEntity": 1,
"RaumEntity": 1,
"SachbearbeiterEntity": 1,
"AdresseEntity": 1,
"FotoEntity": 1,
"EnergieausweisEntity": 1
},
"LicenseIndicatorHashSender": "{LicenseIndicatorHash}",
"LicenseIndicatorHashReceiver": null,
"AttachmentReference": "",
"id": "{JobId-GUID}",
"requesttype": "VermietungsdatenRequest",
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/responses"
},
"confirm": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/confirmations"
}
}
}
]
}
}

9. Datenempfang bestätigen

Bevor die abgeholten Daten verarbeitet werden, muss der Datenempfang in der Cloud API bestätigt werden, dies geschieht mit dem Endpunkt ConfirmationCreate.

Das soll verhindern, dass ggf. zwei Instanzen derselben Gegenstelle die Daten gleichzeitig bearbeiten.

Dazu muss eine JobId in der URL mitgegeben werden, welches eine GUID ist. Außerdem wird ein Authentifizierungstoken im Header benötigt.

POST ConfirmationCreate

HTTP request
POST /CloudApi/V1/api/jobs/{JobId}/confirmations HTTP/1.1
Host: api.realestatehub.haufe.io
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Authorization: Bearer 8a4267cb-d76e-4fd8-971a-9a1b2ebe448e
Accept: */*
Cache-Control: no-cache
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 0
HTTP response
HTTP/1.1 201 Created
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 379
Content-Type: application/json; charset=utf-8
Expires: -1
X-Powered-By: ASP.NET
Date: Fri, 30 Oct 2020 10:37:08 GMT
 
{
"id": "{JobId-GUID}",
"confirmationId": "{ConfirmationId-GUID}",
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId}/confirmations"
},
"respond": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId}/responses"
}
}
}

Das Bestätigen mehrerer Jobs kann mit dem Endpunkt ConfirmationsCreate durchgeführt werden. Hier entfällt außerdem die einzelne JobId in der URL:

POST ConfirmationsCreate


HTTP request
POST /CloudApi/V1/api//jobs/confirmations HTTP/1.1
Host: api.realestatehub.haufe.io
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Content-Type: application/json
Authorization: Bearer e98db7a5-7b78-4c25-9140-9920946894af
Accept: */*
Cache-Control: no-cache
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 46
 
[
"{JobId-GUID}",
"{JobId-GUID}",
"{JobId-GUID}",
"{JobId-GUID}",
"{JobId-GUID}",
"{JobId-GUID}",
. ,
. ,
. ,
. ,
"{JobId-GUID}"
]


HTTP response
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 360
Content-Type: application/json; charset=utf-8
Content-Encoding: gzip
Expires: -1
Vary: Accept-Encoding
X-Powered-By: ASP.NET
Date: Fri, 30 Oct 2020 12:39:48 GMT
 
 
{
"responseCollection": [
{
"id": "{JobID-GUID}",
"confirmationId": "{ConfirmationId-GUID}",
"remark": "Job {JobID-GUID} confirmed."
},
{
"id": "{JobID-GUID}",
"confirmationId": "{ConfirmationId-GUID}",
"remark": "Job {JobID-GUID} confirmed."
},
{
"id": "{JobID-GUID}",
"confirmationId": "{ConfirmationId-GUID}",
"remark": "Job {JobID-GUID} confirmed."
},
{ .
},
{ .
},
{ .
},
{
"id": "{JobID-GUID}",
"confirmationId": "{ConfirmationId-GUID}",
"remark": "Job {JobID-GUID} confirmed."
}
],
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/confirmations"
},
"respond": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/responses"
}
}
}

10. Beantwortung von Requests


Nach der Verarbeitung von Daten aus der Cloud API muss der Empfänger den Request beantworten, sodass der Absender die Information erhält, dass die Daten verarbeitet wurden.

Dies geschieht über den Endpunkt ResponsesCreate. Dazu muss eine JobId mitgegeben werden, welches eine GUID ist.

Außerdem wird ein Authentifizierungstoken im Header benötigt.


POST ResponsesCreate


HTTP request
POST /CloudApi/V1/api/jobs/{JobId}/responses HTTP/1.1
Host: api.realestatehub.haufe.io
Content-Type: application/json
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
Content-Type: application/json
Authorization: Bearer d94fb9c4-8cb5-4e8c-bdd6-51fba2ceed44
Accept: */*
Cache-Control: no-cache
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 342
 
{
"Response":"{Verschlüsselte Antwort}",
"Responsecode":"TestCode-0001",
"IsResponseOk": true,
"ConfirmationToken":
{
"id": "{JobId-GUID}",
"confirmationId": "{ConfirmationId-GUID, welcher man vom Endpunkt ConfirmationCreate bekommt}"
},
"ResponseSalt":"ChangeMeToTheRealSalt"
}


HTTP response
HTTP/1.1 201 Created
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 698
Content-Type: application/json; charset=utf-8
Expires: -1
X-Powered-By: ASP.NET
Date: Fri, 30 Oct 2020 10:11:12 GMT
 
{
"id": "{JobId-GUID}",
"requesttype": "VermietungsdatenRequest",
"state": {
"JobState": 3,
"JobStateAsString": "Processed",
"StateDateTime": "2020-10-30T10:11:12.3078021+00:00",
"PreviousJobState": {
"JobState": 2,
"JobStateAsString": "Confirmed",
"StateDateTime": "2020-10-30T10:05:55.6473117+00:00",
"PreviousJobState": {
"JobState": 0,
"JobStateAsString": "New",
"StateDateTime": "2020-10-30T07:33:28.439343+00:00",
"PreviousJobState": {
"JobState": -1,
"JobStateAsString": "Queued",
"StateDateTime": "2020-10-30T07:33:27.1042678+00:00",
"PreviousJobState": null
}
}
}
},
"_links": {
"self": {
"href": "https://api.realestatehub.haufe.io/CloudApi/V1/api/jobs/{JobId-GUID}/responses"
}
}
}