Skip to content

Metadata and pagination

Numbers and mailboxes carry a free-form metadata JSON object that you control, for example your own customer or order identifier. It is returned with the resource, can be filtered on, and changes are announced by the number.metadata_updated and email_account.metadata_updated webhook events.

You can set it when you rent a number (metadata on POST /numbers/rent) or when a mailbox is connected through an authorization link, and change it later with a PATCH:

curl -X PATCH https://api.clearance.rest/numbers/items/$ID \
-H "X-API-Key: $CLEARANCE_REST_API_KEY" \
-H "content-type: application/json" \
-H 'If-Match: "3"' \
-d '{ "metadata": { "order": "o-17", "old_key": null } }'
  • The body is a JSON Merge Patch (RFC 7396): keys you send are merged in, null removes a key, and arrays replace the whole array.
  • Metadata is limited to 16 KB, 5 levels of nesting and 64 characters per key. Breaking a limit returns 400 invalid_metadata or 413 metadata_too_large.
  • A patch that changes nothing does not bump the version and does not emit an event.

Each resource has a metadata_version, which a single-resource read also returns as the ETag header. Send it back in If-Match and the patch is applied only if nobody changed the metadata since you read it. Otherwise you get 412 metadata_version_mismatch with error.details.current_version; read the resource again, merge your change and retry. Without If-Match the patch is applied on top of whatever is current.

List endpoints accept:

  • metadata.<key>=<value>: the top-level key equals this string. Several filters are combined with AND. Keys match [A-Za-z0-9_-]{1,64}.
  • metadata_absent=a,b: resources that have none of these keys.
curl -G https://api.clearance.rest/emails/accounts \
-H "X-API-Key: $CLEARANCE_REST_API_KEY" \
--data-urlencode "metadata.customer=c1"

List endpoints return one page and a next_cursor.

{ "success": true, "items": [ ], "next_cursor": "eyJ..." }
  • limit is 1 to 200 and defaults to 50.
  • Pass the previous response’s next_cursor as cursor to get the next page. A null next_cursor means the list is complete.
  • Some filters, such as a number’s derived status, are applied after the page is read, so a page can hold fewer than limit items and still have a next_cursor. Keep going until it is null.
  • Treat cursors as opaque. A malformed one returns 400 invalid_cursor.

The SDKs offer generators that walk every page for you: iterateItems, iterateAccounts, iterateAuthLinks, iterateDeliveries.