VismaBouwsoftAPICalls Class (Inherits from Object)

Visma Bouwsoft API - Version 1

Which server to call
Calling the API
API Calls

Which server to call

When making a call to the Visma Bouwsoft API, we always call the server that we get back from the authentication server when we get a new Accesstoken

For instance:
https://authenticationserver.bouwsoft.be/api/v1/Authorize/AccessToken
(where authenticationserver is one of the available authenticationservers
See https://support.bouwsoft.be/manual/api/?page=connection)

with the following HeaderParameters

Parameter name Type Description
Clientnr Integer Clientnr of the Visma Bouwsoft client
RefreshToken String RefreshToken received from the Visma Bouwsoft activation system

The answer we receive is in JSON format and contains

Parameter name Type Description
Accesstoken String AccessToken you need to use the Visma Bouwsoft API
ServerIP String The IP address of the server you need to contact to access the data for this client
ServerName String The name of the server you need to contact to access the data for this client (referenced below as myserver)
Layout String A = Archisoft, B = Bouwsoft, G = Groensoft
ValidUntil String The time until which the current Accesstoken will remain valid

Example:
{
  "AccessToken": "btffWxfAOOzSfPDVtfzRqkGkfPtPVIfUfPkUzbjjkIAfmlDUrn",
  "ServerIP": "95.138.166.117",
  "ServerName": "Osiris.bouwsoft.be",
  "Layout": "B",
  "ValidUntil": "2017–09–05T15:01Z"
}

Calling the API

API Calls

Methods
v1_DELETE_ActualCostMachines v1_GET_Employees v1_POST_LedgerNumbers
v1_DELETE_ActualCostProducts v1_GET_EmployeeTasks v1_POST_MachineGroups
v1_DELETE_ActualCostTimeWorked v1_GET_EmploymentStatuses v1_POST_MachineLists
v1_DELETE_AddressContacts v1_GET_HourGroups v1_POST_Machines
v1_DELETE_Addresses v1_GET_HourLists v1_POST_MaintenanceSheet
v1_DELETE_AddressGroups v1_GET_Hours v1_POST_OrderCommissions
v1_DELETE_AssignmentLabor v1_GET_ItemGroups v1_POST_OrderCosts
v1_DELETE_AssignmentMachines v1_GET_ItemLists v1_POST_OrderDiscounts
v1_DELETE_AssignmentProducts v1_GET_Items v1_POST_OrderGroups
v1_DELETE_Assignments v1_GET_Jobs v1_POST_OrderLines
v1_DELETE_CostCalculation v1_GET_Languages v1_POST_OrderMargins
v1_DELETE_CostCalculationVariables v1_GET_LedgerNumbers v1_POST_Orders
v1_DELETE_Devices v1_GET_LoanedMachines v1_POST_OrderVariables
v1_DELETE_Earthworks v1_GET_MachineGroups v1_POST_Payments
v1_DELETE_Earthworksdetail v1_GET_MachineLists v1_POST_ProductAlternativeUnits
v1_DELETE_EmployeeGroups v1_GET_Machines v1_POST_ProductGroups
v1_DELETE_Employees v1_GET_MaintenanceSheet v1_POST_ProductLists
v1_DELETE_HourGroups v1_GET_OrderApplications v1_POST_Products
v1_DELETE_HourLists v1_GET_OrderCommissionBeneficiaries v1_POST_ProjectAddresses
v1_DELETE_ItemGroups v1_GET_OrderCommissions v1_POST_ProjectContacts
v1_DELETE_ItemLists v1_GET_OrderCosts v1_POST_ProjectGroups
v1_DELETE_Items v1_GET_OrderDiscounts v1_POST_ProjectLists
v1_DELETE_Jobs v1_GET_OrderGroups v1_POST_Projects
v1_DELETE_LedgerNumbers v1_GET_OrderLineGroups v1_POST_PurchaseInvoiceProjects
v1_DELETE_MachineGroups v1_GET_OrderLines v1_POST_PurchaseInvoices
v1_DELETE_MachineLists v1_GET_OrderMarginNrs v1_POST_PurchaseOrders
v1_DELETE_Machines v1_GET_OrderMargins v1_POST_QuantityCalculation
v1_DELETE_MaintenanceSheet v1_GET_Orders v1_POST_SalesInvoices
v1_DELETE_OrderCommissions v1_GET_OrderTypes v1_POST_Salutations
v1_DELETE_OrderCosts v1_GET_OrderVariables v1_POST_VATCodes
v1_DELETE_OrderDiscounts v1_GET_Payments v1_PUT_ActualCostMachines
v1_DELETE_OrderGroups v1_GET_PhotoSheetDetails v1_PUT_ActualCostProducts
v1_DELETE_OrderLines v1_GET_PhotoSheets v1_PUT_ActualCostTimeWorked
v1_DELETE_OrderMargins v1_GET_ProductAlternativeUnits v1_PUT_AddressContacts
v1_DELETE_Orders v1_GET_ProductGroups v1_PUT_Addresses
v1_DELETE_OrderVariables v1_GET_ProductLists v1_PUT_AssignmentDevices
v1_DELETE_Payments v1_GET_Products v1_PUT_AssignmentLabor
v1_DELETE_ProductAlternativeUnits v1_GET_Productstock v1_PUT_AssignmentMachines
v1_DELETE_ProductGroups v1_GET_ProjectAddresses v1_PUT_AssignmentProducts
v1_DELETE_ProductLists v1_GET_ProjectContacts v1_PUT_Assignments
v1_DELETE_Products v1_GET_ProjectGroups v1_PUT_CostCalculation
v1_DELETE_ProjectAddresses v1_GET_ProjectLists v1_PUT_CostCalculationVariables
v1_DELETE_ProjectContacts v1_GET_ProjectPhases v1_PUT_Devices
v1_DELETE_ProjectGroups v1_GET_Projects v1_PUT_Earthworks
v1_DELETE_ProjectLists v1_GET_ProjectStaff v1_PUT_Earthworksdetail
v1_DELETE_Projects v1_GET_PurchaseInvoiceProjects v1_PUT_EmployeeGroups
v1_DELETE_PurchaseInvoiceProjects v1_GET_PurchaseInvoices v1_PUT_Employees
v1_DELETE_PurchaseInvoices v1_GET_PurchaseOrders v1_PUT_HourGroups
v1_DELETE_QuantityCalculation v1_GET_QuantityCalculation v1_PUT_HourLists
v1_DELETE_Salutations v1_GET_SalesDocuments v1_PUT_Hours
v1_DELETE_VATCodes v1_GET_SalesInvoices v1_PUT_ItemGroups
v1_GET_Absences v1_GET_Salutations v1_PUT_ItemLists
v1_GET_ActualCostItems v1_GET_Settings v1_PUT_Items
v1_GET_ActualCostMachines v1_GET_Todos v1_PUT_Jobs
v1_GET_ActualCostProducts v1_GET_TrainingTypes v1_PUT_LedgerNumbers
v1_GET_ActualCostTimeWorked v1_GET_Units v1_PUT_MachineLists
v1_GET_AddressContacts v1_GET_VATCodes v1_PUT_Machines
v1_GET_Addresses v1_GET_WageCategories v1_PUT_MaintenanceSheet
v1_GET_AddressGroups v1_GET_WorkingDocumentData v1_PUT_OrderCommissions
v1_GET_AssignmentDevices v1_GET_ZipCodes v1_PUT_OrderCosts
v1_GET_AssignmentLabor v1_POST_ActualCostMachines v1_PUT_OrderDiscounts
v1_GET_AssignmentMachines v1_POST_ActualCostProducts v1_PUT_OrderGroups
v1_GET_AssignmentProducts v1_POST_ActualCostTimeWorked v1_PUT_OrderLines
v1_GET_Assignments v1_POST_AddressContacts v1_PUT_OrderMargins
v1_GET_CheckIBAN v1_POST_Addresses v1_PUT_Orders
v1_GET_CheckVAT v1_POST_AddressGroups v1_PUT_OrderVariables
v1_GET_CivilStatuses v1_POST_AssignmentLabor v1_PUT_Payments
v1_GET_CodeTranslations v1_POST_AssignmentMachines v1_PUT_ProductAlternativeUnits
v1_GET_CompanyDetails v1_POST_AssignmentProducts v1_PUT_ProductLists
v1_GET_ContractTypes v1_POST_Assignments v1_PUT_Products
v1_GET_CostCalculation v1_POST_CostCalculation v1_PUT_ProductStock
v1_GET_CostCalculationPages v1_POST_CostCalculationVariables v1_PUT_ProjectAddresses
v1_GET_CostCalculationTypes v1_POST_Devices v1_PUT_ProjectContacts
v1_GET_CostCalculationVariables v1_POST_Earthworks v1_PUT_ProjectPhases
v1_GET_CountryCodes v1_POST_Earthworksdetail v1_PUT_Projects
v1_GET_Crews v1_POST_EmployeeGroups v1_PUT_PurchaseInvoiceProjects
v1_GET_Devices v1_POST_Employees v1_PUT_PurchaseInvoices
v1_GET_DocumentTypes v1_POST_HourGroups v1_PUT_PurchaseOrders
v1_GET_Earthworks v1_POST_HourLists v1_PUT_QuantityCalculation
v1_GET_Earthworksdetail v1_POST_ItemGroups v1_PUT_SalesInvoices
v1_GET_EmployeeFunctions v1_POST_ItemLists v1_PUT_Settings
v1_GET_EmployeeGroups v1_POST_Jobs v1_PUT_VATCodes

The Visma Bouwsoft API gets called with the following (possible) Parameters

HeaderParameters

Parameter name Type Description
Accesstoken String AccessToken received from the Visma Bouwsoft activation system
Clientnr Integer Clientnr of the Visma Bouwsoft client

PathParameters

/ApiMethodName/{id}
If you want to get the data for one specific item, you call the API with the id of the item you want to receive
For instance:
https://myserver.bouwsoft.be/api/v1/Addresses/167046

QueryParameters

If you want to modify the list of data you want to receive, you can use the following parameters

Parameter name Type Description
columns String The names of the fields you want in the result set ( seperated by | )
filter String The filter you will use on the list
limit Integer The maximum number of lines you want to see in the result set
nextid Integer The id of the item we want as start of the result set. This parameter is incompatible with offset
offset Integer The offset of the displayed list compared to the start of the result set. This parameter is incompatible with nexid
sort String The field names you will use to sort the list ( seperated by | , use -fieldname for descending )
distinct Boolean Set this field to true if you want to do a distinct select on the selected columns

PS:
Only the columns parameter can be used if the API call was made with a PathParameter

Filtering data, sorting data and selecting columns

The filter query parameter will be used to filter the result.
Multiple filters are seperated by ‘and’ or ‘or’.
Different operators can be used for each column.
If we use a value as the parameter for the filter instead of a comparison (for instance: https://myserver.bouwsoft.be/api/v1/Projects/?filter=201500575 ), the api will look across all fields of the same type (text fields in case of text and number fields in case of a passed number)

If we want to filter data it works as follows :

https://myserver.bouwsoft.be/api/v1/Projects/?filter=pnr%20gt%20201500575
Through this call we will get all projects with a pnr greater than 201500575
The filter is URL Encoded (%20 is a space)

You can use the following operators in a filter

Operator Description
gt Greater than
ge Greater than or equal to
eq equal to
lt smaller than
le smaller than or equal to
ne not equal to
has contains

Sorting works as follows:
https://ra.bouwsoft.be/api/v1/Projects/?filter=pnr%20gt%20201500575&sort=zipcode%7Cname
This command will get all projects with a number greater than 20150575 and sort the sort by zipcode and name
The filter and sort are URL Encoded (%20 is a space and %7C is a | )

sort ascending: sort=columname
sort descending: sort=-columnname

If we only want certain columns in the result we can do it the following way:

https://ra.bouwsoft.be/api/v1/Projects/?filter=pnr%20gt%20201500575&sort=zipcode%7Cname&columns=pnr%7Cname%7Caddress%7Czipcode%7Ccity%7Cts_lastupdate

Here we filter for the projects with pnr greater than 201500575, sort it on zipcode and name and request only the following columns in the output: Name, Address, zipode, city, ts_lastupdate

HTTP Response Codes

Code Description
200 OK Successful response for GET and PUT (Update/Replace) requests.
201 Created Successful response for POST (Create) requests.
204 No Content Successful response for DELETE requests.
400 Bad Request Failure response to a request with a malformed body.
401 Unauthorized Failure response for missing or invalid authentication credentials.
404 Not Found Failure response because the requested resource is invalid.
405 Method Not Allowed This Resource does not support this method
500 Internal Server Error No Response received from this call
501 Not Implemented This Resource does not support this method
503 Service Unavailable The server is temporarily unable to service your request

Examples of queryparameters

columns

The names of the fields you want in the result set (seperated by |) . No single quotes are needed.
For instance GET_Addresses.
With queryparameters
* columns = id|clientnr|name
* limit = 3
Result:
{
  "Content-Range": "0–2/*",
  "NextId": "167079",
  "Records": [
    {
      "id": 167070,
      "clientnr": 20170058,
      "name": ""
    },
    {
      "id": 167071,
      "clientnr": 20170059,
      "name": ""
    },
    {
      "id": 167078,
      "clientnr": 20170064,
      "name": ""
    }
  ]
}

filter

The filter you will use on the list.

For instance GET_Addresses With queryparameters
* filter = name has ‘neorej’ and zipcode has ‘8730’
Result:
{
  "Content-Range": "0–0/1",
  "Records": [
    {
      "id": 167090,
      "clientnr": 20170076,
      "suppliernr": 0,
      "salutation": "Dhr.",
      "name": "Stpilf Neorej",
      "address": "Hoornstraat 9",
      "countrycode": "BE",
      "zipcode": "8730",
      "city": "Beernem",
      "state": "West-Vlaanderen",
      "telephone1": "",
      "telephone2": "",
      "fax": "",
      "gsm": "+32 (0) 484 23 79 29",
      "email": "",
      "vatnr": "",
      "vatregistered": true,
      "date_created": "2017–09–11",
      "ts_lastupdate": "2017–09–11 12:31:28"
    }
  ]
}

For instance GET_LedgerNumbers
With queryparameters
* filter = ‘heftruck’
Result:
{
  "Content-Range": "0–0/1",
  "Records": [
    {
      "id": 1298,
      "nr": 371,
      "description": "Afschrijving Heftruck"
    }
  ]
}

limit

The maximum number of records you want to see in the result set. Default is 200, max is 500. Higher numbers will result in slower respons times.
For instance GET_LedgerNumbers
With queryparameters
* limit = 3
Result:
{
  "Content-Range": "0–2/*",
  "NextId": "190",
  "Records": [
    {
      "id": 26,
      "nr": 1,
      "description": "Eigen vermogen"
    },
    {
      "id": 59,
      "nr": 2,
      "description": "Oprichtingsk., vaste activa, vord. > 1 j"
    },
    {
      "id": 164,
      "nr": 3,
      "description": "Voorraden en bestellingen in uitvoering"
    }
  ]
}

nextid

The id of the item we want as start of the result set. This parameter is incompatible with offset.
For instance GET_LedgerNumbers
With queryparameters
* nextid = 190
* limit = 3
Result:
{
  "Content-Range": "3–5/1297",
  "NextId": "734",
  "Records": [
    {
      "id": 190,
      "nr": 4,
      "description": "Vorderingen en schulden < 1 jaar"
    },
    {
      "id": 341,
      "nr": 5,
      "description": "Geldbeleggingen en liq. midd."
    },
    {
      "id": 368,
      "nr": 6,
      "description": "Kostenrekeningen"
    }
  ]
}

offset

The offset of the displayed list compared to the start of the result set. This parameter is incompatible with nexid.
For instance GET_LedgerNumbers
With queryparameters
* offset = 3
* limit = 3
Result:
{
  "Content-Range": "3–5/*",
  "NextId": "734",
  "Records": [
    {
      "id": 190,
      "nr": 4,
      "description": "Vorderingen en schulden < 1 jaar"
    },
    {
      "id": 341,
      "nr": 5,
      "description": "Geldbeleggingen en liq. midd."
    },
    {
      "id": 368,
      "nr": 6,
      "description": "Kostenrekeningen"
    }
  ]
}

sort

The field names you will use to sort the list ( seperated by | , use -fieldname for descending ).
For instance GET_OrderLines
With queryparameters
* sort = orderid|linenr
* nextid = 141
* limit = 3
Result:
{
  "Content-Range": "101–103/43612",
  "NextId": "144",
  "Records": [
    {
      "id": 141,
      "orderid": 22,
      "linenr": 1,
      "group": "Général 1",
      "nr1": "11",
      "nr2": "",
      "description": "une nouvelle poste",
      "unit1": "5 l",
      "unit2": "",
      "quantity1": 80,
      "quantity2": 1,
      "quantity3": 1,
      "quantity4": 1,
      "quantity_total": 80,
      "price_unit": 30.460000000000001,
      "price_total": 2436.800000000000182,
      "vatcode": "6",
      "vatpercent": 6,
      "vatcocontractor": false,
      "ledger": 70000
    },
    {
      "id": 142,
      "orderid": 22,
      "linenr": 2,
      "group": "Général 1",
      "nr1": "11",
      "nr2": "",
      "description": "une nouvelle poste",
      "unit1": "5 l",
      "unit2": "",
      "quantity1": 90,
      "quantity2": 1,
      "quantity3": 1,
      "quantity4": 1,
      "quantity_total": 90,
      "price_unit": 30.460000000000001,
      "price_total": 2741.400000000000091,
      "vatcode": "6",
      "vatpercent": 6,
      "vatcocontractor": false,
      "ledger": 70000
    },
    {
      "id": 143,
      "orderid": 22,
      "linenr": 3,
      "group": "Général 1",
      "nr1": "11",
      "nr2": "",
      "description": "une nouvelle poste",
      "unit1": "5 l",
      "unit2": "",
      "quantity1": 36,
      "quantity2": 1,
      "quantity3": 1,
      "quantity4": 1,
      "quantity_total": 36,
      "price_unit": 30.460000000000001,
      "price_total": 1096.559999999999945,
      "vatcode": "6",
      "vatpercent": 6,
      "vatcocontractor": false,
      "ledger": 70000
    }
  ]
}

distinct

Set this field to true if you want to do a distinct select on the selected columns.
For instance GET_Products
With queryparameters
* sort = list
* offset = 12
* limit = 3
* columns = list
* distinct = true Result:
{
  "Content-Range": "12–14/*",
  "Records": [
    {
      "list": "ART GALLERY"
    },
    {
      "list": "ARTIKELLIJST DECOVAN"
    },
    {
      "list": "ASEA BROWN BOVERI"
    }
  ]
}


Response Codes

200 OK
201 CREATED
204 NO CONTENT
400 BAD REQUEST
    columns
    filter
       General
       Field Type Specific
          BOOLEAN
          CURRENCY
          CURRENCYHD
          DATE
          INTEGER
          TEXT
    limit
    nextid
    offset
    sort
401 UNAUTHORIZED
404 NOT FOUND
405 METHOD NOT ALLOWED
501 NOT IMPLEMENTED
503 SERVICE UNAVAILABLE

200 OK

Successful response for GET and POST requests.

The reponse is the data you just asked for in JSON format
for instance:
answer to https://myserver.bouwsoft.be/api/v1/Addresses with a queryparameter limit that has a value of 2

{
  "Content-Range": "0–1/*",
  "NextId": "42443",
  "Records": [
    {
      "id": 11342,
      "clientnr": 20160049,
      "suppliernr": 0,
      "salutation": "SPRL",
      "name": "\"CONSTRUCTION\" SPRL",
      "address": "Rue Albert Ier 11",
      "countrycode": "BE",
      "zipcode": "5500",
      "city": "Dinant",
      "state": "Namur",
      "telephone1": "",
      "telephone2": "",
      "fax": "",
      "gsm": "",
      "email": "",
      "vatnr": "BE 0111.111.111",
      "vatregistered": true,
      "date_created": "2013–10–21",
      "ts_lastupdate": "2017–08–17 10:08:12"
    },
    {
      "id": 6424,
      "clientnr": 20160048,
      "suppliernr": 0,
      "salutation": "",
      "name": "’t Bouwbedrijf",
      "address": "Verboekt 17",
      "countrycode": "BE",
      "zipcode": "3980",
      "city": "Tessenderlo",
      "state": "Limburg",
      "telephone1": "012 34 56 78",
      "telephone2": "",
      "fax": "+32 (0) 12 34 56 79",
      "gsm": "",
      "email": "",
      "vatnr": "BE 0111.111.112",
      "vatregistered": true,
      "date_created": "2013–10–21",
      "ts_lastupdate": "2017–02–23 10:02:29"
    }
  ]
}

201 CREATED

Successful response for PUT requests.

The reponse is the data you just inserted in JSON format with the creation date and a timestamp
for instance:
answer to https://myserver.bouwsoft.be/api/v1/Addresses with a queryparameter colums that has the following value
name=’SpikeAPI‘,address=’Groothof 23’,countrycode=’BE‘,zipcode=’8200’,city=’brugge’

{
  "RecordChanges": [
    {
      "id": 167043,
      "clientnr": 0,
      "suppliernr": 0,
      "salutation": "",
      "name": "SpikeAPI",
      "address": "Groothof 23",
      "countrycode": "BE",
      "zipcode": "8200",
      "city": "Brugge",
      "state": "West-vlaanderen",
      "telephone1": "",
      "telephone2": "",
      "fax": "",
      "gsm": "",
      "email": "",
      "vatnr": "",
      "vatregistered": true,
      "date_created": "2017–09–05",
      "ts_lastupdate": "2017–09–05 08:44:27"
    }
  ]
}

204 NO CONTENT

Successful response for DELETE requests.

The reponse is empty since the data has just been deleted.
Therefore the only answer to a delete request is the status code.

PS:
If you try to delete something that does not exist, you will also get a 204 NO CONTENT
The Visma Bouwsoft API does not consider it an error if you try to delete something that does not exist
The end result will always be that the data does indeed not exist after the API Call

400 BAD REQUEST

If there is something wrong with the request, the response status and code is 400

Examples of bad requests:

columns


General

columns: name
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Column not found: name”}

columns: address_id=27332
{“Code”: “400”,“Message”: “Bad Request”,“Description”: “Can’t update address_id”}

POST on a record that is supposed to be connected to another record where corresponding id does not exist
bv. POST op AddressContacts met
columns: contact_name=’SpikeAPI2’,address_id=12
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“address_id must exist”}

