Creating an organization requires
create permission on the organization the token belongs to. Firing a sync trigger requires admin permission on the domain mapping or on its source system integration. Neither is part of the default API service account role; ask Twine to grant them to the role you provision with.1. Create the organization
POST /v1/org creates a new organization as a child of the organization your token belongs to.
Every other provisioning endpoint lives under /v1/org/... and acts on the organization of the token making the request, not on an id in the URL. To configure the new organization, you therefore need a token that belongs to it. Ask for one in the same request by adding a role with create_in set to child and create_api_refresh_token set to true:
roles[].tokens[], with its jwt and jti. This is the only time the refresh token is readable, so store it in your own secret store straight away. Exchange it for an access token as described in Authentication, and use that access token for the remaining steps.
2. Create the system integrations
A system integration is one connection to one system. Look up thesystem_id of each system you need with GET /v1/systems, then create an integration for each with POST /v1/org/system-integrations.
The Twine system integration
Almost every organization needs a system integration for Twine itself. It is the side of a domain mapping that stands for data held in Twine, so it is what lets you read data synced from a source system through the API, and what replicates data you push through the API on to a target system. It takes no credentials:External systems
For an external system, send its credentials inauth and its system-specific settings in system_custom. Both are discriminated by slug, and the fields each system accepts are listed in the endpoint reference.
template_id to create the integration from a template, or create_default_mappings to start from the system’s default property mappings.
If your customer holds the credentials rather than you, leave auth out and send them a credentials link once the integration exists.
Letting your customer enter credentials
POST /v1/org/system-integrations/{id}/credentials-link returns a url your customer opens to enter the integration’s credentials themselves, without a Twine login. You never see what they enter. Systems that sign in through the vendor send the customer there instead.
The link collects credentials only. For a system whose API can live on any host (Flex HRM, Agda PS, S3, SFTP), where the integration connects is yours to set, before you create the link: PATCH /v1/org/system-integrations/{id} with api_endpoint_url in auth (Flex HRM, Agda PS) or the host in system_custom (S3, SFTP). Until then the link request answers 422. Your customer sees that endpoint or host on the form, read-only, so they can tell you if it is not theirs.
The link is valid until expires_at (5 days) and can be submitted once. Create a new one if it expires, or whenever the credentials need to be entered again. Creating a link requires admin permission on the system integration, since whoever holds it can set the credentials.
Stored secrets are never returned by the API. See Changing credentials and endpoints before updating an integration later.
3. Create the domain mappings
A domain mapping moves one domain of data from a source system integration to a target system integration, for example employees from an HR system into Twine. Create one withPOST /v1/org/domain-mappings:
- Scheduled. Give the trigger a
cron_expressionand setenabledtotrue.enableddefaults tofalse, so a trigger created without it does not run until it is enabled. - Manual. Leave
cron_expressionout. The trigger then only runs when you fire it (see the next step). This suits initial loads, testing, and migrations where you want to control exactly when data moves.
sync_triggers is used when creating a domain mapping. Add conditions to filter out entities this mapping should not process.
4. Run a sync
A scheduled trigger runs on its own. To run a sync now, whether the trigger is scheduled or manual, fire it:job_id of the sync. Follow its progress with GET /v1/org/jobs/{job_id}. If a sync is already running for the same system integration and domain, the request is answered with 409 Conflict; retry once that sync has finished.
Changing credentials and endpoints
Update an integration withPATCH /v1/org/system-integrations/{id}. Only the fields you send with a value change. A field left out, or sent as null, keeps its stored value, and this holds inside auth and system_custom too. You can therefore rename an integration or change one setting without knowing its credentials.
Writing credentials requires admin permission on the system integration. A role without it can update everything else.
PUT /v1/org/system-integrations/{id} is deprecated. It requires auth and system_custom in every request; a null in either keeps the stored value. Use PATCH for new integrations.api_client_id is always kept, since it identifies an account rather than proving access to it, and so are webhook secrets, which authenticate requests coming into Twine rather than going out.