Skip to main content

In a nutshell

Some Blockradar API flows return a Dynamic Form Schema when an operation needs more information. The schema describes the object that your integration must produce.
Your integration:
  1. receives the JSON Schema;
  2. determines which fields apply to the current values;
  3. obtains values from a user or automated workflow;
  4. loads choices and resolves fields when their dependencies are ready;
  5. builds and validates the completed object; and
  6. submits that object as documented by the API guide for the operation.
Do not submit the completed object back to a requirements or discovery endpoint. Submit it in the request property documented by the next API operation, such as paymentMethodData or additionalData.

How Dynamic Forms work

A Dynamic Form Schema is a JSON object that describes the fields to collect. It uses standard JSON Schema keywords and documented x-* properties for choices, files, and fields whose values come from another API call. Do not hard-code fields from an earlier response. Use the schema returned for the current operation. Some fields apply only when another value selects a particular oneOf or if/then/else branch. Collect, validate, and submit only the fields in the selected branch. When a value selects a different branch, remove values that no longer apply. Repeat these steps as values change:

Recipes

Collect a basic object

For a schema with no conditions or API-driven fields:
  1. Read the field names from properties.
  2. Read required field names from required.
  3. Collect values using the declared types and validation rules.
  4. Validate the completed object against the schema.
  5. Submit the object in the request property documented by the API guide.
For example, this schema:
produces an object with the same property names and types:

Switch between conditional fields

An object-level oneOf can describe different sets of fields. Each branch uses a required type.const value as its selector:
When type is "mobile_money", collect and submit only that branch:
If type changes to "bank", remove phoneNumber and collect accountNumber.

Complete Withdraw Fiat requirements

  1. Get the payment-method requirements from GET /v2/wallets/{id}/withdraw/fiat/payment-method-requirements.
  2. Collect the fields in data.schema.
  3. When a field contains x-resolution, call it after its dependencies are valid, as described below.
  4. Validate the completed object.
  5. Send it as paymentMethodData when you get a quote or execute the withdrawal.
accountName is included because the resolution returned it. The field is optional in this example because it is not listed in the schema’s required array.

Complete Virtual Account requirements

  1. Get the Virtual Account requirements from GET /v2/wallets/{id}/virtual-accounts/requirements.
  2. If data.additionalDataRequired is true, collect the fields in data.additionalDataSchema.
  3. Validate the completed object.
  4. Send it as additionalData when you create the Virtual Account. Use the provider returned by the requirements request.

Complete Deposit Fiat payment-order requirements

  1. Get a Deposit Fiat quote from POST /v1/wallets/{id}/deposit/fiat/quote.
  2. Read the schema from data.additionalDataRequirements.schema.
  3. Collect its fields and resolve any x-resolution fields using the instructions in the schema. See Resolve Payment Order Requirements.
  4. Validate the completed object.
  5. Send it as additionalData when creating the payment order with POST /v1/wallets/{id}/deposit/fiat/orders.
The quote may return null for the schema. In that case, the selected route does not require additionalData.

Complete customer onboarding requirements

  1. Create an onboarding request for the customer.
  2. Read data.requirements.schema from the response. You can also retrieve the request to obtain its current schema and status.
  3. Collect and validate the customer information described by the schema. For file and document fields, first prepare the upload, then follow the returned direct-upload instructions or send the prepared document.
  4. Submit the completed object in the request body as data.
  5. If the response includes data.requirements, repeat the process using that current schema. If it does not, follow the returned case status and hosted session information.
If the case requires confirmation, fetch its confirmation requirements, complete that schema, and submit the confirmation.
The property names above are illustrative. Always use the properties returned by the current onboarding request.

Complete a schema from existing data

For an automated integration:
  1. Copy existing values only when their property paths and JSON types match the fields that currently apply.
  2. Report required fields that have no value. Do not invent placeholders.
  3. Accept only identifiers declared by enum or const.
  4. Load documented choices and resolve fields only after their dependencies are valid.
  5. If required information is still missing, stop and return the missing and invalid property paths to the calling workflow.
  6. Return a completed object only after full validation succeeds.

Schema structure and supported keywords

Dynamic Form Schemas use JSON Schema Draft 07 and declare:
Accept http://json-schema.org/draft-07/schema#. Accept another value only when the API operation explicitly documents that dialect. Otherwise, stop and report that the schema dialect is unsupported. Implement only the features present in the schemas your integration receives:

Validation keywords

Requiredness belongs to the containing object’s required array. A field-level required: true is not Draft 07.

Presentation annotations

Blockradar extensions

Nested objects define their own properties, required, and additionalProperties. Arrays retain the structure declared by items. Do not flatten nested paths when validating or submitting values. For a selectable object-level oneOf, each branch has a non-empty title and a required type property with a unique string const. Dynamic Forms does not use an OpenAPI discriminator.

Language-neutral data model

? means optional, [] means a list, and map<string, T> means an object whose property names map to values of type T.