Field type specific

BOOLEAN

columns: senttoaccountingsoftware=2
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid booleanvalue in Column senttoaccountingsoftware: 2 (True or False expected)”}

CURRENCY

columns: cashdiscount_amount=’a’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid Currencyvalue in Column cashdiscount_amount: ‘a’”}

CURRENCYHD

columns: price_cost=’Kraan + Operator K31/35 Forfait 4u’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid CurrencyHDvalue in Column price_cost: ‘Kraan + Operator K31\/35 Forfait 4u’”}

DATE

columns: purchasedate=’a’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid Datevalue in Column purchasedate: a”}

DOUBLE

columns: quantity=’a’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid Doublevalue in Column quantity: ‘a’”}

INTEGER

columns: constructionyear=’a’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid Integervalue in Column constructionyear: ‘a’”}

TEXT

columns: license_plate=0
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid Stringvalue in Column license_plate: 0”}

filter


General

any filter on a request with an id
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“filter found on a request for 1 single id”}

filter: name has ‘gino’ and
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Filter ends with AND”}

filter: name has ‘gino’ or
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Filter ends with OR”}

filter: contactname has ‘Gino’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Unknown field: ‘contactname’”}

filter: contact_name contact_email has ‘gino’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“2 fields in 1 filterexpression are not allowed”}

