Introduktion
Vi tillhandahåller ett API för maskinella uppdateringar av servicedata.
Detta API lämpar sig för organisationer som har IT-avdelningar/utvecklare, då det krävs att dataleverantörer utvecklar egna klienter för att jobba mot vårt API.
Med ServiceApi får du programmatiskt tillgång till Tillväxtverkets tjänster för att uppdatera servicedata.
Nedanstående video beskriver vår datamodell och centrala begrepp:
ServiceApi är ett REST-baserat API där data överförs som JSON.
För att använda ServiceApi krävs ett giltigt användarnamn och lösenord.
Tillväxtverket tillhandahåller en testinstans av ServiceApi som med fördel används vid utveckling och test.
Innehållet i testinstansens databas återställs varje natt.
Testinstansen har även ett grafiskt gränssnitt som nås genom samma adress och användaruppgifter.
Testserver | |
---|---|
Url | |
Användarnamn | testbanken |
Lösenord | Sommar&sol2020 |
Uppdateringsstrategier
Det finns flera strategier för att uppdatera data via vårt API, bland annat inkrementell och full uppdatering.
Båda strategierna kräver att leverantörens data matchas mot Tillväxtverkets servicedata.
ServiceApi tillhandahåller inga mekanismer för att matcha data, det ansvarar respektive leverantör för.
En matchning kan göras genom att hämta ut alla serviceplatser och sedan jämföra exempelvis dess adresser och koordinater med leverantörens interna register.
I Tillväxtverkets databas finns idag ca 17 000 serviceplatser och många av utförarna är samma år från år för de olika servicetyperna. Sannolikheten att det redan finns en befintlig serviceplats i databasen att koppla på en service till är därför stor. Trots detta kan en matchning mellan exempelvis besöksadress och postort ge relativt få träffar eftersom adresserna kan vara skrivna på olika sätt i de olika matchningsregistren.
Försök i möjligaste mån matcha mot en befintlig serviceplats innan ni ger er på att skapa helt nya serviceplatser. Tänk på att det kan finnas andra attribut i utförarinformationen som också går att matcha på än besöksadress och koordinat. Exempelvis kan även serviceplatsens namn vara vägledande för matchningsmetoden.
Inkrementell
Hämta via API en kollektion med all service och dess serviceplatser som leverantören ansvarar för.
Uppdatera de som har ändrats.
Radera de som har försvunnit.
Skapa de som har tillkommit.
När en ny service skapas, kontrollera ifall det finns en serviceplats på aktuell adress och använd den, annars skapa en ny serviceplats.
Endast serviceplatser som saknar relationer till service får raderas.
Upptäcks fel på befintliga serviceplatser, rapporteras dessa med ett ändringsförslag.
Full uppdatering
Vid en full uppdatering, då raderas först all service som leverantören ansvarar för, sedan skapas all service igen och binds till befintliga serviceplatser.
Fördelen med en full uppdatering är att borttag, nya och uppdateringar inte behöver hanteras separat, däremot måste all service som skapas matchas mot befintliga serviceplatser (där det är möjligt).
Autentisering
För att använda API'et krävs ett giltigt konto som utfärdas av Tillväxtverket.
Autentiseringen baseras på OAuth 2.0 Authentication.
Ett giltigt token erhålls efter en accepterad inloggning, därefter används denna token (bakas in i HTTP headern Authorization) i alla anrop mot API'et.
Logga in med en användare
Request
POST /Token HTTP/1.1 Accept: application/json Content-Type: application/x-www-form-urlencoded; charset=UTF-8 grant_type=password&username=testbanken&password=Sommar&sol2020
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "access_token": "imSXTs2aiadQhIXffziFCO3rF...", "token_type": "bearer", "expires_in":1209599, "userName": "testbanken", ".issued": "Wed, 01 Oct 2017 01:22:33 GMT", ".expires": "Wed, 15 Oct 2017 01:22:33 GMT" }
Användning av token
Vid anrop till API'et sätts HTTP headern Authorization till Bearer följt av ett mellanslag och sedan värdet av token (access_token som erhölls vid inloggningen ovan).
Request
GET /api/providers/7000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Provider (Serviceplats)
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning |
---|---|---|---|
id | int | frivillig, går inte att ändra | Serviceplatsens id, genereras av servern. |
name | string | obligatorisk | Namnet på serviceplatsen (ex. ICA Kvantum Landskrona, Swedbank AB Åre, Statoil Frösön). |
code | string | frivillig, går inte att ändra | Intern unik kod för serviceplatsen, genereras av servern och används bland annat för att förenkla återkoppling vid uppdatering. |
visitingAddress | string | obligatorisk | Serviceplatsens besöksadress. |
postalCode | string | obligatorisk | Serviceplatsens postnummer. |
postTown | string | obligatorisk | Serviceplatsens postort. |
x | float | obligatorisk | Serviceplatsens x-koordinat i SWEREF99 TM (EPSG:3006) |
y | float | obligatorisk | Serviceplatsens y-koordinat i SWEREF99 TM (EPSG:3006) |
services | array | utelämnas | En lista över service som serviceplatsen tillhandahåller (en serviceplats kan tillhandahålla flera service av samma typ och form under förutsättning att servicen har olika huvudmän). Default tom, används bara då 'embedservices' sätts till true i anropet FindAll. |
properties | dictionary | frivillig | En dictionary med nycklar och värden för att lagra egendefinierad data till serviceplatsen. Kan fritt användas för att t.ex. spara metadata som externa id'n (för att förenkla koppling/matchning mot externt data) eller geokodningens källa. |
GetProvider (hämta en serviceplats)
Request
GET /api/providers/7000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "x": 509886.4, "y": 6568855.5, "services": [], "properties": {} } } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested provider not found" }] }
GetServicesForProvider (hämta den service som tillhandahålls av serviceplatsen)
Request
GET /api/providers/7000/services HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "type": "service", "id": 30000, "data": [{ "attributes": { "id": 30000, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 2, "forms": ["Bankkassa med kontanter","Bankkassa mot bankkonto/kort"], "properties": null, "active": true, "year": 0 }, { "attributes": { "id": 30001, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 1, "forms": ["Uttagsautomat"], "properties": null, "active": true, "year": 0 }] } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested provider not found" }] }
GetServicesForProviderByYear (hämta den service som tillhandahålls av serviceplatsen för ett specifikt år)
Request
GET /api/providers/7000/services/2016 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "type": "service", "id": 30000, "data": [{ "attributes": { "id": 30000, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 2, "forms": ["Bankkassa med kontanter","Bankkassa mot bankkonto/kort"], "properties": null, "active": true, "year": 2016 }, { "attributes": { "id": 30001, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 1, "forms": ["Uttagsautomat"], "properties": null, "active": true, "year": 2016 }] } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested provider not found" }] }
FindAllProviders (hämta en lista med serviceplatser, utifrån sökkriterier)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
query | string | frivillig | fulltextsökning |
servicetype | string | frivillig | Hämta bara serviceplatser som tillhandahåller service av en viss typ (t.ex. Kontantuttag eller Dagligvaruförsäljning) |
limit | int | frivillig | Anger hur många serviceplatser som ska hämtas åt gången |
start | int | frivillig | Anger hur många serviceplatser som ska hoppas över vid paging |
embedservices | bool | frivillig | Anger om den service som serviceplatsen tillhandahåller ska inkluderas in i svaret. |
Request
GET /api/providers HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "x": 509886.4, "y": 6568855.5, "services": [], "properties": {} } }, // ... { "id": 7001, "type": "provider", "attributes": { "id": 7001, "name": "INGO Örebro, Bettorpsgatan", "code": "INGO-0080", "visitingAddress": "Bettorpsgatan 24", "postalCode": "703 69", "postTown": "ÖREBRO", "x": 513141.5, "y": 6574119.3, "services": [], "properties": {} } }] }
FindProvidersByCoordinate (hämta en lista med serviceplatser inom en radie från en angiven koordinat)
Funktionen returnerar en lista med serviceplatser som är sorterad på avståndet från serviceplatsen till koordinaten (närmast först).
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
x | int | obligatorisk | X-koordinat i SWEREF 99 |
y | int | obligatorisk | Y-koordinat i SWEREF 99 |
buffer | int | obligatorisk | Sökradie i meter |
limit | int | frivillig | Anger hur många serviceplatser som ska hämtas åt gången |
Request
GET /api/providers/coordinate?x=466588&y=6985694&buffer=1000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "x": 509886.4, "y": 6568855.5, "services": [], "properties": {} } }, // ... { "id": 7001, "type": "provider", "attributes": { "id": 7001, "name": "INGO Örebro, Bettorpsgatan", "code": "INGO-0080", "visitingAddress": "Bettorpsgatan 24", "postalCode": "703 69", "postTown": "ÖREBRO", "x": 513141.5, "y": 6574119.3, "services": [], "properties": {} } }] }
FindProvidersByProperty (hämta en lista med serviceplatser filtrerat ett "nyckel/värde"-par i attributet properties)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
key | string | obligatorisk | Nyckeln i properties |
value | string | obligatorisk | Nyckelns värde |
limit | int | frivillig | Anger hur många serviceplatser som ska hämtas åt gången |
Request
GET /api/providers/property/?key=externalId&value=123456 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "x": 509886.4, "y": 6568855.5, "services": [], "properties": { "externalId": "123456" } } }] }
FindOwnProviders (hämta en lista med egna serviceplatser, dvs. serviceplatsen tillhandahåller service som aktuell användare äger)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
servicetype | string | frivillig | Hämta bara serviceplatser som tillhanda håller service av en viss typ (t.ex. Kontantuttag eller Dagligvaruförsäljning) |
limit | int | frivillig | Anger hur många serviceplatser som ska hämtas åt gången |
start | int | frivillig | Anger hur många serviceplatser som ska hoppas över vid paging |
embedservices | bool | frivillig | Anger om den service som serviceplatsen tillhandahåller ska inkluderas in i svaret. |
Request
GET /api/providers/own HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "x": 509886.4, "y": 6568855.5, "services": [], "properties": {} } }, // ... { "id": 7001, "type": "provider", "attributes": { "id": 7001, "name": "INGO Örebro, Bettorpsgatan", "code": "INGO-0080", "visitingAddress": "Bettorpsgatan 24", "postalCode": "703 69", "postTown": "ÖREBRO", "x": 513141.5, "y": 6574119.3, "services": [], "properties": {} } }] }
CreateProvider (skapa en ny serviceplats)
Request
POST /api/providers HTTP/1.1 Content-Type: application/vnd.api+json Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF... { "data": { "type": "provider", "attributes": { "name": "INGO Örebro, Adolfsbergsvägen", "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "x": 509886.4, "y": 6568855.5 } } }
Response 201 Created
HTTP/1.1 201 Created Content-Type: application/json { "data": { "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "x": 509886.4, "y": 6568855.5, "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "properties": {} } } }
Response 409 Conflict
HTTP/1.1 409 Conflict Content-Type: application/json { "errors": [{ "detail": "A provider with similar/equals attributes already exists", "source": "https://example.com/provider/6000" }] }
UpdateProvider (uppdatera en befintlig serviceplats)
Request
PATCH /api/providers/7000 HTTP/1.1 Content-Type: application/json Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF... { "data": { "type": "provider", "id": 7000, "attributes": { "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "x": 509886.4, "y": 6568855.5, "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "properties": {} } } }
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "type": "provider", "id": 7000, "attributes": { "id": 7000, "name": "INGO Örebro, Adolfsbergsvägen", "code": "INGO-0079", "x": 509886.4, "y": 6568855.5, "visitingAddress": "Adolfsbergsvägen 4", "postalCode": "702 27", "postTown": "ÖREBRO", "properties": {} } } }
Response 409 Conflict
HTTP/1.1 409 Conflict Content-Type: application/json { "errors": [{ detail: "Invalid SWEREF99 coordinate" }] }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested provider not found" }] }
DeleteProvider (ta bort en befintlig serviceplats)
Request
DELETE /api/providers/7000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 Ok Content-Type: application/json {}
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Provider not found" }] }
Response 409 Conflict
HTTP/1.1 409 Conflict Content-Type: application/json { "errors": [{ detail: "The selected provider cannot be deleted since it is referenced by other services" }] }
Service (tjänst)
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | int | Genereras | Servicens id, genereras av servern. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
providerId | int | Obligatorisk | Id till serviceplatsen som tillhandahåller servicen, se Serviceplatser. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
servicePrincipalId | int | Obligatorisk | Id för servicens huvudman, se Huvudman. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
serviceTypeId | int | Obligatorisk | Id till typen av service som utförs, se Servicetyp. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
properties | dictionary | Frivillig | En dictionary med nycklar och värden som är knutna till specifik servicetyp.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
forms | array | Obligatorisk | Det sätt som servicen tillhandahålls. Form är knutet till servicetyp. En service kan ha en eller flera former. Giltiga värden för form för respektive servicetyp beskrivs nedan.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
active | bool | Obligatorisk | Anger om servicen tillfälligt är inaktiv, ex. säsongsbutik som bara är öppen under sommarhalvåret. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
year | int | Frivillig (Sätts till nutid) | Det år servicen tillhör. Default är 0 vilket motsvarar aktuellt år. Vid varje årsskifte körs en intern process som arkiverar det gångna årets service. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timelinessDate | date | Frivillig | Senast uppdaterad. För aktuellt år måste datumet ligga inom intervallet xxxx-01-01 till aktuellt datum. För historiskt data ska datumet ligga inom året. |
GetService (hämta en service)
Request
GET /api/services/30000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "type": "service", "id": 30000, "data": { "attributes": { "id": 30000, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 2, "forms": ["Bankkassa med kontanter","Bankkassa mot bankkonto/kort"], "properties": null, "active": true, "year": 0, "timelinessDate": "2019-01-20T00:00:00" } } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested service not found" }] }
CreateService (skapa en ny service)
Request
POST /api/services HTTP/1.1 Content-Type: application/json Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF... { "data": { "type": "service", "attributes": { "providerId": 7000, "servicePrincipalId": 123, "serviceTypeId": 7, "forms": [], "properties": { "revenue": 250000 }, "active": true, "timelinessDate": "2019-01-11T00:00:00+01:00" } } }
Response 201 Created
HTTP/1.1 201 Created Content-Type: application/json { "data": { "type": "service", "id": 30000, "attributes": { "id": 30000, "providerId": "7000", "servicePrincipalId": "123", "serviceTypeId": "7", "forms": [], "properties": { "revenue": 250000 }, "active": true, "year": 0, "timelinessDate": "2019-01-11T00:00:00+01:00" } } }
Response 409 Conflict
HTTP/1.1 409 Conflict Content-Type: application/json { "errors": [{ "detail": "Truck diesel is not a valid form for service type Kontantuttag" }] }
UpdateService (uppdatera en befintlig service)
Request
PATCH /api/services/30000 HTTP/1.1 Content-Type: application/json Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF... { "data": { "type": "service", "id": 30000, "attributes": { "providerId": "7000", "servicePrincipalId": "123", "serviceTypeId": "7", "forms": ['Dagligvaror'], "properties": { "revenue": 250000 }, "active": true, "timelinessDate": "2019-01-11T00:00:00+01:00" } } }
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "type": "service", "id": 30000, "attributes": { "id": 30000, "providerId": "7000", "servicePrincipalId": "123", "serviceTypeId": "7", "forms": ['Dagligvaror'], "properties": { "revenue": 250000 }, "active": true, "year": 0, "timelinessDate": "2019-01-11T00:00:00+01:00" } } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested service not found" }] }
Response 409 Conflict
HTTP/1.1 409 Conflict Content-Type: application/json { "errors": [{ detail: "No principal with id 123 exists." }] }
DeleteService (ta bort en befintlig service)
Request
DELETE /api/services/30000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Responses 200 OK
HTTP/1.1 200 Ok Content-Type: application/json {}
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Service not found" }] }
GetServicesByPrincipal (hämta en lista med all service som ägs av en huvudman)
Request
GET /api/services?principalId=20 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "attributes": { "id": 30000, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 2, "forms": ["Bankkassa med kontanter","Bankkassa mot bankkonto/kort"], "properties": { "lst": false }, "active": true, "year": 0, "timelinessDate": "2019-01-20T00:00:00" } }, { "attributes": { "id": 30001, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 1, "forms": ["Uttagsautomat"], "properties": { "lst": false, "ticketsRequired": false }, "active": true, "year": 0, "timelinessDate": "2019-01-20T00:00:00" } }] }
FindServicesByProperty (hämta en lista med service filtrerat på ett "nyckel/värde"-par i attributet properties)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
key | string | obligatorisk | Nyckeln i properties |
value | string | obligatorisk | Nyckelns värde |
year | int | frivillig | Det år servicen tillhör. Default är 0 vilket motsvarar aktuellt år. |
limit | int | frivillig | Anger hur många serviceobjekt som ska hämtas åt gången |
Request
GET /api/services/property/?key=externalId&value=123456&limit=2 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "attributes": { "id": 30000, "providerId": 7000, "servicePrincipalId": 20, "serviceTypeId": 2, "forms": ["Bankkassa med kontanter","Bankkassa mot bankkonto/kort"], "properties": { "externalId": '123456' }, "active": true, "year": 0, "timelinessDate": "2019-01-20T00:00:00" } }] }
Servicetype (typ av service)
Beskrivning av attribut
Namn | Typ | Beskrivning |
---|---|---|
id | int | Servicetypens id, genereras av servern. |
name | string | Servicetyp är den typ av betaltjänst som erbjuds:
|
GetServiceType (hämta en servicetyp)
Request
GET /api/servicetypes/7 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "type": "serviceType", "id": 7, "attributes": { "id": 7, "name": "Dagligvaror" } } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested servicetype not found" }] }
GetAllServiceTypes (hämta en lista med alla servicetyper)
Request
GET /api/servicetypes/ HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "serviceType", "id": 1, "attributes": { "id": 1, "name": "Kontantuttag" } }, //... { "type": "serviceType", "id": 7, "attributes": { "id": 7, "name": "Dagligvaror" } } }
ServicePrincipal (huvudman)
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning |
---|---|---|---|
id | int | Genereras | Huvudmannens id, genereras av servern. |
name | string | Obligatorisk | Huvudmannens namn. |
GetPrincipal (hämta en huvudman)
Request
GET /api/serviceprincipals/30 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "type": "servicePrincipal", "id": 7, "attributes": { "id": 7, "name": "Dagligvaror" } } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested service principal not found" }] }
GetAllServicePrincipals (hämtar en lista med alla huvudmän)
Request
GET /api/serviceprincipals/ HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "servicePrincipal", "id": 1, "attributes": { "id": 1, "name": "Gulf - EMAB AB" } }, //... { "type": "servicePrincipal", "id": 40, "attributes": { "id": 40, "name": "Nära Dej" } } }
CreatePrincipal (skapa en ny huvudman)
Request
POST /api/serviceprincipals HTTP/1.1 Content-Type: application/json Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF... { "data": { "type": "servicePrincipal", "attributes": { "name": "ICA Sverige AB" } } }
Response 201 Created
HTTP/1.1 201 Created Content-Type: application/json { "data": { "type": "servicePrincipal", "id": 40, "attributes": { "id": 40, "name": "ICA Sverige AB" } } }
Response 409 Conflict
HTTP/1.1 409 Conflict Content-Type: application/json { "errors": [{ "detail": "ICA Sverige AB already exists" }] }
Serviceform (formen av den service som utförs)
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning |
---|---|---|---|
id | int | Genereras | Serviceformens id, genereras av servern. |
serviceTypeId | int | Obligatorisk | Id till den servicetypen som serviceformen tillhör. |
name | string | Obligatorisk | Namnet på serviceformen. |
GetServiceForm (hämta en serviceform)
Request
GET /api/serviceform/19 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "type": "serviceForm", "id": 19, "attributes": { "id": 19, "name": "Kortterminal" "serviceTypeId": 1, } } }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Requested servicetype not found" }] }
GetAllServiceForms (hämta en lista med alla serviceformer)
Request
GET /api/serviceforms/ HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "type": "serviceForm", "id": 21, "attributes": { "id": 21, "name": "Bankkassa", "serviceTypeId": 1 } }, //... { "type": "serviceForm", "id": 10, "attributes": { "id": 10, "name": "Dagligvaror", "serviceTypeId": 3 } } }
Organisation
Beskrivning av attribut
Namn | Typ | Beskrivning |
---|---|---|
id | int | Organisationens id, genereras av servern. |
name | string | Namnet på organisationen (ex. Testbanken AB). |
organisationNumber | string | Organisationsnummer (unik). |
username | string | Det användarnamn organisationen använder för att registrera uppdaterare i administrationsportalen. |
string | E-postadress till ovan användare. | |
isSupplier | bool | Anger om organisationen är ett kreditinstitut. |
isPrincipal | bool | Anger om organisationen är en huvudman. |
servicePrincipalId | int | Om organisationen är en huvudman anges huvudmannens id-nummer här. |
activeSupplier | bool | Anger om organisationen är ett aktivt kreditinstitut. |
inactiveSupplierCaseNumber | string | Om organisationen sätts till inaktivt kreditinstitut, anges ärendenumret här. |
activePrincipal | bool | Anger om organisationen är en aktiv huvudman. |
inactivePrincipalCaseNumber | string | Om organisationen sätt till inaktiv huvudman, anges ärendenumret här. |
submitted | bool | När alla uppdatering är klar sätts submitted till true och redigeringsmöjligheterna blir låsta. |
GetOrganisation (hämta en organisation)
Request
GET /api/organisations/7000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "attributes": { "id": 6, "name": "Testbanken AB", "organisationNumber": "12345678-1234", "servicePrincipalId": 245, "username": "lassekongo", "email": "lassekongo@mail.com", "isSupplier": true, "isPrincipal": true, "activePrincipal": true, "activeSupplier": true, "submitted": false, "inactiveSupplierCaseNumber": "", "inactivePrincipalCaseNumber": "" }, "id": 6, "type": "organisation" }
Response 404 Not Found
HTTP/1.1 404 Not Found Content-Type: application/json { "errors": [{ "detail": "Ingen organisation med id 123 hittades." }] }
ServiceFormTemplate
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning |
---|---|---|---|
id | int | Genereras | Mallens id, genereras av servern. |
principalOrganisationId | int | Obligatorisk | Id till den organisation som äger mallen, se Organisation |
serviceTypeId | int | Obligatorisk | Id till typen av service som utförs, se Servicetyp. |
serviceFormId | int | Obligatorisk | Id till formen som utförs, se Serviceform. |
openHoursPerWeek | int | Frivillig | Öppettider anges i timmar per vecka under normalvecka. Med normalvecka avses en vecka som består av fem helgfria dagar samt lördag och söndag utan extra helgdagar, under normalsäsong. Om platsen för kontanttjänsten finns i en lokal eller inrättning som har kortare öppettider än platsen anges lokalens eller inrättningens öppettider. Giltiga värden är 0 till 168. |
closedWeeksPerYear | int | Frivillig | Anges i antal veckor per år som platsen är stängd. Giltiga värden är 0 till 53. |
advancedOpenHourDescription | string | Frivillig | Fält där avgiftsmodellen kan förklaras i fritext om den inte passar in i ovanstående alternativ eller om det finns olika avgifter för olika kunder. |
withdrawalLimit | int | Frivillig | Ange högsta tillåtna belopp per uttag, som du som huvudman tillåter. Ange 0 om inte maxbelopp tillämpas. |
minFlatFee | int | Frivillig | Fylls i med lägsta fasta avgift. Beloppet anges i kronor. |
minPercentageFee | float | Frivillig | Fylls i med lägsta rörliga avgift i form av procent av uttag. Anges i procent, giltiga värden är 0 till 100. |
maxFlatFee | int | Frivillig | Fylls i med högsta fasta avgift. Beloppet anges i kronor. |
maxPercentageFee | float | Frivillig | Fylls i med högsta rörliga avgift i form av procent av uttag. Anges i procent, giltiga värden är 0 till 100. |
advancedFeeDescription | string | Frivillig | Fält där avgiftsmodellen kan förklaras i fritext om den inte passar in i ovanstående alternativ eller det finns olika avgifter för olika kunder. |
depositLimit | int | Frivillig | Ange högsta tillåtna belopp per insättning, som du som huvudman tillåter. Beloppet ska anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
withdrawalLimitDescription | string | Frivillig | Fält där modell för lägsta maxbelopp för insättning eller uttag kan förklaras i fritext om den inte passar in i ovanstående alternativ. |
weeklyDepositLimit | int | Frivillig | Ange högsta tillåtna belopp, som du som huvudman tillåter, att kunden får sätta in på en vecka. Beloppet ska anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
accessBarrier | bool | Frivillig | Tillträdeshinder. Sant om det krävs inträdesbiljett och/eller specifik behörighet till område/lokal. Om tillträdeshinder är sant ska attributet accessBarrierDescription anges. |
accessBarrierDescription | string | Frivillig | Fält där tillträdeshindret kan förklaras i fritext. |
GetServiceFormTemplate (hämta en en mall)
Request
|
Response 200 OK
|
GetServiceFormTemplatesByOrganisation (hämta de mallar som ägs av organisationen)
Request
|
Response 200 OK
|
UpdateServiceFormTemplate (Uppdatera en mall)
Request
|
Response 200 OK
|
ServiceFormCustomization
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning |
---|---|---|---|
id | int | Genereras | Anpassningens id, genereras av servern. |
serviceId | int | Obligatorisk | Id till den service som anpassningen hör till. |
serviceFormId | int | Obligatorisk | Id till den serviceform som anpassningen hör till. |
accessBarrier | bool | Frivillig | Tillträdeshinder. Sant om det krävs inträdesbiljett och/eller specifik behörighet till område/lokal. Om tillträdeshinder är sant ska attributet accessBarrierDescription anges. |
accessBarrierDescription | string | Frivillig | Fält där tillträdeshindret kan förklaras i fritext. |
openHoursPerWeek | int | Frivillig | Öppettider anges i timmar per vecka under normalvecka. Med normalvecka avses en vecka som består av fem helgfria dagar samt lördag och söndag utan extra helgdagar, under normalsäsong. Om platsen för kontanttjänsten finns i en lokal eller inrättning som har kortare öppettider än platsen anges lokalens eller inrättningens öppettider. Giltiga värden är 0 till 168. |
closedWeeksPerYear | int | Frivillig | Anges i antal veckor per år som platsen är stängd. Giltiga värden är 0 till 53. |
advancedOpenHourDescription | string | Frivillig | Fält där avgiftsmodellen kan förklaras i fritext om den inte passar in i ovanstående alternativ eller om det finns olika avgifter för olika kunder. |
withdrawalLimit | int | Frivillig | Ange högsta tillåtna belopp per uttag, som du som huvudman tillåter. Ange 0 om inte maxbelopp tillämpas. |
minFlatFee | int | Frivillig | Fylls i med lägsta fasta avgift. Beloppet anges i kronor. |
minPercentageFee | float | Frivillig | Fylls i med lägsta rörliga avgift i form av procent av uttag. Anges i procent, giltiga värden är 0 till 100. |
maxFlatFee | int | Frivillig | Fylls i med högsta fasta avgift. Beloppet anges i kronor. |
maxPercentageFee | float | Frivillig | Fylls i med högsta rörliga avgift i form av procent av uttag. Anges i procent, giltiga värden är 0 till 100. |
advancedFeeDescription | string | Frivillig | Fält där avgiftsmodellen kan förklaras i fritext om den inte passar in i ovanstående alternativ eller det finns olika avgifter för olika kunder. |
depositLimit | int | Frivillig | Ange högsta tillåtna belopp per insättning, som du som huvudman tillåter. Beloppet ska anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
withdrawalLimitDescription | string | Frivillig | Fält där modell för lägsta maxbelopp för uttag eller insättning kan förklaras i fritext om den inte passar in i ovanstående alternativ. Ange 0 om inte maxbelopp tillämpas. |
weeklyDepositLimit | int | Frivillig | Ange högsta tillåtna belopp, som du som huvudman tillåter, att kunden får sätta in på en vecka. Beloppet ska anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
ServiceSupplierModel
Beskrivning av attribut
Namn | Typ | Krav vid update/create | Beskrivning |
---|---|---|---|
id | int | Genereras | Modellens id, genereras av servern. |
supplierOrganisationId | int | Obligatorisk | Organisations-id till det kreditinstitut eller filial till utländskt kreditinstitut som omfattas av skyldigheten att tillhandahålla kontanttjänster. |
principalOrganisationId | int | Obligatorisk | Organisations-id till den huvudman som driver eller på annat sätt råder över kontanttjänsten. |
serviceTypeId | int | Obligatorisk | Servicetyps-id till den typ av betaltjänst som erbjuds (kontantuttag, dagskasseinsättning eller betalningsförmedling). |
serviceFormId | int | Obligatorisk | Serviceforms-id till den serviceform modellen gäller. |
minFlatFee | int | Obligatorisk | Avgift per uttag (fast avgift). |
minPercentageFee | float | Obligatorisk | Avgift per uttag (rörlig avgift). |
maxFlatFee | int | Obligatorisk | Avgift per uttag (fast avgift). Totala högsta fasta avgift som era slutkunder får betala när de använder den aktuella betaltjänsten hos ovan vald huvudman. Belopp anges i kronor. |
maxPercentageFee | float | Obligatorisk | Avgift per uttag (rörlig avgift). Totala högsta rörliga avgift som era slutkunder får betala när de använder den aktuella betaltjänsten hos ovan vald huvudman. Värdet anges i %. |
advancedWithdrawalFeeDescription | string | Frivillig | Fält där avgiftsmodellen kan förklaras i fritext om den inte passar in i ovanstående alternativ. |
withdrawalLimit | int | Frivillig | Ange högsta tillåtna belopp per uttag för era slutkunder när de gör uttag från ert betalkonto genom tjänst hos aktuell huvudman och för vald serviceform. Beakta gränser för maxbelopp hos er och hos huvudmannen (dvs välj det lägsta av de två). Beloppet ska anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
weeklyDepositLimit | int | Frivillig | Ange högsta tillåtna belopp som era slutkunder får sätta in på en vecka på betalkonto hos er genom tjänst hos ovan vald huvudman och för ovan vald serviceform. Beakta gällande maxbelopp hos er och hos huvudmannen (dvs välj det lägsta av de två). Beloppet anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
depositLimit | int | Frivillig | Ange högsta tillåtna belopp per insättning som era slutkunder får sätta in på betalkonto hos er genom tjänst hos ovan vald huvudman och för ovan serviceform. Beakta gällande maxbelopp hos er och hos huvudmannen (dvs välj det lägsta av de två). Beloppet anges i kronor. Ange 0 om inte maxbelopp tillämpas. |
withdrawalLimitDescription | string | Frivillig | Fält där modell för lägsta maxbelopp för insättning eller uttag kan förklaras i fritext om den inte passar in i ovanstående alternativ. |
includedServiceIds | int[] | Frivillig | Inkludera bara specifika platser för kontanttjänster hos vald huvudman. Listan innehåller id till service. |
Address
Beskrivning av attribut
Namn | Typ | Beskrivning |
---|---|---|
id | int | Adressens interna id. |
address | string | Postadress |
postal_code | int | Postnummer |
post_town | string | Postort |
formatted_address | string | Formaterad adress |
x | double | X-koordinat i SWEREF 99 |
y | double | Y-koordinat i SWEREF 99 |
FindByAttributes (Söker adress med hjälp av postadress, postnummer och postort)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
address | string | obligatorisk | Postadress |
postalcode | int | obligatorisk | Postnummer |
posttown | string | obligatorisk | Postort |
Request
GET /api/geocode/findByAttributes/?address=storgatan%2044&postalCode=11455&postTown=stockholm HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
FindByCoordinate (Söker närmaste adress från en koordinat i SWEREF 99)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
x | int | obligatorisk | X-koordinat i SWEREF 99 TM (EPSG 3006) |
y | int | obligatorisk | Y-koordinat i SWEREF 99 TM (EPSG 3006) |
Request
GET /api/geocode/findByCoordinate/?x=600000&y=7000000 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": { "attributes": { "id": 379665, "address": "Storgatan 44", "postal_code": 11455, "post_town": "Stockholm", "formatted_address": "Storgatan 44, 114 55 Stockholm", "x": 600002.88, "y": 7000010.607 }, "id": 379665, "type": "addressPlace" } }
FindByPattern (Söker adresser med hjälp av fritext, returnerar en lista med adresser sorterad på relevans)
Parameter | Typ | Krav | Beskrivning |
---|---|---|---|
pattern | string | required | Fritextfält, t. ex. "Storgatan 44, Stockholm" |
limit | int | required | Max antal sökträffar som ska returneras |
Request
GET /api/geocode/findByPattern/?pattern=storgatan%2044%2C%20stockholm&limit=10 HTTP/1.1 Accept: application/json Authorization: Bearer imSXTs2aiadQhIXffziFCO3rF...
Response 200 OK
HTTP/1.1 200 OK Content-Type: application/json { "data": [{ "attributes": { "id": 379665, "address": "Storgatan 44", "postal_code": 11455, "post_town": "Stockholm", "formatted_address": "Storgatan 44, 114 55 Stockholm", "x": 675797.33, "y": 6581265.607 }, "id": 379665, "type": "addressPlace" }, { "attributes": { "id": 1517317, "address": "Storgatan 44A", "postal_code": 11455, "post_town": "Stockholm", "formatted_address": "Storgatan 44A, 114 55 Stockholm", "x": 675801.006, "y": 6581247.599 }, "id": 1517317, "type": "addressPlace" }] }
Kodexempel
Python3
#-*- coding: utf-8 -*- import urllib.request import urllib.error import urllib.parse import json BASE_URL = 'https://kontantanalys.tillvaxtverket.se/test' def acquire_token(username, password): """ Login and acquire a valid token """ url = BASE_URL + '/Token' data = { 'grant_type': 'password', 'username': username, 'password': password } opener = urllib.request.build_opener() response = opener.open(url, urllib.parse.urlencode(data).encode("utf-8")) if response.getcode() == 200: content = response.read() data = json.loads(content) return data['access_token'] return None def create_provider(provider, token): headers = { 'Authorization': 'Bearer %s' % token, 'Content-Type': 'application/json', 'Accept': 'application/json' } envelope = { "data": provider } url = BASE_URL + '/api/providers/' data = json.dumps(envelope).encode('utf8') req = urllib.request.Request(url, headers=headers) try: response = urllib.request.urlopen(req, data=data) content = response.read() new_object = json.loads(content) return new_object['data'] except urllib.error.HTTPError as e: content = e.read() if content: errors = json.loads(content) print ('Error (%d) create provider' % e.code) for error in errors['errors']: print (error) else: print ('Error (%d) create provider' % e.code) return None def find_provider(provider_id, token): """ Get provider by id """ opener = urllib.request.build_opener() opener.addheaders = [('Authorization', 'Bearer %s' % token)] url = BASE_URL + '/api/Providers/%d' % provider_id response = opener.open(url) content = response.read() data = json.loads(content) return data['data'] def main(): token = acquire_token('testbanken', 'Sommar&sol2020') provider = { 'type': 'provider', 'attributes': { 'name': 'INGO Örebro, Adolfsbergsvägen', 'visitingAddress': 'Adolfsbergsvägen 4', 'postalCode': '702 27', 'postTown': 'ÖREBRO', 'x': 509886.4, 'y': 6568855.5 } } new_provider = create_provider(provider, token) if new_provider: provider = find_provider(new_provider['id'], token) assert provider['attributes']['name'] == new_provider['attributes']['name'] if __name__== "__main__": main()
C#
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Web; using Newtonsoft.Json; namespace PiPoS.Examples { public class ApiExamples { static readonly string BASE_URL = "https://kontantanalys.tillvaxtverket.se/test"; public static void Main(string[] args) { var token = AcquireToken("testbanken", "Sommar&sol2020"); var provider = new Provider { Name = "INGO Örebro, Adolfsbergsvägen", VisitingAddress = "Adolfsbergsvägen 4", PostalCode = "702 27", PostTown = "ÖREBRO", X = 509886.4, Y = 6568855.5 }; var newProvider = CreateProvider(provider, token); provider = FindProvider(newProvider.Id, token); System.Diagnostics.Debug.Assert(newProvider.Name == provider.Name); } static string AcquireToken(string username, string password) { string token = string.Empty; using (var client = new WebClient()) { client.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var formData = string.Format("grant_type=password&username={0}&password={1}", HttpUtility.UrlEncode(username), HttpUtility.UrlEncode(password) ); var htmlResult = client.UploadString(BASE_URL + "/Token", formData); var json = JsonConvert.DeserializeObject<Dictionary<string, object>>(htmlResult); if (json.ContainsKey("access_token")) { token = json["access_token"] as string; } } return token; } static Provider CreateProvider(Provider provider, string token) { using (var client = new WebClient()) { client.Headers.Add(HttpRequestHeader.Authorization, string.Format("Bearer {0}", token)); client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); client.Headers.Add(HttpRequestHeader.Accept, "application/json"); var envelope = new Envelope<Provider> { Data = new Data<Provider> { Attributes = provider, Type = "provider" } }; var json = JsonConvert.SerializeObject(envelope); var result = string.Empty; try { result = client.UploadString(BASE_URL + "/api/providers/", json); } catch (WebException exception) { var responseStream = exception.Response?.GetResponseStream(); if (responseStream != null) { using (var reader = new StreamReader(responseStream)) { var responseText = reader.ReadToEnd(); if (!string.IsNullOrEmpty(responseText)) { try { var responseData = JsonConvert.DeserializeObject<Error>(responseText); foreach (var error in responseData?.Errors) { Console.Error.WriteLine($"Error:\t{error}"); } } catch (JsonReaderException) { Console.Error.WriteLine(responseText); } } } } throw exception; } var newProvider = JsonConvert .DeserializeObject<Envelope<Provider>>(result) .Data .Attributes; return newProvider; } } static Provider FindProvider(int providerId, string token) { using (var client = new WebClient()) { client.Headers.Add(HttpRequestHeader.Authorization, string.Format("Bearer {0}", token)); using (var data = client.OpenRead(BASE_URL + $"/api/providers/{providerId}")) using (var reader = new StreamReader(data)) { var provider = JsonConvert .DeserializeObject<Envelope<Provider>>(reader.ReadToEnd()) .Data .Attributes; return provider; } } } public class Envelope<TEntity> { [JsonProperty(PropertyName = "data")] public Data<TEntity> Data { get; set; } } public class Data<TEntity> { [JsonProperty(PropertyName = "attributes")] public TEntity Attributes { get; set; } [JsonProperty(PropertyName = "id")] public int Id { get; set; } [JsonProperty(PropertyName = "type")] public string Type { get; set; } } public class Provider { [JsonProperty(PropertyName = "id")] public int Id { get; set; } [JsonProperty(PropertyName = "name")] public string Name { get; set; } [JsonProperty(PropertyName = "code")] public string Code { get; set; } [JsonProperty(PropertyName = "x")] public double X { get; set; } [JsonProperty(PropertyName = "y")] public double Y { get; set; } [JsonProperty(PropertyName = "visitingAddress")] public string VisitingAddress { get; set; } [JsonProperty(PropertyName = "postalCode")] public string PostalCode { get; set; } [JsonProperty(PropertyName = "postTown")] public string PostTown { get; set; } [JsonIgnore] public string TypeName => "provider"; } public class Error { [JsonProperty(PropertyName = "errors")] public List<string> Errors { get; set; } } } }