Finding the fields that apply

Start at the root schema and follow nested objects and arrays. Apply conditional keywords before collecting their properties:
At each object, read required from that object. At each array, retain numeric indexes in error paths, such as owners[0].address.country. When a value selects a different object-level branch, remove fields that exist only in the previous branch. Reload choices and resolved values that depended on the changed value. Use a Draft 07 validator to evaluate allOf, oneOf, and conditional schemas. Do not implement branch selection by field titles or property order.

Supplying field values

Store every value at the exact property path from the selected branch and keep its declared JSON type. Do not assume that every schema contains a field such as accountName, country, or document. Validate supplied values before using them. Accept only declared enum or const identifiers, obtain resolved values through x-resolution, and obtain file references through the upload flow documented by the API operation.

Choices, dependencies, and resolved fields

Static choices

For enum, submit the selected value. For a oneOf choice whose branches contain const, show each branch’s title and submit its const:
The completed value is "999", not "Example Bank".

Remote choices

x-data-source names a remote choice source. x-data-source-depends-on lists the property paths required before that source can load. Wait until every dependency is present and valid. x-data-source does not provide the endpoint, request body, or response format. Use the loading instructions documented by the API guide. Discard old choices when a dependency changes. If the API guide does not document the source, do not guess an endpoint from the source name. Stop and tell the caller that the choice source has no documented integration flow.

Resolved fields

A field with x-resolution gets its value from the API request described by x-resolution: x-field-kind: "resolved" does not make a field required. A resolved field is required only when its property name appears in the containing object’s required array. Resolve an optional field when the API flow needs its value or when you want to show the verified result.

Resolve an account name

This recipe uses the x-resolution returned by the Withdraw Fiat requirements request:
Given these current values:
the request body is:
Send this body to x-resolution.url. For this recipe, see Resolve Payment Method. The API returns:
Follow responsePath from the response’s top-level data value:
Store the result at accountName:
Copy body into a new request body. When inputPath is present, add the current form values at that path. If a dependency changes, clear the previous result and call the resolution again with the new values. Do not call the resolution while a path in dependsOn is missing or invalid. If the request fails, leave the field unresolved and surface the API error to the calling workflow.

File and document fields

File fields add upload constraints to a schema property:
x-field-kind: "files" uses an array whose items are objects. x-document-types can contain strings or objects with value, label, and optional sides containing front or back. The API guide defines how to upload the file and which value to place in the completed object. The schema itself does not provide an upload endpoint, multipart field name, response format, or file-reference format. Do not place a platform-specific file object or raw bytes in the JSON object. If the API operation does not document the upload flow or file-reference format, stop and tell the caller that the file field cannot be submitted. Enforce x-accept, x-max-file-size-bytes, array limits, document types, and required sides before submission.

Partial and complete validation

Partial validation answers: Are the values supplied so far valid? It does not mean the object is ready to submit. For partial validation, validate the current object against the branch that applies. Continue to enforce:
  • supplied value types and constraints;
  • enum and const;
  • additionalProperties;
  • array constraints; and
  • allOf, oneOf, and any if/then/else branch that can already be determined.
Ignore only required failures for properties that have not been supplied yet. Do not validate each property in isolation because rules on the containing object may also apply. Complete validation answers: Is the object ready to submit? Validate the completed object against the full, unmodified schema and report every failure. Preserve strings when the schema declares type: "string", including account numbers and decimal amounts. Submit JSON numbers for fields declared as number or integer.

Constructing and submitting the final object

Build a new object from the properties that currently apply:
  • copy accepted values at exact property paths;
  • retain nested objects and arrays;
  • copy identifiers rather than labels;
  • include values returned by resolution calls;
  • include documented uploaded-file references;
  • omit properties from unselected branches and any UI-only state;
  • reject unknown properties where additionalProperties: false; and
  • omit absent optional properties.
Validate this new object against the complete schema. Then place it in the request property documented by the API guide.

Error handling

Dynamic Forms uses the standard Blockradar API error response. A validation failure includes the HTTP status and a message that identifies the missing or invalid field:
requestId is included when request context is available. Some errors can also include details. Do not depend on undocumented error codes. Use the HTTP status and message, and retain requestId when contacting support.

Security boundaries

The integration must:
  • keep API credentials out of untrusted application code;
  • use the schema returned by Blockradar instead of a modified client copy;
  • read the schema as data; never execute content from it as code;
  • accept only the documented POST or PATCH resolution methods and API-relative paths on the configured Blockradar origin;
  • validate the completed object before submission; and
  • avoid logging credentials or sensitive field values.

Testing and production checklist

Before production, verify that your integration can:
  • retrieve schemas dynamically;
  • identify required and conditional fields at nested paths;
  • handle static choices, documented data sources, and resolved fields;
  • preserve exact names, types, paths, objects, and arrays;
  • remove values from branches that no longer apply;
  • build and validate the completed object; and
  • submit it in the request property documented by the API guide.