filter: contact_name has Gino’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid number of quotes in filter”}

filter: (contact_name has ‘Gino’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Every opening bracket needs a closing bracket”}

filter: (contact_name has ‘gino’) ( or contact_email has ‘gino’)
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid position for an opening bracket”}

filter: (contact_name has ‘gino’ or ) ( contact_email has ‘gino’)
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid position for a closing bracket”}

filter: 5
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Value found without Field or Operator in this filterexpression”}

filter: eq ‘5’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Operator eq found without a Field”}

filter: address_id not eq 400
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“‘not eq’ is not a valid operator”}

Field type specific

BOOLEAN

filter: vatregistered has false
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“EQ and NE are the only allowed operators in a filter on a boolean”}

filter: vatregistered eq null
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“NULL value not allowed in a filter on a boolean”}

filter: vatregistered eq ‘BE’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“‘BE’ is not a boolean”}

DATE

filter: ts_lastupdate has ‘2017–07–10 15:38:23’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“‘has’/’has not’ operator not allowed in a filter on a date”}

filter: ts_lastupdate eq NULL eq NULL
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“NULL value not allowed in a filter on this datefield”}

filter: ts_lastupdate lt NULL
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“EQ and NE are the only allowed operators to check on NULL”}

filter: date_created eq ‘test’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“‘test’ is not a date”}

