Documentation
Technical ReferenceREST API

Statement descriptors

The statementDescriptor field on products, collections, and your company, with its validation rules, the cascade that picks one value per charge, and the warnings returned when you save.

Statement descriptors

A statement descriptor is the dynamic part of the text a customer sees on their card statement, for example PREMIUM BOX in ACMEGOODS* PREMIUM BOX (the examples on this page use the placeholder brand ACMEGOODS). You can save one on a product, on a collection, and on your company (the client level). For each charge Flo picks one value through the cascade and sends it to the gateway, which puts its prefix in front. How the final text is built, how to set the Stripe shortened descriptor, and how to act on the alert enrollment check are explained in Show your brand on card statements, in the Accept a payment guide.

Nothing changes until a descriptor is saved: with no descriptor at any level, Flo's requests to Stripe are unchanged. The one exception is Worldpay, where every order now carries your Worldpay prefix or, without a prefix, your company name, with no activation step. See Worldpay prefix and fallback text.

Endpoints

statementDescriptor is available on these merchant endpoints, with the authentication you already use for them:

LevelCreateUpdateRead
ProductPOST /v1/productsPATCH /v1/products/{productUuid}GET /v1/products/{productUuid}
CollectionPOST /v1/collectionsPATCH /v1/collections/{collectionUuid}GET /v1/collections/{collectionUuid}
Client (your company)Not applicablePATCH /v1/companyGET /v1/company

PATCH /v1/company needs an OAuth access token (Authorization: Bearer) for an owner or admin of your company. An API token sent with HTTP Basic is refused with a 403, because it does not identify the person making the change. GET /v1/company and the product and collection endpoints accept either. With an OAuth access token, product and collection writes also need an owner or admin, because members have read-only catalog access.

The statementDescriptor field

  • What it holds: the dynamic part only, not the full statement text. The gateway adds its prefix and * in front of it.
  • Optional: a product, collection, or company without a value reads back "statementDescriptor": null.
  • Clearing: sending null or "" clears the value. A value of only spaces clears it too.
  • Leaving it alone: omitting the field from an update leaves the stored value unchanged.
  • Normalization: the value is trimmed of leading and trailing spaces, and its case is kept as entered. Length is counted after trimming.

Validation

A value is refused when it:

  • contains any of these characters: <, >, \, ', ", *;
  • has no letter (a value needs at least one letter);
  • is longer than 18 characters after trimming.

An invalid value gets a 400 whose message names the field and the rule it broke, and nothing is saved.

PATCH /v1/company takes statementDescriptor, currency, or both. It needs at least one of currency or statementDescriptor, and a body with neither gets a 400. A currency-only body behaves as it did before.

A value that passes these rules but is too long for a gateway's prefix is still saved. The response reports it in statementDescriptorWarnings (see Save warnings).

curl -X PATCH https://api.flopay.com/v1/company \
  -H "Authorization: Bearer $FLOPAY_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "statementDescriptor": "PREMIUM BOX TRIAL"
  }'

Cascade

Flo works out one descriptor per charge, from the products the charge is for, and uses the first level that settles:

  1. Product: every product in the charge has a product-level descriptor, and they are all the same value.
  2. Collection: take the collections that contain every product in the charge and have a descriptor. If they give exactly one distinct value, it applies. With none, or with different values, Flo moves up.
  3. Client: the descriptor saved on your company, if it is set.
  4. Nothing: no descriptor applies, and the charge carries none.

A mixed basket, where one product has a descriptor and another has none or a different one, never uses a product value: it falls through to the next level, collection and then client.

Values are compared as exact text, and the comparison is case-sensitive. Brand and BRAND are different values, so two collections holding them do not agree and Flo moves up to client.

  • A product counts once, even when the charge includes it twice.
  • Deleted collections are ignored.
  • A product's own descriptor counts whatever the product's status, because a renewal can be for an archived product.
  • A charge with no products skips the product and collection levels.
  • Flo works the descriptor out again for every new charge attempt, from your current settings. A rebill replay reuses the descriptor of the attempt it replays.

Save warnings

Create and update responses at all three levels carry two arrays next to the saved resource: statementDescriptorWarnings and preDisputeAlertWarnings. Both appear only on write responses, are [] when nothing applies, and never block the save: the value is saved either way. Reads return only the value.

statementDescriptorWarnings

One entry per active gateway whose known prefix leaves less room than your value needs. Gateways whose prefix Flo does not know never warn. The array is [] when the field was not sent, was cleared, or fits every gateway.

FieldTypeMeaning
gatewayIdstringThe gateway's id.
gatewayNamestringThe gateway's name.
prefixstringThe prefix Flo knows for this gateway, for example the Stripe shortened descriptor.
maxLengthnumberThe longest dynamic part this gateway allows, normally 22 minus the prefix length minus 2.
previewstringThe statement text built from the prefix, * , and your value.

preDisputeAlertWarnings

Filled in when you have pre-dispute alerts set up (at least one live enrolled descriptor) and the write carries a non-empty statementDescriptor. It has one entry per active gateway whose prefix Flo knows. The alert enrollment check section of the Accept a payment guide explains the matching rule and what to do with each result.

FieldTypeMeaning
gatewayIdstringThe gateway's id.
gatewayNamestringThe gateway's name.
finalTextstringThe statement text for this gateway: the prefix, * , then your value.
resultstringattributed when every entry in networks matches alerts for finalText to you, otherwise unmatched.
messagestringA readable explanation that includes finalText. Its wording can change, so build on result.
networksarrayOne entry per alert network you have a live enrollment on.

Each networks entry:

FieldTypeMeaning
networkstringThe alert network: ethoca, rdr, or cdrn.
attributedbooleanWhether alerts on this network for finalText would be matched to you.
enrolledDescriptorstring or nullYour enrolled descriptor that matched, or null when none of yours did. Another client's descriptor is never returned.

Example: the response to the PATCH /v1/company request above, for a client whose Stripe gateway has the shortened descriptor ACMEGOODS and who has a live ACMEGOODS* enrollment on Ethoca.

{
  "id": "4f1c2b7e-9a3d-4e8f-b2c6-1d5a7e9f0c3b",
  "slug": "acme-goods",
  "currency": "USD",
  "statementDescriptor": "PREMIUM BOX TRIAL",
  "createdAt": "2026-03-02T10:15:00.000Z",
  "updatedAt": "2026-10-24T09:00:00.000Z",
  "statementDescriptorWarnings": [
    {
      "gatewayId": "9b2e4d61-3c7a-4f08-a5d9-6e1f2b8c4a70",
      "gatewayName": "Stripe",
      "prefix": "ACMEGOODS",
      "maxLength": 11,
      "preview": "ACMEGOODS* PREMIUM BOX TRIAL"
    }
  ],
  "preDisputeAlertWarnings": [
    {
      "gatewayId": "9b2e4d61-3c7a-4f08-a5d9-6e1f2b8c4a70",
      "gatewayName": "Stripe",
      "finalText": "ACMEGOODS* PREMIUM BOX TRIAL",
      "result": "attributed",
      "message": "Pre-dispute alerts for ACMEGOODS* PREMIUM BOX TRIAL would be attributed to you. Confirm with your alert provider that this variant is covered.",
      "networks": [
        {
          "network": "ethoca",
          "attributed": true,
          "enrolledDescriptor": "ACMEGOODS*"
        }
      ]
    }
  ]
}

Product and collection create and update responses carry the same two arrays next to the product or collection fields.

On this page