# Create client link Link a new or existing organization to your OAuth application, in effect creating a new client. The response contains a `clientLink` where you should redirect your customer to. ## Redirecting the Customer The `clientLink` URL behaves similarly to a standard OAuth authorization URL. Therefore, after receiving the `clientLink` URL in the API response, you need to **append the following query parameters** *before* redirecting the customer: * `client_id` _string (required)_ The client ID you received when you registered your OAuth app. The ID starts with `app_`. For example: `app_abc123qwerty`. * `state` _string (required)_ A random string **generated by your app** to prevent CSRF attacks. This will be reflected in the `state` query parameter when the user returns to the `redirect_uri` after authorizing your app. * `scope` _string (required)_ A space-separated list of permissions ('scopes') your app requires. See the [permissions list](https://docs.mollie.com/docs/permissions) for more information about the available scopes. We recommend at least : `onboarding.read onboarding.write` * `approval_prompt` _string_ Can be set to `force` to force showing the consent screen to the merchant, *even when it is not necessary*. If you force an approval prompt and the user creates a new authorization, previously active authorizations will be revoked. Possible values: `auto` `force` (default: `auto`) ### Example of a Complete Redirect URL After adding the above url parameter your URL will look something like this and you can redirect your client to this page: ``` https://my.mollie.com/dashboard/client-link/{id}?client_id={your_client_id}&state={unique_state}&scope=onboarding.read%20onboarding.write ``` ## Error Handling Error handling is also dealt with similar to the [Authorize](https://docs.mollie.com/reference/authorize) endpoint: the customer is redirected back to your app's redirect URL with the `error` and `error_description` parameters added to the URL. > 🚧 > > A client link must be used within 30 days of creation. After that period, it will expire and you will need to create a new client link. > 🔑 Access with > > [Organization access token with **clients.write**](/reference/authentication) # OpenAPI definition ````json { "openapi": "3.1.0", "info": { "title": "Mollie Connect", "version": "1.0.0", "license": { "name": "Attribution-NonCommercial-ShareAlike 4.0 International", "identifier": "CC-BY-NC-SA-4.0" } }, "servers": [ { "url": "https://api.mollie.com" } ], "security": [ { "apiKey": [] }, { "organizationAccessToken": [] }, { "oAuth": [] } ], "paths": { "/v2/client-links": { "post": { "summary": "Create client link", "x-speakeasy-name-override": "create", "tags": [ "Client Links API" ], "operationId": "create-client-link", "security": [ { "organizationAccessToken": [ "clients.write" ] } ], "description": "Link a new or existing organization to your OAuth application, in effect creating a new client. The response contains a `clientLink` where you should redirect your customer to.\n\n## Redirecting the Customer\n\nThe `clientLink` URL behaves similarly to a standard OAuth authorization URL. Therefore, after receiving the `clientLink` URL in the API response, you need to **append the following query parameters** *before* redirecting the customer:\n\n* `client_id` _string (required)_\n\n The client ID you received when you registered your OAuth app. The ID starts with `app_`. For example: `app_abc123qwerty`.\n\n* `state` _string (required)_\n\n A random string **generated by your app** to prevent CSRF attacks. This will be reflected in the `state` query parameter when the user returns to the `redirect_uri` after authorizing your app.\n\n* `scope` _string (required)_\n\n A space-separated list of permissions ('scopes') your app requires. See the [permissions list](https://docs.mollie.com/docs/permissions) for more information about the available scopes.\n\n We recommend at least : `onboarding.read onboarding.write`\n\n* `approval_prompt` _string_\n\n Can be set to `force` to force showing the consent screen to the merchant, *even when it is not necessary*. If you force an approval prompt and the user creates a new authorization, previously active authorizations will be revoked.\n\n Possible values: `auto` `force` (default: `auto`)\n\n### Example of a Complete Redirect URL\n\nAfter adding the above url parameter your URL will look something like this and you can redirect your client to this page:\n\n``` https://my.mollie.com/dashboard/client-link/{id}?client_id={your_client_id}&state={unique_state}&scope=onboarding.read%20onboarding.write ```\n\n## Error Handling\n\nError handling is also dealt with similar to the [Authorize](https://docs.mollie.com/reference/authorize) endpoint: the customer is redirected back to your app's redirect URL with the `error` and `error_description` parameters added to the URL.\n\n> 🚧\n>\n> A client link must be used within 30 days of creation. After that period, it will expire and you will need to create a new client link.\n\n> 🔑 Access with\n>\n> [Organization access token with **clients.write**](/reference/authentication)", "requestBody": { "content": { "application/json": { "schema": { "allOf": [ { "type": "object", "properties": { "resource": { "type": "string", "description": "Indicates the response contains a client link object. Will always contain the string `client-link` for this endpoint.", "readOnly": true, "default": "client-link" }, "id": { "type": "string", "description": "The identifier uniquely referring to this client link. Example: `cl_vZCnNQsV2UtfXxYifWKWH`.", "readOnly": true, "example": "cl_vZCnNQsV2UtfXxYifWKWH" }, "owner": { "type": "object", "description": "Personal data of your customer.", "properties": { "email": { "type": "string", "description": "The email address of your customer.", "example": "john@example.org" }, "givenName": { "type": "string", "description": "The given name (first name) of your customer.", "example": "John" }, "familyName": { "type": "string", "description": "The family name (surname) of your customer.", "example": "Doe" }, "locale": { "type": [ "string", "null" ], "description": "Preset the language to be used for the login screen, if applicable. For the consent screen, the preferred language of the logged in merchant will be used and this parameter is ignored.\n\nWhen this parameter is omitted, the browser language will be used instead.\n\nPossible values: `en_US` `en_GB` `nl_NL` `nl_BE` `de_DE` `de_AT` `de_CH` `fr_FR` `fr_BE` `es_ES` `ca_ES` `pt_PT` `it_IT` `nb_NO` `sv_SE` `fi_FI` `da_DK` `is_IS` `hu_HU` `pl_PL` `lv_LV` `lt_LT` `null`", "example": "en_US" } }, "required": [ "email", "givenName", "familyName" ], "writeOnly": true }, "name": { "type": "string", "description": "Name of the organization.", "example": "Acme Corporation", "writeOnly": true }, "address": { "type": "object", "description": "Address of the organization.", "properties": { "streetAndNumber": { "type": [ "string", "null" ], "description": "The street name and house number of the organization.", "example": "Main Street 123" }, "postalCode": { "type": [ "string", "null" ], "description": "The postal code of the organization. Required if a street address is provided and if the country has a postal code system.", "example": "1234AB" }, "city": { "type": [ "string", "null" ], "description": "The city of the organization. Required if a street address is provided.", "example": "Amsterdam" }, "country": { "type": "string", "description": "The country of the address in [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format.", "example": "NL" } }, "required": [ "country" ], "writeOnly": true }, "registrationNumber": { "type": [ "string", "null" ], "description": "The registration number of the organization at their local chamber of commerce.", "example": 12345678, "writeOnly": true }, "vatNumber": { "type": [ "string", "null" ], "description": "The VAT number of the organization, if based in the European Union. VAT numbers are verified against the international registry *VIES*.", "writeOnly": true, "example": "NL123456789B01" }, "legalEntity": { "type": "string", "description": "The legal entity type of the organization, based on its country of origin. Please refer to the [legal entity list](common-data-types#legal-entity) for all possible options.", "example": "nl-bv", "writeOnly": true }, "registrationOffice": { "type": "string", "description": "The registration office that the organization was registered at. Please refer to the [registration office list](common-data-types#registration-office) for all possible options.", "example": "aachen", "writeOnly": true }, "incorporationDate": { "type": [ "string", "null" ], "description": "The incorporation date of the organization (format `YYYY-MM-DD`)", "example": "2024-12-24", "writeOnly": true }, "_links": { "type": "object", "description": "An object with several relevant URLs. Every URL object will contain an `href` and a `type` field.", "properties": { "self": { "type": "object", "description": "In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field.", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "description": "The actual URL string.", "example": "https://..." }, "type": { "type": "string", "description": "The content type of the page or endpoint the URL points to.", "example": "application/hal+json" } } }, "clientLink": { "description": "The link you can send your customer to, where they can either log in and link their account, or sign up and proceed with onboarding.", "type": "object", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "description": "The actual URL string.", "example": "https://..." }, "type": { "type": "string", "description": "The content type of the page or endpoint the URL points to.", "example": "application/hal+json" } } }, "documentation": { "type": "object", "description": "In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field.", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "description": "The actual URL string.", "example": "https://..." }, "type": { "type": "string", "description": "The content type of the page or endpoint the URL points to.", "example": "application/hal+json" } } } }, "readOnly": true } } }, { "type": "object", "required": [ "owner", "name", "address" ] } ] } } } }, "responses": { "201": { "description": "The newly created client link object.", "content": { "application/hal+json": { "schema": { "allOf": [ { "type": "object", "properties": { "resource": { "type": "string", "description": "Indicates the response contains a client link object. Will always contain the string `client-link` for this endpoint.", "readOnly": true, "default": "client-link" }, "id": { "type": "string", "description": "The identifier uniquely referring to this client link. Example: `cl_vZCnNQsV2UtfXxYifWKWH`.", "readOnly": true, "example": "cl_vZCnNQsV2UtfXxYifWKWH" }, "owner": { "type": "object", "description": "Personal data of your customer.", "properties": { "email": { "type": "string", "description": "The email address of your customer.", "example": "john@example.org" }, "givenName": { "type": "string", "description": "The given name (first name) of your customer.", "example": "John" }, "familyName": { "type": "string", "description": "The family name (surname) of your customer.", "example": "Doe" }, "locale": { "type": [ "string", "null" ], "description": "Preset the language to be used for the login screen, if applicable. For the consent screen, the preferred language of the logged in merchant will be used and this parameter is ignored.\n\nWhen this parameter is omitted, the browser language will be used instead.\n\nPossible values: `en_US` `en_GB` `nl_NL` `nl_BE` `de_DE` `de_AT` `de_CH` `fr_FR` `fr_BE` `es_ES` `ca_ES` `pt_PT` `it_IT` `nb_NO` `sv_SE` `fi_FI` `da_DK` `is_IS` `hu_HU` `pl_PL` `lv_LV` `lt_LT` `null`", "example": "en_US" } }, "required": [ "email", "givenName", "familyName" ], "writeOnly": true }, "name": { "type": "string", "description": "Name of the organization.", "example": "Acme Corporation", "writeOnly": true }, "address": { "type": "object", "description": "Address of the organization.", "properties": { "streetAndNumber": { "type": [ "string", "null" ], "description": "The street name and house number of the organization.", "example": "Main Street 123" }, "postalCode": { "type": [ "string", "null" ], "description": "The postal code of the organization. Required if a street address is provided and if the country has a postal code system.", "example": "1234AB" }, "city": { "type": [ "string", "null" ], "description": "The city of the organization. Required if a street address is provided.", "example": "Amsterdam" }, "country": { "type": "string", "description": "The country of the address in [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format.", "example": "NL" } }, "required": [ "country" ], "writeOnly": true }, "registrationNumber": { "type": [ "string", "null" ], "description": "The registration number of the organization at their local chamber of commerce.", "example": 12345678, "writeOnly": true }, "vatNumber": { "type": [ "string", "null" ], "description": "The VAT number of the organization, if based in the European Union. VAT numbers are verified against the international registry *VIES*.", "writeOnly": true, "example": "NL123456789B01" }, "legalEntity": { "type": "string", "description": "The legal entity type of the organization, based on its country of origin. Please refer to the [legal entity list](common-data-types#legal-entity) for all possible options.", "example": "nl-bv", "writeOnly": true }, "registrationOffice": { "type": "string", "description": "The registration office that the organization was registered at. Please refer to the [registration office list](common-data-types#registration-office) for all possible options.", "example": "aachen", "writeOnly": true }, "incorporationDate": { "type": [ "string", "null" ], "description": "The incorporation date of the organization (format `YYYY-MM-DD`)", "example": "2024-12-24", "writeOnly": true }, "_links": { "type": "object", "description": "An object with several relevant URLs. Every URL object will contain an `href` and a `type` field.", "properties": { "self": { "type": "object", "description": "In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field.", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "description": "The actual URL string.", "example": "https://..." }, "type": { "type": "string", "description": "The content type of the page or endpoint the URL points to.", "example": "application/hal+json" } } }, "clientLink": { "description": "The link you can send your customer to, where they can either log in and link their account, or sign up and proceed with onboarding.", "type": "object", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "description": "The actual URL string.", "example": "https://..." }, "type": { "type": "string", "description": "The content type of the page or endpoint the URL points to.", "example": "application/hal+json" } } }, "documentation": { "type": "object", "description": "In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field.", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "description": "The actual URL string.", "example": "https://..." }, "type": { "type": "string", "description": "The content type of the page or endpoint the URL points to.", "example": "application/hal+json" } } } }, "readOnly": true } } }, { "type": "object", "required": [ "resource", "id", "_links" ] } ] }, "examples": { "create-client-link-201-1": { "summary": "The newly created client link object", "value": { "resource": "client-link", "id": "cl_vZCnNQsV2UtfXxYifWKWH", "_links": { "self": { "href": "...", "type": "application/hal+json" }, "clientLink": { "href": "https://my.mollie.com/dashboard/client-link/cl_vZCnNQsV2UtfXxYifWKWH", "type": "text/html" }, "documentation": { "href": "...", "type": "text/html" } } } }, "create-client-link-201-2": { "summary": "Create client link all parameters", "x-request": "./requests.yaml#/oauth-create-client-link-all-parameters", "value": { "id": "csr_ayCz46QLwCbxpTaSYQQZH", "resource": "client-link", "_links": { "clientLink": { "href": "https://my.mollie.com/dashboard/client-link/csr_ayCz46QLwCbxpTaSYQQZH", "type": "text/html" }, "documentation": { "href": "...", "type": "text/html" } } } }, "create-client-link-201-3": { "summary": "Create client link minimal requirements", "x-request": "./requests.yaml#/oauth-create-client-link-minimal-requirements", "value": { "id": "csr_ayCz46QLwCbxpTaSYQQZH", "resource": "client-link", "_links": { "clientLink": { "href": "https://my.mollie.com/dashboard/client-link/csr_ayCz46QLwCbxpTaSYQQZH", "type": "text/html" }, "documentation": { "href": "...", "type": "text/html" } } } } } } } }, "404": { "description": "No entity with this ID exists.", "content": { "application/hal+json": { "schema": { "type": "object", "description": "An error response object.", "required": [ "status", "title", "detail", "_links" ], "properties": { "status": { "type": "integer", "description": "The status code of the error message. This is always the same code as the status code of the HTTP message itself.", "minimum": 400, "maximum": 599, "example": 404 }, "title": { "type": "string", "description": "The HTTP reason phrase of the error. For example, for a `404` error, the `title` will be `Not Found`.", "example": "Not Found" }, "detail": { "type": "string", "description": "A detailed human-readable description of the error that occurred.", "example": "The resource does not exist" }, "field": { "type": "string", "description": "If the error was caused by a value provided by you in a specific field, the `field` property will contain the name of the field that caused the issue.", "example": "description" }, "_links": { "type": "object", "required": [ "documentation" ], "properties": { "documentation": { "type": "object", "description": "The URL to the generic Mollie API error handling guide.", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "example": "https://docs.mollie.com/errors" }, "type": { "type": "string", "example": "text/html" } } } } } } }, "example": { "status": 404, "title": "Not Found", "detail": "No entity exists with token 'uct_abcDEFghij123456789'", "_links": { "documentation": { "href": "...", "type": "text/html" } } } } } }, "422": { "description": "The request contains issues. For example, if the `owner` field is missing.", "content": { "application/hal+json": { "schema": { "type": "object", "description": "An error response object.", "required": [ "status", "title", "detail", "_links" ], "properties": { "status": { "type": "integer", "description": "The status code of the error message. This is always the same code as the status code of the HTTP message itself.", "minimum": 400, "maximum": 599, "example": 404 }, "title": { "type": "string", "description": "The HTTP reason phrase of the error. For example, for a `404` error, the `title` will be `Not Found`.", "example": "Not Found" }, "detail": { "type": "string", "description": "A detailed human-readable description of the error that occurred.", "example": "The resource does not exist" }, "field": { "type": "string", "description": "If the error was caused by a value provided by you in a specific field, the `field` property will contain the name of the field that caused the issue.", "example": "description" }, "_links": { "type": "object", "required": [ "documentation" ], "properties": { "documentation": { "type": "object", "description": "The URL to the generic Mollie API error handling guide.", "required": [ "href", "type" ], "properties": { "href": { "type": "string", "example": "https://docs.mollie.com/errors" }, "type": { "type": "string", "example": "text/html" } } } } } } }, "example": { "status": 422, "title": "Unprocessable Entity", "detail": "The 'owner' field is missing", "field": "owner", "_links": { "documentation": { "href": "...", "type": "text/html" } } } } } } }, "x-readme": { "code-samples": [ { "language": "shell", "code": "curl -X POST https://api.mollie.com/v2/client-links \\\n -H \"Authorization: Bearer access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ\" \\\n -d \"owner[email]=info@example.org\" \\\n -d \"owner[givenName]=Chuck\" \\\n -d \"owner[familyName]=Norris\" \\\n -d \"address[country]=NL\" \\\n -d \"name=Mollie B.V.\" \\\n -d \"registrationNumber=30204462\" \\\n -d \"vatNumber=NL815839091B01\"" }, { "language": "php", "code": "setAccessToken('access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ');\n\n$clientLink = $mollie->send(\n new CreateClientLinkRequest(\n owner: new Owner(\n email: 'info@example.org',\n givenName: 'Chuck',\n familyName: 'Norris'\n ),\n name: 'Mollie B.V.',\n address: new OwnerAddress(countryCode: 'NL'),\n registrationNumber: '30204462',\n vatNumber: 'NL815839091B01'\n )\n);", "install": "composer require mollie/mollie-api-php" }, { "language": "node", "code": "/*\nWe don't have a Node.js code example for this\nAPI call yet.\n\nIf you have some time to spare, feel free to\nshare suggestions on our Discord:\nhttps://discord.gg/VaTVkXB4aQ\n*/", "install": "npm install @mollie/api-client" }, { "language": "python", "code": "from mollie.api.client import Client\n\nclient = Client()\nauthorized, authorization_url = client.setup_oauth(...)\n\nprint(\"authorized\", authorized)\nprint(\"authorization_url\", authorization_url)\n\nclient_link = client.client_links.create(\n {\n \"owner[email]\": \"info@example.org\",\n \"owner[givenName]\": \"Chuck\",\n \"owner[familyName]\": \"Norris\",\n \"address[country]\": \"NL\",\n \"name\": \"Mollie B.V.\",\n \"registrationNumber\": 30204462,\n \"vatNumber\": \"NL815839091B01\",\n }\n)", "install": "pip install mollie-api-python" }, { "language": "ruby", "code": "# We don't have a Ruby code example for this\n# API call yet.\n#\n# If you have some time to spare, feel free to\n# share suggestions on our Discord:\n# https://discord.gg/VaTVkXB4aQ", "install": "gem install mollie-api-ruby" } ] } } } }, "components": { "securitySchemes": { "apiKey": { "type": "http", "scheme": "bearer", "x-default": "live_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM" }, "organizationAccessToken": { "type": "http", "scheme": "bearer", "x-default": "access_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM" }, "oAuth": { "type": "oauth2", "flows": { "authorizationCode": { "authorizationUrl": "https://my.mollie.com/oauth2/authorize", "tokenUrl": "https://api.mollie.com/oauth2/tokens", "scopes": {} } } } } }, "x-readme": { "explorer-enabled": false, "samples-languages": [ "shell", "php", "node", "python", "ruby" ] } } ````