Access-denied (403) on connector creation
A 403/access-denied response when creating a connector has two unrelated causes that share the same generic exception — always read the exact error message text, since that’s the only way to tell them apart.
1. Role and access rights
Creating a connector requires the ADMIN or PROJECT_MANAGER role, and a separate access right called “Modify global server settings”. Having the ADMIN role does not guarantee this right is enabled — it’s an independent per-account setting. If your error message is a generic access-denied with no further detail, check this first.
2. Per-connector-type subscription entitlement
Some connector types are gated behind their own subscription add-on, independent of your role or access rights: AEM_PLUGIN, CONTENTFUL, HUBSPOT, OPTIMIZELY, TRIDION, KENTICO_KONTENT, BRAZE_MULTILANG, CONTENTSTACK, MARKETO, and ZENDESK each require a separate Phrase subscription add-on.
If the error message literally says something like “<TYPE> is not enabled”, this is not a permissions problem at all — your organization’s Phrase subscription doesn’t include that connector’s add-on. This is fixable through your subscription/billing, not through any access-rights toggle.
If you can successfully create one connector type but a different type fails with an access-denied error, that’s a strong signal you’re looking at case 2, not case 1 — a role/rights problem would affect every connector type equally.
Per-connector-type field quirks
The generic connector-creation schema only documents the common base fields (name, type, sourceUrl, defaultRemoteFolder, encodedDefaultRemoteFolder, commitMessage) — it doesn’t reliably surface each connector type’s own extra fields. A handful of types have field names that don’t match what you’d naturally guess:
Amazon S3 (AMAZON_S3)
Fields are exactly apiKey, apiSecret, and amazonIamRole — not AWS’s own naming (accessKeyId/secretAccessKey). There is no region field: the region is embedded directly in the bucket hostname (e.g. integrations-plugins.qa.eu-west-1.s3.memsource.com).
Sending the wrong field names here doesn’t produce a validation error — the API silently accepts null credentials and only fails later, at test-connection time, with an unhelpful server error that can look like a platform outage. If test-connection fails right after creating an AMAZON_S3 connector, check your field names before assuming anything else is wrong.
Marketo (MARKETO)
marketoConnectorType is required — creation fails without it. Collect it upfront alongside the credentials, not as a follow-up question after the connector already failed to create.
You need four things to create a Marketo connector: the API key, the API secret, the API identity URL, and how the customer wants “Create translations” to work. Use the TMS UI’s own field labels when asking for credentials — “Marketo API key”, “Marketo API secret”, and “Marketo API identity URL” — rather than Marketo’s native OAuth terminology (“Client ID”, “Client Secret”, “Munchkin ID”). They map directly to the API’s field names, but the host value must be sent as identityURL in the request body — host is a hidden/internal field name and is silently ignored if you send it instead.
The identity URL follows the format https://<munchkin-id>.mktorest.com/identity — for example https://063-RVK-838.mktorest.com/identity. Find your own instance’s value in Marketo Admin → Integration → Web Services.
The “Create translations” mode field is marketoConnectorType, and its values are not dynamic/static as you might expect — they match the two options shown in the TMS UI:
SEPARATED_ASSET — “as separate documents”: translations are created as siblings of the original document, with the locale code appended to the title (e.g. Black Friday promo [de-de])
SEGMENTED_DYNAMIC_CONTENT — “as segmented dynamic content”: translations are stored within the original document, with each segment associated with a target locale
Required fields are exactly apiKey, apiSecret, host (sent as identityURL), and marketoConnectorType. Segmentation mapping (marketoSegmentationMapping) is optional at the API level even when using segmented dynamic content mode.
Adobe Experience Manager (AEM_PLUGIN)
Beyond the base fields: host (required), plus optional basicAuthUserName/basicAuthPassword (used specifically for live preview, not the main connection), forcedHttps (boolean), and urlRewriteFind/urlRewriteReplace. Not OAuth-based.
WordPress (WORDPRESS)
WordPress connector credentials are not your normal WordPress admin login. They come from the Phrase/Memsource Connector plugin’s own settings page on the WordPress site:
On that page, click “Show Connector settings” and copy the “Phrase TMS Connector authentication token”, plus the username and password shown there.
If test-connection returns GENERAL_ERROR, check whether the site’s host is actually a public URL first. A host like localhost or a local development port is unreachable from Phrase’s servers entirely, regardless of whether the credentials are correct — you’ll need a public URL or a tunnel (e.g. ngrok) for Phrase to reach a local WordPress instance.
GitHub (plain GIT type, credential-based)
If you’re connecting to a github.com (or GitHub Enterprise) host using the plain GIT connector type (not GITHUB/GITHUB2), note that GitHub has rejected real account passwords for Git-over-HTTPS since August 2021. The password field must be a Personal Access Token, not your actual account password. An UNAUTHORIZED response for a GitHub-hosted GIT connector is almost always this.
Types not listed here
For any connector type not covered above, inspect its create-connector request schema directly (use the full schema view in the API reference, not the summarized one) before assuming what fields it needs: a code+redirectUri field pair means it’s OAuth-based (see OAuth Connector Setup); anything else (a token, an API key, or host+credentials) means it isn’t.