curl --request GET \
--url https://api.dueflow.co/v1/deletions \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.dueflow.co/v1/deletions"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.dueflow.co/v1/deletions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dueflow.co/v1/deletions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.dueflow.co/v1/deletions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.dueflow.co/v1/deletions")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dueflow.co/v1/deletions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "<string>",
"resourceType": "cardTransactions.list",
"resourceId": "<string>",
"parentId": "<string>",
"deletedAt": "2023-11-07T05:31:56Z"
}
],
"hasMore": true,
"nextCursor": "<string>"
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}List deletions
Requires scope
cards:read, orchapters:read, orfundraise:read, orgroups:read, orgroups:write, ormembers:read, orpayments:read, orreimbursements:read, orreminders:read, orstore:read· Minimum role viewer
Records deleted outright from the synced lists, oldest deletion first, so an incremental client can drop its copies. resourceType is the list the record came from (groups.list is GET /groups, groups.listMembers is GET /groups/{groupId}/members, with the group as parentId); without it, every list the token can read. Keep a copy per list (and per parent): a deletion removes the record from that list only, so a groups.listMembers deletion drops the member from that group’s list, not from /members. Drop your copy only when deletedAt is later than the updatedAt of the copy you got from that same list and parent: a record can come back after it was deleted (a member re-added to a group). As updatedSince, pass the latest deletedAt you have seen minus a margin (5 minutes): it is stamped before the deletion commits, so one can land after a later-stamped one, and dropping a copy twice is harmless. A groups.list deletion also removes that group’s members list. Deletions are pruned after 90 days; only an updatedSince or cursor older than the latest deletion pruned for the organization answers 410 sync_expired, and then the client resyncs the lists in full. Not reported here: an archived member leaving groups.listMembers (which lists active members only; /members reports the archive), and a chapter moved to another national leaving the old national’s /chapters.
curl --request GET \
--url https://api.dueflow.co/v1/deletions \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.dueflow.co/v1/deletions"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.dueflow.co/v1/deletions', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dueflow.co/v1/deletions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.dueflow.co/v1/deletions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.dueflow.co/v1/deletions")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dueflow.co/v1/deletions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": "<string>",
"resourceType": "cardTransactions.list",
"resourceId": "<string>",
"parentId": "<string>",
"deletedAt": "2023-11-07T05:31:56Z"
}
],
"hasMore": true,
"nextCursor": "<string>"
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}{
"error": {
"code": "<string>",
"message": "<string>",
"requestId": "<string>",
"docsUrl": "<string>",
"param": "<string>",
"requiredScopes": [
"<string>"
]
}
}Authorizations
A Dueflow access token: dfp_ (personal) or dfs_ (service). Permissions are the token's scopes intersected with the role ceiling, re-evaluated per request.
Scopes
Query Parameters
1 <= x <= 100cardTransactions.list, cards.list, chapters.list, chapters.listMembers, fundraise.listCampaigns, groups.list, groups.listMembers, members.list, payments.list, reimbursements.list, reminders.list, store.listListings 
