OData
Das Open Data Protocol (OData) ist ein Webservice-Protokoll für den Datenaustausch. Es unterstützt gefilterte Abfragen, Metadaten-Reflection und Datenmanipulation (d. h. Einfügen, Ändern, Löschen).
Time cockpit bietet einen OData-Endpunkt, der Modell und Daten einschließlich individueller Konfigurationen des Datenmodells bereitstellt. OData kann von Client-Anwendungen (z. B. PowerBI, Excel, LINQPad) und aus verschiedenen Programmiersprachen (z. B. C#, TypeScript, Java) genutzt werden.
Service-Endpunkt
Die Adresse unseres OData-Endpunkts ist https://api.timecockpit.com/odata.
Authentifizierung
Um den OData-Endpunkt zu verwenden, müssen Sie sich zuerst beim Dienst authentifizieren. Wie Sie sich authentifizieren, lesen Sie unter Authentifizierung.
Aktuelle Einschränkungen
- OData wird nur bis Version 3.0 unterstützt.
- Der numerische Operator
Modulo (%)wird nicht unterstützt. - Die Entity-Set-Funktion
Countwird nicht unterstützt. - Nur die Filterfunktionen
length,concat,day,monthundyearwerden unterstützt. Andere Funktionen (z. B.substringof,startswith) werden nicht unterstützt.
C#-CRUD-Beispiel
var timeCockpitBaseUri = "https://api.timecockpit.com";
var timeCockpitDataApiPAT = "YOUR_PAT";
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(timeCockpitBaseUri);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue($"Bearer", timeCockpitDataApiPAT);
// ## CREATE
var guid = new Guid("af0725c0-cf12-43da-8688-3dcced935909");
var newTask = new
{
APP_TaskUuid = guid,
APP_Code = "IMPL",
USR_Title = "Implementation",
APP_ProjectUuid = "79b82123-596e-4abe-bdf2-38a8c279f589"
};
var newTaskContent = new StringContent(JsonConvert.SerializeObject(newTask), Encoding.UTF8, "application/json");
var result = await httpClient.PostAsync($"https://api.timecockpit.com/odata/APP_Task", newTaskContent);
// ## READ
result = await httpClient.GetAsync($"https://api.timecockpit.com/odata/APP_Task()?$filter=APP_TaskUuid eq guid'{guid}'");
var json = JObject.Parse(result.Content.ReadAsStringAsync().Result);
// ## READ ALL
result = await httpClient.GetAsync("https://api.timecockpit.com/odata/APP_Task()");
json = JObject.Parse(result.Content.ReadAsStringAsync().Result);
// ## UPDATE
var taskData = new
{
APP_Description = "Development"
};
var updatedJson = new StringContent(JsonConvert.SerializeObject(taskData), Encoding.UTF8, "application/json");
result = await httpClient.PatchAsync($"https://api.timecockpit.com/odata/APP_Task(guid'{guid}')", updatedJson);
// ## DELETE
result = await httpClient.DeleteAsync($"https://api.timecockpit.com/odata/APP_Task(guid'{guid}')");
}
Beispielabfrage: Alle Länder abrufen
Das folgende Beispiel zeigt, wie Sie alle Elemente des Entitätstyps APP_Country abfragen. Ein HTTP GET auf das entsprechende Entity Set ergibt eine ungefilterte Abfrage. Das Beispiel verwendet Token-Authentifizierung, und die Antwort enthält eine Sammlung von vier Ländern. Beachten Sie, dass das Ergebnis als JSON kodiert ist und einige OData-spezifische Informationen enthält.
Anfrage
GET https://api.timecockpit.com/odata/APP_Country HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Host: api.timecockpit.com
Antwort
HTTP/1.1 200 OK
Cache-Control: no-store, must-revalidate, no-cache
Pragma: no-cache
Content-Length: 600
Content-Type: application/json; odata=minimalmetadata; streaming=true; charset=utf-8
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=244116e25a72155d832c22601a40ae87af7d9c2cb18a99a181efeffc297cbc64;Path=/;Domain=api.timecockpit.com
Date: Wed, 30 Apr 2014 14:19:29 GMT
{
"odata.metadata":"https://api.timecockpit.com/odata/$metadata#APP_Country","value":[
{
"APP_CountryUuid":"94bac4d3-fdc3-4ef7-ab6b-3123a6f361e0","APP_CountryName":"Switzerland","APP_IsoCode":"CH"
},{
"APP_CountryUuid":"e3d0782e-b929-4edc-826b-3d1f79d45115","APP_CountryName":"Germany","APP_IsoCode":"DE"
},{
"APP_CountryUuid":"89e40635-268f-436a-8388-516f2ccb1c9e","APP_CountryName":"Austria","APP_IsoCode":"AT"
},{
"APP_CountryUuid":"35a34340-2533-4925-b445-ab243a1115d0","APP_CountryName":"United Kingdom","APP_IsoCode":"GB"
}
]
}
Beispielabfrage: Gefilterte Zeitbuchungen
Dieses Beispiel wählt die 101. Zeitbuchung für österreichische Kunden aus. Es enthält den zugeordneten Benutzer, das Projekt und den Kunden.
Anfrage-URI (mit Zeilenumbrüchen zur besseren Lesbarkeit)
https://api.timecockpit.com/odata/APP_Timesheet()
?$filter=APP_Project/APP_Customer/APP_Country/APP_CountryName eq 'Austria'
&$orderby=APP_BeginTime
&$skip=100
&$top=1
&$expand=APP_UserDetail,APP_Project/APP_Customer
Entsprechende TCQL-Abfrage
From A In APP_Timesheet.Include('APP_UserDetail').Include('APP_Project.APP_Customer')
Where (A.APP_Project.APP_Customer.APP_Country.APP_CountryName = "Austria")
Order By A.APP_BeginTime Asc
Skip 100
Take 1
Select A
Antwort-Body
{
"odata.metadata": "https://api.timecockpit.com/odata/$metadata#APP_Timesheet",
"value": [
{
"APP_UserDetail": {
"APP_UserDetailUuid": "58b4edf2-d161-4a3c-926a-d1163718d0fc",
"APP_DateOfJoining": "2013-01-01T00:00:00",
"APP_DateOfSeparation": null,
"APP_Firstname": "Tim",
"APP_HourlyRate": "25.00",
"APP_IsHidden": false,
"APP_Lastname": "Smith",
"APP_Username": "demo@timecockpit.com",
"APP_WeeklyHoursOfWork": "38.50",
"APP_Fullname": "Smith, Tim",
"APP_ReadOnlyUsername": "demo@timecockpit.com",
"APP_CultureInfoUuid": "c6b71cf0-2d96-46ba-b7e9-33d46c2b74d1",
"APP_DepartmentUuid": null,
"APP_LegalHolidayCalendarUuid": "65945ecf-bd8c-4008-adeb-959ba5b546d8"
},
"APP_Project": {
"APP_Customer": {
"APP_CustomerUuid": "6a8ff888-c830-471f-a322-01d27d0083f8",
"APP_Code": "FernandoArchitecture",
"APP_CommercialRegNumber": "FN999999x",
"APP_CompanyName": "Fernando Architecture Ltd",
"APP_ContactInfo": "Max Muster",
"APP_Email": "office@Fernando.com",
"APP_Fax": null,
"APP_HourlyRate": "67.00",
"APP_InvoiceFAO": null,
"APP_InvoicingRules": null,
"APP_Phone": "123 456 789",
"APP_Street": "Euro Plaza 99",
"APP_Town": "Home",
"APP_VatID": "XY999999",
"APP_ZipCode": "20100",
"APP_CountryUuid": "89e40635-268f-436a-8388-516f2ccb1c9e"
},
"APP_ProjectUuid": "fc4beca0-157b-4fbc-ac2e-d5d028562e66",
"APP_Billable": true,
"APP_Budget": null,
"APP_BudgetInHours": null,
"APP_Closed": false,
"APP_Code": "ProjectCons",
"APP_Description": "Project Consulting Time & Material",
"APP_EndDate": null,
"APP_ExternalProjectCode": "SAP123-456-789",
"APP_FixedPrice": false,
"APP_HourlyRate": "80.40",
"APP_InvoicingRules": "Monthly invoicing, we do not charge travelling time, ...",
"APP_ProjectName": "Project Consulting",
"APP_StartDate": "2013-01-01T00:00:00",
"APP_Fullname": "FernandoArchitecture.ProjectCons",
"APP_HourlyRateActual": "80.40",
"APP_HourlyRateCustomer": "67.00",
"APP_CustomerUuid": "6a8ff888-c830-471f-a322-01d27d0083f8"
},
"APP_TimesheetUuid": "63aca8f6-b31c-4334-bfa3-1efd318f2b1a",
"APP_BeginTime": "2013-05-23T13:15:00",
"APP_Description": "Project Consulting Time & Material",
"APP_EndTime": "2013-05-23T15:00:00",
"APP_HourlyRate": null,
"APP_HourlyRateBilled": "80.40",
"APP_IsDurationTimesheet": false,
"APP_JourneyDistance": null,
"APP_JourneyFrom": null,
"APP_JourneyTo": null,
"APP_Location": "Russia",
"APP_NoBilling": false,
"APP_BeginTimeActual": "2013-05-23T13:15:00",
"APP_Billable": true,
"APP_Billed": true,
"APP_CompanyNameActual": "Fernando Architecture Ltd",
"APP_DateActual": "2013-05-23T00:00:00",
"APP_DurationInDays": "0.2187499999999998",
"APP_DurationInHours": "1.7499999999999984",
"APP_EndTimeActual": "2013-05-23T15:00:00",
"APP_HourlyRateActual": "80.40",
"APP_HourlyRateProjectOrTask": "80.40",
"APP_ProjectCodeActual": "ProjectCons",
"APP_ProjectOrTaskIsBillable": true,
"APP_Revenue": "140.699999999999871360",
"APP_InvoiceUuid": "d776673b-99d7-48c9-9ef8-07a4608b9899",
"APP_JourneyMeansOfTransportUuid": null,
"APP_ProjectUuid": "fc4beca0-157b-4fbc-ac2e-d5d028562e66",
"APP_TaskUuid": null,
"APP_UserDetailUuid": "58b4edf2-d161-4a3c-926a-d1163718d0fc",
"APP_WorkingTimeWeightUuid": null
}
]
}
Beispieloperation: Ein neues Land einfügen
Mit TypeScript und JayData lässt sich einfach eine kleine Anwendung erstellen, die ein neues Land einfügt. Das zeigt, wie Sie unseren Dienst aus einer Client-Technologie nutzen, die nicht standardmäßig unterstützt wird. Der Service-Client wurde mit JaySvcUtil generiert und bietet typisierte Modellentitäten, Entity Sets und Abfrageoperationen, vergleichbar mit LINQ.
var data = new cofx.DataService({
name: "oData",
oDataServiceHost: "https://api.timecockpit.com/odata",
user: "demo@timecockpit.com",
password: "...",
maxDataServiceVersion: '3.0'
});
var country = new cofx.APP_Country({
APP_CountryName: "Ireland",
APP_IsoCode: "IE",
APP_CountryUuid: "00000000-0000-0000-0000-000000000000"
});
data.APP_Country.add(country);
data.saveChanges();
Eine HTTP-POST-Operation fügt neue Daten in das Entity Set APP_Country ein. Beachten Sie, dass viele der Header in der Anfrage optional sind und vom Webbrowser eingefügt wurden. Der Anfrage-Body enthält ein JSON-kodiertes Länderobjekt. Da die ID des Objekts (APP_CountryUuid) leer gelassen wird, legt der Dienst eine neue ID fest.
Anfrage-Header
POST https://api.timecockpit.com/odata/APP_Country HTTP/1.1
Accept: application/atomsvc+xml;q=0.8, application/json;odata=fullmetadata;q=0.7, application/json;q=0.5, */*;q=0.1
MaxDataServiceVersion: 3.0
DataServiceVersion: 3.0
Authorization: Basic bmljZTp0cnkgOik=
Content-Type: application/json;odata=verbose
Referer: http://localhost:20337/
Accept-Language: de-AT
Origin: http://localhost:20337
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: api.timecockpit.com
Content-Length: 105
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
Anfrage-Body
{
"APP_CountryUuid" : "00000000-0000-0000-0000-000000000000",
"APP_CountryName" : "Ireland",
"APP_IsoCode" : "IE"
}
Der Antwort-Body enthält das neue Objekt einschließlich Metadaten, die Header spiegeln das erfolgreiche Anlegen des Objekts wider. Beachten Sie, dass die eindeutige ID und die URL des Landes in der Antwort enthalten sind.
Antwort-Header
HTTP/1.1 201 Created
Content-Length: 529
Content-Type: application/json; odata=fullmetadata; charset=utf-8
Location: https://api.timecockpit.com/odata/APP_Country(guid'046ac6cf-1c55-493c-b6dd-65249fcf669e')
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://localhost:20337
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: DataServiceVersion
DataServiceVersion: 3.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=244116e25a72155d832c22601a40ae87af7d9c2cb18a99a181efeffc297cbc64;Path=/;Domain=api.timecockpit.com
Date: Wed, 30 Apr 2014 15:48:26 GMT
Antwort-Body
{
"odata.metadata" : "https://api.timecockpit.com/odata/$metadata#APP_Country/@Element",
"odata.type" : "cofx.APP_Country",
"odata.id" : "https://api.timecockpit.com/odata/APP_Country(guid'046ac6cf-1c55-493c-b6dd-65249fcf669e')",
"Customers@odata.navigationLinkUrl" : "https://api.timecockpit.com/odata/APP_Country(guid'046ac6cf-1c55-493c-b6dd-65249fcf669e')/Customers",
"APP_CountryUuid@odata.type" : "Edm.Guid",
"APP_CountryUuid" : "046ac6cf-1c55-493c-b6dd-65249fcf669e",
"APP_CountryName" : "Ireland",
"APP_IsoCode" : "IE"
}