INTEGER

filter: address_id has ‘5’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“‘has’/’has not’ operator not allowed in a filter on an integer”}

filter: address_id eq NULL
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“NULL value not allowed in a filter on an integer”}

filter: address_id eq ‘0’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“‘0’ is not an integer”}

TEXT

filter: name eq NULL
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“NULL value not allowed in a filter on a textfield”}

filter: contact_name has 5
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“5 is not a textvalue”}

limit


a limit on a request with an id
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“limit found on a request for 1 single id”}

limit: ‘test’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Limit is not valid: ‘test’”}

limit: 0
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Requested limit is smaller than 1”}

limit: 1000
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Requested limit is larger than 500”}

nextid


a nextid on a request with an id
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“nextid found on a request for 1 single id”}

nextid: ‘test’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Invalid NextId”}

offset


any sort on a request with an id
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“sort found on a request for 1 single id”}

an offset on a request with an id
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“offset found on a request for 1 single id”}

offset: ‘test’
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Offset is not valid: ‘test’”}

offset: –10
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Requested offset is negative”}

offset: 1 and nextid: 29
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“offset can’t be combined with nextid”}

sort


sort: zipcode|name|planet
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Sort Field not found: planet”}

sort: zipcode|name|zipcode
{“Code”:“400”,“Message”:“Bad Request”,“Description”:“Sort Field defined twice: zipcode”}

