How it works?
This documentation needs work. See "Help improve this page" in the sidebar.
Source options
Mandatory options are marked with a star (*).
The graphql source offers a number of options to allow you to best configure your query. In short:
source:
plugin: graphql
# [mandatory] The GraphQL endpoint
endpoint: <value>
# [optional] Basic, Bearer, Digest, etc...
auth_scheme: <value>
# [optional] Paired with auth_scheme will generate the string that
# will be passed to the Authorization header
auth_parameter: <value>
# [optional] Used to specify a different name for "data" property
data_key: <value>
# [optional] Source field to use as ID (if omitted will be "id" of "string" type)
ids:
<source_field_name>:
type: <source_filed_type> # string, int, etc.
# [mandatory] from here starts the query definition
query:
# [mandatory] The query name
<query_name>:
# [optional] Query arguments (filtering, pagination, and so on...).
# See the example below.
arguments:
# [mandatory] Query fields definition
fields:
# [mandatory] It is 'data' if no different value has been set in data_key
- <data|data_key>:
- <field_1>
- <field_2>
- <field_n>
-
endpoint*: Represents the GraphQL endpoint.
-
Authentication
-
auth_scheme: Specify different authorization schemes like Basic, Bearer, Digest (etc...);
-
auth_parameter: Simply pairing the auth_scheme and auth_parameters value, will generate the string that will be passed to the Authorization header. So, as example:
-
auth_scheme: Bearer auth_parameter: 'eyJhbGciO.eyJzdWIiOiIxMjM0NTY3...'will generate the following
Authorization header:Authorization: Bearer eyJhbGciO.eyJzdWIiOiIxMjM0NTY3...
-
-
-
data_key: Specify a different name for "data" property. By default the data key's name is "data". It also accepts the
Row::PROPERTY_SEPARATOR(/) to navigate nested structures, including iterator placeholder '%' for dynamic mapping. Get more information by reading "The data_key" section of documentation. -
ids: Specify what source's filed represents the item ID. It's possible to configure its name (
<source_field_name>) and its type (<source_field_type>). If this option is omitted will be automatically used "id" as<source_field_name>and "string" as<source_field_type>. Example:-
data_key: items query: schools: fields: - items: - acronym - msdeReport ids: acronym: type: string
-
-
query*: from here starts the query definition.
-
arguments: used to specify query arguments. It simply needs to be transposed the graphql into the yaml format.
-
query: posts: arguments: options: paginate: page: 1 limit: 10 fields: ...that in GraphQL become:
-
query { posts(options:{ paginate: { page:1, limit:10 } }) { ... }
-
- fields*: The only difference between the GraphQL query and the YAML transposition is the mandatory property fields, the usefulness of which is solely a matter of choice for the developer.
- ids: Allows to configure custom IDs in the GraphQL source plugin for migrations, similar to the existing functionality in the migrate_plus URL source plugin. This allows users to specify IDs that are not simply called "id". If not specified it will be "id" of "string" type. An example:
query: schools: fields: - items: - acronym - msdeReport ids: acronym: type: string
The data_key
Specify a different name for the "data" property. By default the data key's name is "data". But, in some cases, it may need to go deeper instead of stopping at the first level of the structure. As example, let's take the following query:
query:
posts:
fields:
-
anotherBrickInTheWall:
posts:
- id
- title
- bodynow suppose we want to get all the posts inside anotherBrickInTheWall, using data_key property we can do as follow:
data_key: anotherBrickInTheWall/postsWe used the PROPERTY_SEPARATOR (/) to get nested posts items.
Iterator placeholder '%':
- Example:
data_key: data/%/user(follow below explanation)
Another case should be the following, imagine we have the following query:
...
query:
albums:
fields:
-
data:
-
user:
- id
- name
- emailThat will generate a response like this:

To map the properties of the 'user' item (id, name, email) onto the Drupal entity:user entity, you need to use data_key combined with the '%' placeholder like this: data_key: data/%/users.
Each time the migration loops through the response's results, it will check for the '%' placeholder, which represents an index (0, 1, ..., number of items). This allows it to access the internal 'user' items in the array. For example, it will first access $data[0]['user'], then $data[1]['user'], next $data[2]['user'], and so on.
In summary, using the '%' placeholder instructs the migration to retrieve the 'user' item within the array, rather than the element containing it.
An example
For this example we will use the GraphQLZero (Fake Online GraphQL API for Testing and Prototyping) from which we will migrate some entities, that on GraphQLZero are called posts, into the our Drupal instance populating the our's default articles.
Follow GraphQL query shows how to get a list of posts from GraphQLZero:
query {
posts {
data {
id
title
body
}
}
}The response:

The migration
So we, as first thing, have to setup the YAML migration file. As like as follow:
id: migrate_graphql_posts_articles
label: 'Migrate posts from GraphQLZero'
migration_tags: null
source:
plugin: graphql
endpoint: 'https://graphqlzero.almansi.me/api'
auth_scheme: Bearer
auth_parameter: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3...'
query:
posts:
fields:
-
data:
- id
- title
- body
ids:
id:
type: string
process:
title: title
body: body
destination:
plugin: 'entity:node'
default_bundle: article
migration_dependencies: { }The only difference between the GraphQL query and the YAML transposition is the mandatory property fields, the usefulness of which is solely a matter of choice for the developer.
This is what you should expect at the end of the migration:

ResultsEvent for Data Manipulation
Starting from version 2.1.0, the Migrate Source GraphQL module introduces the ResultsEvent, allowing other modules to modify the results obtained from a GraphQL query during migration.
Key Features
getResults(): Retrieves the current query results.setResults(array $results): Allows modification of these results.
Usage Example
Modules can subscribe to the ResultsEvent to manipulate the migration data:
use Drupal\migrate_source_graphql\Event\ResultsEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MyModuleSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [ResultsEvent::class => 'onResultsEvent'];
}
public function onResultsEvent(ResultsEvent $event) {
$results = $event->getResults();
// Custom modifications to results.
$results['custom_field'] = 'custom_value';
$event->setResults($results);
}
}
The GraphQL plugin now dispatches this event, enabling custom data handling during migrations.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion
Still on Drupal 7? Security support for Drupal 7 ended on 5 January 2025. Please visit our Drupal 7 End of Life resources page to review all of your options.