Opret listeelementer med REST fra Power Automate
Endpoints, headers og body til at oprette og rette elementer med Send an HTTP request to SharePoint, feltformat for hver felttype og de fejl, SharePoint svarer med.
Create item klarer tekst, tal, datoer og valg. Når et felt ikke vil — managed metadata, flere personer, flere opslag — eller når jeg vil have fejlen i hånden i stedet for et rødt kryds, opretter jeg elementet med Send an HTTP request to SharePoint mod REST-API’et. Handlingen hører til SharePoint-connectoren og kræver ikke Premium. Det gør den generiske HTTP-handling.
Hyperlinkfelter og personfelter med StringId står for sig i Link- og personfelter på et listeelement med HTTP i Power Automate. Her er resten.
Endpoints#
POST https://[site]/_api/web/lists/getbytitle('[ListName]')/items
POST https://[site]/_api/web/lists/getbytitle('[ListName]')/items([ItemID])
GET https://[site]/_api/web/lists/getbytitle('[ListName]')/items([ItemID])
Den første opretter, den anden retter (med en X-HTTP-Method), den tredje henter.
Headers#
Opret:
1{
2 "Accept": "application/json;odata=verbose",
3 "Content-Type": "application/json;odata=verbose"
4}
Ret de felter, der står i body (MERGE):
1{
2 "Accept": "application/json;odata=verbose",
3 "Content-Type": "application/json;odata=verbose",
4 "X-HTTP-Method": "MERGE",
5 "IF-MATCH": "*"
6}
Erstat hele elementet (PUT):
1{
2 "Accept": "application/json;odata=verbose",
3 "Content-Type": "application/json;odata=verbose",
4 "X-HTTP-Method": "PUT",
5 "IF-MATCH": "*"
6}
X-HTTP-Method laver en POST om til MERGE, PUT eller DELETE. IF-MATCH: * betyder, at versionen er ligegyldig. Med en ETag i stedet for * afviser SharePoint ændringen, hvis nogen har rettet elementet imellemtiden.
Body#
Mindst:
1{
2 "__metadata": {
3 "type": "SP.Data.[ListName]ListItem"
4 },
5 "Title": "Item Title"
6}
Med flere felter:
1{
2 "__metadata": {
3 "type": "SP.Data.TasksListItem"
4 },
5 "Title": "Complete Documentation",
6 "AssignedToId": 42,
7 "DueDate": "2025-04-30",
8 "Status": "In Progress",
9 "Priority": "High"
10}
Fremgangsmåde#
1. Hent listens typenavn. Det skal stå i __metadata.type, og det er ikke altid det, listens navn får én til at gætte.
Site Address: [Your SharePoint site]
Method: GET
Uri: _api/web/lists/getbytitle('[ListName]')?$select=ListItemEntityTypeFullName
Headers:
{
"Accept": "application/json;odata=verbose"
}
1{
2 "d": {
3 "ListItemEntityTypeFullName": "SP.Data.TasksListItem"
4 }
5}
Initialize variable - varMetadataType
Value: body('Get_List_Metadata')?['d']?['ListItemEntityTypeFullName']
2. Læg værdierne i variabler. Så er body til at læse, og tomme værdier kan fanges, før kaldet laves.
varTitle: "Q1 2025 Review"
varAssignedToId: 42
varDueDate: "2025-03-31"
varStatus: "New"
varPriority: "High"
varDescription: "Quarterly review of all projects"
3. Opret elementet.
Site Address: [Your SharePoint site]
Method: POST
Uri: _api/web/lists/getbytitle('Tasks')/items
Headers:
{
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose"
}
Body:
{
"__metadata": {
"type": "@{variables('varMetadataType')}"
},
"Title": "@{variables('varTitle')}",
"AssignedToId": @{variables('varAssignedToId')},
"DueDate": "@{variables('varDueDate')}",
"Status": "@{variables('varStatus')}",
"Priority": "@{variables('varPriority')}",
"Description": "@{variables('varDescription')}"
}
Tekst og datoer står i anførselstegn, tal og ja/nej gør ikke. Datoer skrives ISO 8601: "2025-03-31".
4. Læs svaret (valgfrit). Et oprettet element giver status 201 og elementet tilbage.
Content: body('Create_Item_HTTP')
Schema:
{
"type": "object",
"properties": {
"d": {
"type": "object",
"properties": {
"Id": { "type": "integer" },
"Title": { "type": "string" },
"Created": { "type": "string" },
"Author": {
"type": "object",
"properties": {
"Title": { "type": "string" }
}
}
}
}
}
}
Item ID: body('Parse_JSON')?['d']?['Id']
Created Date: body('Parse_JSON')?['d']?['Created']
Author: body('Parse_JSON')?['d']?['Author']?['Title']
Felttyper#
Feltnavnet er altid det interne navn.
Tekst. En linje, flere linjer og rich text:
1"Title": "Project Alpha"
1"Description": "This is a detailed description\nwith line breaks"
1"RichDescription": "<div><strong>Bold text</strong> and <em>italic</em></div>"
Tal. Heltal, decimaltal, procent og valuta. Procent gemmes som en brøk: 0.75 er 75 %.
1"Quantity": 100
1"Price": 99.95
1"CompletionRate": 0.75
1"Budget": 50000.00
Dato og tid. Kun dato, dato med tid, og nu:
1"DueDate": "2025-03-31"
1"MeetingDateTime": "2025-03-31T14:30:00Z"
1"ProcessedDate": "@{utcNow()}"
Valg. Ét valg er bare teksten. Flere valg er en samling:
1"Status": "In Progress"
1"Categories": {
2 "__metadata": { "type": "Collection(Edm.String)" },
3 "results": ["High Priority", "Customer Facing"]
4}
Ja/nej:
1"IsActive": true,
2"IsArchived": false
Person. Feltnavnet får Id på, og værdien er brugerens id på webstedet. Én person:
1"AssignedToId": 42
eller
1"AssignedToStringId": "42"
Flere personer:
1"TeamMembersId": {
2 "__metadata": { "type": "Collection(Edm.Int32)" },
3 "results": [42, 57, 89]
4}
Id’et findes med ensureuser (se fejl 5 herunder), som også lægger brugeren på webstedet, hvis vedkommende ikke er der. Get user profile (V2) giver Entra-objekt-id’et, og det er ikke det samme tal.
Opslag. Samme mønster: feltnavn plus Id, og værdien er id’et på elementet i opslagslisten.
1"ProjectId": 15
1"RelatedProjectsId": {
2 "__metadata": { "type": "Collection(Edm.Int32)" },
3 "results": [15, 23, 47]
4}
Hyperlink:
1"Website": {
2 "__metadata": { "type": "SP.FieldUrlValue" },
3 "Description": "Company Website",
4 "Url": "https://example.com"
5}
Beregnede felter kan ikke sættes. SharePoint regner dem selv ud.
Managed metadata. WssId er -1 for et term, der ikke er brugt på webstedet før:
1"DepartmentId": {
2 "__metadata": { "type": "SP.Taxonomy.TaxonomyFieldValue" },
3 "Label": "IT Department",
4 "TermGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
5 "WssId": -1
6}
Ikke efterprøvet: flere kilder sætter objektet på feltets interne navn uden Id ("Department": {...}). Virker den ene ikke, er det den anden.
Fejlhåndtering#
To mønstre. Et try/catch med to scopes:
Scope: Try Create Item
Send HTTP request - Create item
Parse JSON response
Scope: Catch Error
Configure run after (on Try scope): has failed, has timed out
Compose - Error Details:
body('Create_item')?['error']?['message']
Send email - Notify admin
Create item - Log error to audit list
Eller en betingelse på statuskoden:
Send HTTP request - Create item
Condition: Status code equals 201 (Created)
If yes:
Parse response
Continue workflow
If no:
Log error
Send notification
Terminate flow
Betingelsen kræver, at HTTP-handlingen ikke stopper flowet ved fejl, altså Configure run after på det næste trin.
Fejl, SharePoint svarer med#
“The property ‘FieldName’ does not exist”. Forkert internt navn. Slå det op:
GET _api/web/lists/getbytitle('ListName')/fields?$filter=Title eq 'Display Name'
Navnet skelner mellem store og små bogstaver, og mellemrum står som _x0020_.
“Invalid JSON format”. Et komma for meget eller for lidt, et anførselstegn der ikke er lukket, eller et specialtegn i en variabel. Det hjælper at bygge body i en Compose først og se, hvad der faktisk bliver sendt.
“A value without a type name was found”. __metadata mangler eller har den forkerte type:
1{
2 "__metadata": {
3 "type": "SP.Data.TasksListItem"
4 }
5}
“The request ETag value does not match”. Elementet er ændret siden sidst. IF-MATCH: * ser bort fra det:
1Headers:
2{
3 "IF-MATCH": "*"
4}
“User cannot be found”. Brugeren er ikke på webstedet endnu. ensureuser lægger vedkommende der og giver id’et tilbage:
POST _api/web/ensureuser
Body: { "logonName": "user@domain.com" }
Mange elementer på én gang#
Flere oprettelser kan sendes i ét kald til $batch. Eksemplet her viser formen:
POST _api/$batch
Content-Type: multipart/mixed; boundary=batch_xxxxxxxx
--batch_xxxxxxxx
Content-Type: application/http
Content-Transfer-Encoding: binary
POST _api/web/lists/getbytitle('Tasks')/items
{"__metadata":{"type":"SP.Data.TasksListItem"},"Title":"Item 1"}
--batch_xxxxxxxx
Content-Type: application/http
POST _api/web/lists/getbytitle('Tasks')/items
{"__metadata":{"type":"SP.Data.TasksListItem"},"Title":"Item 2"}
--batch_xxxxxxxx--
Som det står, går det ikke igennem. Skriveoperationer skal ligge i et changeset, der er sin egen multipart/mixed-del med sin egen boundary inde i batchen, og hver indre forespørgsel skal have sine egne Content-Type- og Accept-headers og en tom linje før body. Alle adresser i batchen skal pege på samme websted. Et changeset er ikke en transaktion: fejler én oprettelse, bliver de andre stående. Microsofts eksempler står under Make batch requests with the REST APIs.
Mønstre#
Felter ud fra regler. En Switch på prioriteten sætter frist og ansvarlig, før elementet oprettes:
Switch: triggerOutputs()?['body/Priority']
Case "High":
Set varDueDate: addDays(utcNow(), 1)
Set varAssignedTo: variables('varManagerId')
Case "Medium":
Set varDueDate: addDays(utcNow(), 7)
Set varAssignedTo: variables('varTeamLeadId')
Case "Low":
Set varDueDate: addDays(utcNow(), 30)
Set varAssignedTo: variables('varTeamMemberId')
Create item via HTTP with conditional values
Skabeloner. JSON i et tekstfelt i en liste, hentet efter elementtype, parset og brugt som udgangspunkt for body.
1. Store templates in SharePoint list (JSON in text field)
2. Get template based on item type
3. Parse template JSON
4. Populate variables from template
5. Create item via HTTP
Rul tilbage. Fejler noget efter oprettelsen, slettes elementet igen:
Scope: Try
Create item via HTTP
Parse response - Store Item ID
Perform additional operations
Scope: Catch
Configure run after: has failed
Condition: Item was created
variables('varItemId') is not null
If yes:
DELETE _api/web/lists/getbytitle('Tasks')/items(@{variables('varItemId')})
DELETE sendes som POST med X-HTTP-Method: DELETE og IF-MATCH: *.
Prøv igen med stigende pause:
Do Until: Success or MaxRetries
Try create item
If fails:
Increment retry count
Delay: 2^retryCount seconds
Continue loop
If succeeds:
Break loop
HTTP-handlingen har også sin egen Retry policy under indstillingerne, som klarer 429 og 5xx uden en løkke.
Det der driller#
- Typenavnet følger listens oprindelige navn, ikke det nuværende. En liste, der er omdøbt, beholder sit gamle
SP.Data.…ListItem. Derfor henter jeg det i stedet for at gætte. - Interne navne er ikke visningsnavne. Et felt oprettet som “Due Date” hedder
Due_x0020_Date, også efter det er omdøbt. - Personer og opslag vil have tal, ikke navne eller e-mails. Id’et på en person er webstedets id, ikke Entra-id’et.
- Sprog. Interne navne er de samme på et dansk og et engelsk websted, visningsnavne er ikke. Datoer sendes som
yyyy-MM-dd, aldrig som31-03-2025.formatDateTime(variables('varDueDate'), 'yyyy-MM-dd')ordner det.