401 UNAUTHORIZED

Failure response for missing or invalid authentication credentials.

If you forget to send the Authentication, the response status and code is 401
(401 Unauthorized)

The possible responses in this case are:
{“Code”:“401”,“Message”:“Unauthorized”,“Description”:“No AccessToken found in request”}
{“Code”:“401”,“Message”:“Unauthorized”,“Description”:“No ClientNr found in request”}
{“Code”: “401”,“Message”: “Unauthorized”,“Description”: “This accesstoken is not valid in combination with the given clientnr”}
{“Code”: “401”,“Message”: “Unauthorized”,“Description”: “This accesstoken is expired and will be removed shortly”}

404 NOT FOUND

Failure response because the requested resource is invalid.

If there is no record that has the requested id the HTTP response status and code is 404
(404 Not found)
example: https://myserver/api/v1/Addresses/12
{“Code”:“404”,“Message”:“Not Found”,“Description”:“Id not found: 12”}

If there is no record that has the requested nextid the HTTP response status and code is 404
(404 Not found)
example: https://myserver/api/v1/Addresses/ and the queryparameter nextid is 12
{“Code”:“404”,“Message”:“Not Found”,“Description”:“NextId not found: 12”}

Another possible reason is that you are using http instead of https

When using http, you get 404 with the following reply (in http)

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /api/v1/Machines was not found on this server.</p>
<hr>
<address>Apache/2.4.18 (Ubuntu) Server at ra.bouwsoft.be Port 80</address>
</body></html>

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">  
<html><head>  
<title>405 Method Not Allowed</title>  
</head><body>  
<h1>Method Not Allowed</h1>  
<p>The requested method PUT is not allowed for the URL /api/v1/Projects/558.</p>  
<hr>   
<address>Apache/2.4.18 (Ubuntu) Server at ra.bouwsoft.be Port 80</address>  
</body></html>  

