First of all, this information is provided by me @bjornsallarp as a result of my private investigations. Noone has assisted me or disclosed any details regarding the implementation at Handelsbanken. I have no association with Handelsbanken, in fact, I'm not even a customer with them.
Handelsbanken has not publically announced this API, this is the API they use for their iPhone application. I would really like for all banks to publish public APIs and let users access their own personal information.
Handelsbanken has not gone to great lengths to prevent us from using this API. They require three headers that must be sent with every request:
When authentication is successful a token is returned together with a sessions cookie. For GET requests the authToken is passed in the URL and for POST requests it's passed along with the other form values. Content-Type for all POST requests is: application/x-www-form-urlencoded are
POST https://m.handelsbanken.se/app//office-search
TEXT SEARCH BODY : searchParam=tranås&nearU=false
LOCATION SEARCH BODY: longitude=18.059718&latitude=59.349545&nearU=true&category=-1
RESPONSE:
<response code="000" label="OK">
<offices>
<office>
<clearing>6648</clearing>
<name>Tranås</name>
<address>Storgatan 28</address>
<city>Tranås</city>
<phone>0140-385440</phone>
<open>må-on 9.30-16, to 9.30-18, fr 9.30-16</open>
<category>-2</category>
<latitude />
<longitude />
<distance />
</office>
</offices>
<zoomSpan>
<longitudeDelta>0.01</longitudeDelta>
<latitudeDelta>0.01</latitudeDelta>
</zoomSpan>
</response>
There are two possibilities here. Either search using free-text or by GPS location.
There's a category parameter when searching using GPS location. -1 means both offices and ATMs. 1 = Offices only. 2 = ATMs.
POST https://m.handelsbanken.se/app//office-detail
BODY: clearingNumber=6648
RESPONSE:
<response code="000" label="OK">
<offices>
<office>
<clearing>6648</clearing>
<name>Tranås</name>
<address>Storgatan 28</address>
<city>Tranås</city>
<phone>0140-385440</phone>
<open>må-on 9.30-16, to 9.30-18, fr 9.30-16</open>
<category>1</category>
<latitude>58.03514099121094</latitude>
<longitude>14.976479530334473</longitude>
<distance>0.0</distance>
</office>
<office>
<clearing>6648-20</clearing>
<name>SHB</name>
<address>Storg 28</address>
<city>Tranås</city>
<phone />
<open />
<category>2</category>
<latitude>58.03501510620117</latitude>
<longitude>14.97634506225586</longitude>
<distance>16.070812225341797</distance>
</office>
<office>
<clearing>6618-20</clearing>
<name>SHB</name>
<address>Bryggerigatan 12</address>
<city>Hultsfred</city>
<phone />
<open />
<category>2</category>
<latitude>57.488033294677734</latitude>
<longitude>15.841794967651367</longitude>
<distance>79544.296875</distance>
</office>
<office>
<clearing>6672-20</clearing>
<name>SHB</name>
<address>Stora torget</address>
<city>Falköping</city>
<phone />
<open />
<category>2</category>
<latitude>58.160736083984375</latitude>
<longitude>13.554816246032715</longitude>
<distance>84645.6953125</distance>
</office>
<office>
<clearing>6598-20</clearing>
<name>SHB</name>
<address>Bergslagsv 9</address>
<city>Finspång</city>
<phone />
<open />
<category>2</category>
<latitude>58.70730209350586</latitude>
<longitude>15.774603843688965</longitude>
<distance>87989.9296875</distance>
</office>
<office>
<clearing>6593-80</clearing>
<name>SHB</name>
<address>Slåttergatan 106</address>
<city>Norrköping</city>
<phone />
<open />
<category>2</category>
<latitude>58.60360336303711</latitude>
<longitude>16.144941329956055</longitude>
<distance>92953.21875</distance>
</office>
<office>
<clearing>6596-80</clearing>
<name>SHB</name>
<address>Hageby centrum</address>
<city>Norrköping</city>
<phone />
<open />
<category>2</category>
<latitude>58.57255172729492</latitude>
<longitude>16.209123611450195</longitude>
<distance>93518.28125</distance>
</office>
<office>
<clearing>6707-20</clearing>
<name>SHB</name>
<address>Emmabodav 1</address>
<city>Nybro</city>
<phone />
<open />
<category>2</category>
<latitude>56.74229431152344</latitude>
<longitude>15.900981903076172</longitude>
<distance>153963.921875</distance>
</office>
</offices>
<zoomSpan>
<longitudeDelta>0.01</longitudeDelta>
<latitudeDelta>0.01</latitudeDelta>
</zoomSpan>
</response>
The list is shortened here because it's damn long!
GET https://m.handelsbanken.se/app//interests
RESPONSE:
<response code="000" label="OK">
<validTo>2011-10-29</validTo>
<rates>
<rate period="3 månader" value="4,39%" />
<rate period="1 år" value="4,39%" />
<rate period="2 år" value="4,20%" />
<rate period="3 år" value="4,32%" />
<rate period="5 år" value="4,79%" />
<rate period="8 år" value="5,03%" />
<rate period="10 år" value="5,20%" />
</rates>
<maxRateBind>5 år</maxRateBind>
<maxRateCurrent>4,82%</maxRateCurrent>
<maxRateTop>5,75%</maxRateTop>
<maxRateUpdate>3</maxRateUpdate>
</response>
POST https://m.handelsbanken.se/app//login BODY: username=8209250000&pin=1234&deviceid=f8280cf34708c7b5a8bd2ed93dcd3c814800000 RESPONSE HEADER: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2; Path=/;Secure;HttpOnly RESPONSE: <response code="000" label="OK"> <authToken>ecfdd82164e954ae57711f7969e13155</authToken> </response>
Oh happy day! The token and cookie needed for authenticating other requests!
GET https://m.handelsbanken.se/app//accounts?authToken=ecfdd82164e954ae57711f7969e13155 HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 RESPONSE: <response code="000" label="OK"> <accounts> <account> <accountId>1</accountId> <accountName>Allkonto</accountName> <accountNumber>00000000</accountNumber> <accountNumberModified>53 *** 018</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 125,43</accountAmount> <accountBalance>1 125,43</accountBalance> </account> <account> <accountId>2</accountId> <accountName>Allkonto</accountName> <accountNumber>00000000</accountNumber> <accountNumberModified>165 *** 212</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 125,32</accountAmount> <accountBalance>1 125,32</accountBalance> </account> <account> <accountId>3</accountId> <accountName>Sparkonto</accountName> <accountNumber>00000000</accountNumber> <accountNumberModified>254 *** 378</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 125,00</accountAmount> <accountBalance>1 125,00</accountBalance> </account> </accounts> </response>
Response information (such as account numbers etc) has been altered to anonymize it.
POST https://m.handelsbanken.se/app//transactions HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 BODY: authToken=ecfdd82164e954ae57711f7969e13155&type=1&account=1&accountType=1 RESPONSE: <response code="000" label="OK"> <account> <accountId>1</accountId> <accountName>Allkonto</accountName> <accountNumber>00000000</accountNumber> <accountNumberModified>53 *** 018</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 399,43</accountAmount> <accountBalance>1 399,43</accountBalance> </account> <transactions> <transactionCardTransactions>false</transactionCardTransactions> <transaction> <transactionDate> 2011-10-29</transactionDate> <transactionAmount>-130,00</transactionAmount> <transactionDescription>Prel kortköp</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-29</transactionDate> <transactionAmount>-75,35</transactionAmount> <transactionDescription>Prel kortköp</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-29</transactionDate> <transactionAmount>-398,00</transactionAmount> <transactionDescription>Prel kortköp</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-28</transactionDate> <transactionAmount>-159,00</transactionAmount> <transactionDescription>Prel kortköp</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-28</transactionDate> <transactionAmount>-317,54</transactionAmount> <transactionDescription>Prel kortköp</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-28</transactionDate> <transactionAmount>-150,00</transactionAmount> <transactionDescription>RÄDDA BARNEN</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-25</transactionDate> <transactionAmount>120,00</transactionAmount> <transactionDescription>ELIN PRESENT</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-22</transactionDate> <transactionAmount>-104,10</transactionAmount> <transactionDescription>HEMKOP</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-20</transactionDate> <transactionAmount>-358,00</transactionAmount> <transactionDescription>KICKS FALTOVER</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-20</transactionDate> <transactionAmount>-63,11</transactionAmount> <transactionDescription>VIDEOMIX</transactionDescription> <transactionType>1</transactionType> </transaction> <transaction> <transactionDate> 2011-10-14</transactionDate> <transactionAmount>-500,00</transactionAmount> <transactionDescription>SANGRIA TAPAS</transactionDescription> <transactionType>1</transactionType> </transaction> </transactions> </response>
The list is shortened here because it's damn long!
Response information (such as account numbers etc) has been altered to anonymize it.
GET https://m.handelsbanken.se/app//transfer?authToken=ecfdd82164e954ae57711f7969e13155 HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 RESPONSE: <response code="000" label="OK"> <control href="transfer-status" /> <fromAccounts> <accounts> <account> <accountId>0</accountId> <accountName>Allkonto</accountName> <accountNumber>000000</accountNumber> <accountNumberModified>53 *** 018</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 125,43</accountAmount> <accountBalance /> </account> <account> <accountId>1</accountId> <accountName>Allkonto</accountName> <accountNumber>000000</accountNumber> <accountNumberModified>165 *** 212</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 125,32</accountAmount> <accountBalance /> </account> <account> <accountId>2</accountId> <accountName>Sparkonto</accountName> <accountNumber>000000</accountNumber> <accountNumberModified>254 *** 378</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount>1 125,00</accountAmount> <accountBalance /> </account> </accounts> </fromAccounts> <toAccounts> <accounts> <account> <accountId>0</accountId> <accountName>Allkonto</accountName> <accountNumber>000000</accountNumber> <accountNumberModified>53 *** 018</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount /> <accountBalance /> </account> <account> <accountId>1</accountId> <accountName>Allkonto</accountName> <accountNumber>000000</accountNumber> <accountNumberModified>165 *** 212</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount /> <accountBalance /> </account> <account> <accountId>2</accountId> <accountName>Sparkonto</accountName> <accountNumber>000000</accountNumber> <accountNumberModified>254 *** 378</accountNumberModified> <typeAccount>1</typeAccount> <accountAmount /> <accountBalance /> </account> <account> <accountId>3</accountId> <accountName /> <accountNumber>000000</accountNumber> <accountNumberModified>53 *** 018</accountNumberModified> <typeAccount /> <accountAmount /> <accountBalance /> </account> <account> <accountId>4</accountId> <accountName /> <accountNumber>000000</accountNumber> <accountNumberModified>165 *** 212</accountNumberModified> <typeAccount /> <accountAmount /> <accountBalance /> </account> <account> <accountId>5</accountId> <accountName /> <accountNumber>000000</accountNumber> <accountNumberModified>254 *** 378</accountNumberModified> <typeAccount /> <accountAmount /> <accountBalance /> </account> </accounts> </toAccounts> </response>
This is a two step rocket.
POST https://m.handelsbanken.se/app//transfer-status HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 BODY: authToken=ecfdd82164e954ae57711f7969e13155&annotation=Björn testar&accountFromNr=1&message=Meddelande test&amount=100&accountToNr=0 RESPONSE: <response code="000" label="OK"> <commit href="transfer-result" /> </response>
This sets up the transfer for confirmation. I'm transfering 100 SEK from account 1 to account 0. The message is "Meddelande test" and shows up with the money on the incoming account. The annotation text "Björn testar" shows up with the withdrawl in the outgoing account.
GET https://m.handelsbanken.se/app//transfer-result?authToken=ecfdd82164e954ae57711f7969e13155 HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 RESPONSE: <response code="000" label="OK"> </response>
Money transfered!
GET https://m.handelsbanken.se/app//card-list?authToken=ecfdd82164e954ae57711f7969e13155 HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 RESPONSE: <response code="000" label="OK"> <cards> <card> <cardName>Bankkort VISA</cardName> <queueNumber>01</queueNumber> <cardNumber>4263 **** **** 9112</cardNumber> <accountNumber>53 *** 018</accountNumber> <accountName /> <cardStatusInternet>1</cardStatusInternet> <cardStatusAbroad>1</cardStatusAbroad> </card> </cards> </response>
POST https://m.handelsbanken.se/app//card-list HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 BODY: authToken=ecfdd82164e954ae57711f7969e13155&queueNumber=01&toggleAbroad=true&toggleInternet=false RESPONSE: <response code="000" label="OK"> <cards> <card> <cardName>Bankkort VISA</cardName> <queueNumber>01</queueNumber> <cardNumber>4263 **** **** 9112</cardNumber> <accountNumber>53 *** 018</accountNumber> <accountName /> <cardStatusInternet>1</cardStatusInternet> <cardStatusAbroad>0</cardStatusAbroad> </card> </cards> </response>
Obviously the toggleAbroad and toggleInternet parameters turns either on or off the functionality. The response is updated credit card information.
GET https://m.handelsbanken.se/app//logout?authToken=ecfdd82164e954ae57711f7969e13155 HEADER: Cookie: JSESSIONID=8706A37E49D05C486EB954D2D00DBFF2 RESPONSE: <response code="000" label="OK"> <loggedIn>false</loggedIn> </response>