Skip to main content

Filtering and Sorting

Every list query in the Refersion GraphQL API takes the same shape of arguments: some filters, a sort, and a page size. The rules below apply to all of them, so learning them once covers the whole API. For the arguments a specific query accepts, see the Schema Reference.

Filters combine with AND

Pass several filters and a record must match all of them. There is no OR, and no way to widen a query beyond your own data.

Unless noted otherwise, a filter is an exact match on the field of the same name — there are no contains, starts with, or greater-than operators. The only range filters are the date arguments below.

{
"query": "{ conversions(status: \"APPROVED\" affiliate_id: 123456) { id total } }"
}

Dates are Unix timestamps

Every date argument takes a Unix timestamp in seconds, not an ISO 8601 string, and they come in _from / _to pairs:

ArgumentMatches
created_fromRecords created strictly after the timestamp.
created_toRecords created at or before the timestamp.

updated_from / updated_to, last_login_from / last_login_to and last_conversion_from / last_conversion_to behave the same way. The bounds are asymmetric: _from is exclusive, _to is inclusive. Paging a date range by passing the previous page's last timestamp as the next _from therefore will not repeat that record.

Date fields come back the same way — as Unix timestamps, not ISO 8601 strings:

{ "created": "1526674258" }
note

On the Affiliate type, a date that was never set comes back as null rather than as a timestamp of zero.

Some arguments filter a differently-named field

A few arguments are named for the concept rather than the underlying field. They are equivalent to the field they map to, not additional filters:

ArgumentActually filtersNotes
order_idThe order identifier you sent when reporting the orderIdentical to merchant_unique_id.
sub_idThe subid carried on the tracking linkNote the underscore in the argument but not the field.
payment_statusWhether the record is attached to a paymentUNPAID matches records with no payment; any other value matches records that have one.
is_test_conversionWhether the conversion came from test trafficOmit it to receive both test and real conversions.
created_from / created_to on clicksThe click's entry timeClicks record an entry time rather than a created time.

Sorting

sort takes a single field name and always sorts descending. There is no direction argument and no multi-field sort.

Each type accepts its own short list of sort fields — they are listed under Sorting on every type page. Two consequences worth knowing:

  • An unrecognized sort is ignored silently. No error is returned; you get the results back in the database's own order. If a sort seems to have no effect, check the field is on that type's list. Sorting clicks by subid, for example, uses subid and not sub_id.
  • first and last override sort. Both act as a page size, but they also force sorting by idfirst ascending, last descending. A query that passes first alongside sort gets id-ordering, not the sort you asked for.

Page size and paging

limit caps the rows returned. Any value outside 1–200 — including a negative number, a non-numeric value, or a number above 200 — is silently replaced by 200, which is also the default when you pass no page size at all.

There are two ways to page:

  • Offset paging with limit (or first) plus offset. Straightforward, and what Pagination walks through.
  • Cursor paging with before and after, which match on id rather than position: after: 500 returns records with an id above 500. Because a cursor is anchored to a record rather than to a position, it does not skip or repeat rows when new records arrive mid-page — which offset paging over a growing table can do.

Records you will never see

Some records are filtered out before your arguments are applied, so no filter value will surface them:

QueryAlways excluded
affiliatesAny affiliate not in ACTIVE, PENDING, DISABLED or DENIED.
conversionsArchived conversions, and any status outside APPROVED, PENDING, DENIED, UNQUALIFIED.
conversion_triggersEvery trigger that is not ACTIVE.

conversion_triggers is the one that surprises people: it accepts a status argument, but only active triggers exist as far as the API is concerned, so filtering for any other status returns an empty list rather than an error.

payments is a special case. Cancelled payments are excluded only when the query carries at least one argument — any argument at all, including limit. A bare payments { … } returns cancelled payments alongside the rest, so pass a limit (which you want anyway) if you need them filtered out.

Errors

A query that fails validation — an unknown field, a wrong argument type, malformed syntax — returns HTTP 400 with an errors array describing what went wrong. A query that is valid but matches nothing returns HTTP 200 and an empty list.