405 METHOD NOT ALLOWED

You are trying to use a method that has not been implemented (the HTTP PATCH method)
This Resource does not support this method

Visma Bouwsoft API does not support PATCH. If you try to use it, you get the 405 Method not allowed message below (JSON)
{“Code”:“405”,“Message”:“Method Not Allowed”,“Description”:“This Resource does not support this method: PATCH”}

PS:
Instead of using PATCH, the Visma Bouwsoft API works with the PUT method to update records
If you want to PATCH the data, you use the PUT method in combination with the QueryParameter columns
For instance:
https://myserver.bouwsoft.be/api/v1/Addresses/165982
with the queryparameter columns that has the value: city=’Oostende‘,salutation=’Mrs.’

500 Internal Server Error

No Response received from this call

Visma Bouwsoft API was not able to answer this call
For instance:
https://ra.bouwsoft.be/api/v1/Addressen
If you try this, you get the 501 Not Implemented message below
{“Code”:“501”,“Message”:“Method Not Implemented”,“Description”:“This Method is not implemented: api\/v1\/Addressen”}

501 NOT IMPLEMENTED

This Resource does not support this method

Visma Bouwsoft API does not have this method available
For instance:
https://ra.bouwsoft.be/api/v1/Addressen
If you try this, you get the 501 Not Implemented message below
{“Code”:“501”,“Message”:“Method Not Implemented”,“Description”:“This Method is not implemented: api\/v1\/Addressen”}

503 SERVICE UNAVAILABLE

The server is temporarily unable to service your request due to maintenance downtime or capacity problems.
Please try again later.
This usually lasts only a couple of seconds.