Pagination
List operations return one page at a time. Every page has the same envelope:
{ "data": [ { "id": "0199…", "…": "…" } ], "has_more": true, "next_cursor": "0199…"}| Field | Meaning |
|---|---|
data |
The items on this page. |
has_more |
true if there is at least one more page. |
next_cursor |
The value to send as cursor for the next page. null on the last page. |
Some lists add fields beside these, such as pending_count on
listApprovals.
Fetching pages
Section titled “Fetching pages”Two query parameters control paging:
limit: how many items per page. Most lists accept 1 to 100 and default to 50. Each list’s reference page gives its range.cursor: where to continue. Leave it out for the first page.
curl -s "$ELE_API_BASE/api/v1/organizations/$ORG_ID/transactions?limit=100" \ -H "Authorization: Bearer $ELE_TOKEN"While has_more is true, send next_cursor as cursor to fetch the next
page. Keep every other parameter the same:
curl -s "$ELE_API_BASE/api/v1/organizations/$ORG_ID/transactions?limit=100&cursor=$NEXT_CURSOR" \ -H "Authorization: Bearer $ELE_TOKEN"Stop when has_more is false.
Treat the cursor as an opaque value. Some lists happen to use the last item’s
ID, but always take the cursor from next_cursor rather than building one.
On listAttentionItems, a cursor
whose item has since been resolved returns an empty page. Start again from the
first page.
The example
Section titled “The example”This program lists every transaction of an organization, newest first. The
transactions function returns a Go iterator (iter.Seq2) that fetches each
page only when the loop reaches it. Breaking out of the loop stops the
fetching:
// Pagination: list every transaction of an organization, newest first, one// page at a time. The iterator fetches the next page only when the loop// reaches it, and stops fetching when the loop stops.//// ELE_TOKEN=… go run ./pagination <organization_id>package main
import ( "context" "fmt" "iter" "log" "net/url" "os"
"github.com/elephants-labs/ele/developers/examples/internal/ele")
// transaction holds the fields this example prints. Transactions have many// more, which depend on their type.type transaction struct { ID string `json:"id"` Type string `json:"type"` RecordedAt string `json:"recorded_at"` Effect *effect `json:"effect"`}
type effect struct { Direction string `json:"direction"` Total string `json:"total"` Currency string `json:"currency"`}
type page struct { Data []transaction `json:"data"` HasMore bool `json:"has_more"` NextCursor *string `json:"next_cursor"`}
func main() { if len(os.Args) != 2 { log.Fatal("usage: go run ./pagination <organization_id>") } ctx := context.Background() c := ele.FromEnv()
for t, err := range transactions(ctx, c, os.Args[1]) { if err != nil { log.Fatal(err) } if t.Effect == nil { fmt.Printf("%s %-18s\n", t.RecordedAt, t.Type) continue } fmt.Printf("%s %-18s %-3s %s %s\n", t.RecordedAt, t.Type, t.Effect.Direction, t.Effect.Total, t.Effect.Currency) }}
// transactions yields each transaction of the organization. On an error it// yields the error once and stops.func transactions(ctx context.Context, c *ele.Client, organizationID string) iter.Seq2[transaction, error] { path := "/api/v1/organizations/" + url.PathEscape(organizationID) + "/transactions" return func(yield func(transaction, error) bool) { query := url.Values{"limit": {"100"}} for { var p page if err := c.Do(ctx, "GET", path+"?"+query.Encode(), nil, &p); err != nil { yield(transaction{}, err) return } for _, t := range p.Data { if !yield(t, nil) { return } } if !p.HasMore || p.NextCursor == nil { return } query.Set("cursor", *p.NextCursor) } }}ELE_TOKEN=… go run ./pagination "$ORG_ID"listTransactions also takes
filters, such as date_start and date_end. Add them to the first request
and keep them on every later one.