Skip to content

Properties

authentication_methodstring

Type of authentication used.

Possible values:
oauth2api_keyoauth2_client_credentialskeka_oauth
contextRecord<string, any>

The context of the integrated account. You can find these in the Variables section of an integrated account in the Truto UI.

Example: {"zendesk_subdomain":"truto"}
created_atstring · date-time

The date and time when the integrated account was created.

Example: 2021-08-10T10:00:00.000Z
environment_integration_idstring

The ID of the environment integration (installed integration).

Example: b179ad55-db02-4bd4-b7a4-d2c173eee9ae
idstring · uuid

The ID of the integrated account.

Example: 1ba1f401-7183-47c5-9e39-e8e257e3c795
is_sandboxboolean

Whether the integrated account is in sandbox mode or not. Sandbox integrated accounts do not allow any "write" operations.

Example: false
last_action_resultobject

The results of the post install and validation steps that ran on the integrated account.

last_errorstring

The last error that occurred while running the post install or validation steps.

last_forbidden_errorobject

Details of the most recent 403 Forbidden returned by the third-party API for this account, or null if the most recent call succeeded. Cleared automatically on the next successful call.

descriptionstring

The sentence the live 403 carried, recorded so this row reads the same as the call did.

Example: Access forbidden. This operation requires a role or privilege granted in the provider's own admin console, not an OAuth scope — reconnecting will not change it.
methodstring

The method that was attempted on that resource.

Example: list
missing_any_of_scopesstring[]

Scopes of which the operation needs any one, where the grant holds none. Kept apart from missing_scopes so alternatives are never reported as though all were required.

Example: ["Chat.Read.All","Chat.ReadWrite.All"]
missing_scopesstring[]

The scopes required by this resource and method that the provider did not confirm as granted.

Present only when both halves of that comparison are known: the provider echoed the scopes it granted, and this resource and method declares required scopes. It is absent — not empty — otherwise, which includes api_key and OAuth1 connections (no scope grant exists), OAuth2 and jwt_bearer connections where the provider omits scope from its token response, resources and methods that declare no required scopes, and requirements that are not OAuth scopes at all (refusal_basis: non_scope_requirement — see permission_vocabulary), where no diff is run and required_permissions carries the answer instead.

An empty array therefore means "no all-of scope is missing", while an absent field means "cannot be determined" — two different statements. Read refusal_basis for the one question this field cannot answer on its own, "was anything missing at all": an empty array sits beside a populated missing_any_of_scopes whenever the whole shortfall is an unmet any-of requirement, so on refusal_basis: scopes_missing an empty array does not mean every permission was granted. It means that on refusal_basis: scopes_satisfied, and only there. Do not default an absent missing_scopes to [] either: that reads back as "nothing is missing" about a request that was refused.

Truto's comparison is an inference over integration configuration. The provider's own account of the refusal is the authoritative one, and Truto relays it without interpreting it: raw_response (the error body verbatim) and message (its human text) on the 403 itself, and a capped copy of the body on this record as raw_response_excerpt. message is not persisted, so re-run the call to see it.

Truto deliberately does not lift a "code" or a "documentation link" out of that body. Which key in an arbitrary provider's error shape is the important one has no correct general answer, and a confidently wrong one placed above a correct body is the same failure as reporting a scope missing that was never checked.

Example: ["crm.objects.contacts.read"]
occurred_atstring · date-time

When the forbidden response was recorded.

Example: 2021-08-10T10:00:00.000Z
permission_vocabularystring

Which vocabulary required_permissions is written in, and therefore what the remedy is. Only oauth_scope is fixed by reconnecting: api_key_permission is granted to the API key in the provider, and role_label in the provider's own admin console.

x-extensible-enum for the same reason as refusal_basis above: this is a stored value, and a rollback can serve one written by a build that knew a fourth vocabulary. Keep a default branch.

Example: role_label
raw_response_excerptstring

A capped copy of the integration's own error body, so this record shows what the provider said and not only what Truto inferred about it. Truncated with a trailing … truncated marker past 2,048 bytes of UTF-8, because this record is deserialized on every proxy and unified call that resolves the account and that cost is what the bound exists to control. Bytes, not characters: 2,048 characters of CJK is about 6 KB stored, so a character bound would charge one language three times what it charges another. Expect fewer characters than 2,048 for any non-ASCII body. The 2,048 covers the marker as well, so the stored value never exceeds it.

A truncated excerpt is not parseable. It is a byte prefix of a serialized body with a marker on the end, so JSON.parse on this field throws whenever truncation happened — which the trailing … truncated is how you detect. Render it as text. An untruncated excerpt of a JSON body does parse, but nothing guarantees this field is JSON at all: a plain-text or HTML error body is stored exactly as it arrived.

Absent when the refusal carried no body. Not forwarded to the connections widget: it is a raw provider string, which is what connections.show_error_details exists to keep away from an end user.

Note that "every remote 403 carries an insight" and "every remote 403 leaves a record here" are different statements. A Proxy API custom method and a Custom API both carry the live insight, but a Custom API names no resource or method, and writing {resource: "", method: ""} would replace a record naming a real call with one naming none — so no record is written for those. Read the insight on the response for them.

Example: {"error":"insufficient_scope","error_description":"Token does not have crm.objects.contacts.write scope"}
refusal_basisstring

Which of the states below produced this record, so a reader never has to infer it from the presence or emptiness of missing_scopes. Absent on rows recorded before Truto stored it — and on such a row an empty missing_scopes cannot be read as "compared, nothing missing", because it was also written when nothing had been compared at all.

An open set, and x-extensible-enum rather than enum says so to a code generator as well as to a reader. Prose asking for a default branch is not something a generator reads, and a closed union here can be violated by design: the read path deliberately accepts an unrecognised value so a row written by a newer build stays readable after a rollback, and the older build then serves that value straight back on this field. The values below are what Truto writes today. Keep a default branch.

The live truto_error_insight.forbidden_error.value.refusal_basis keeps a closed enum, and the asymmetry is the point: a running build always emits its own documented set, while a stored row can carry a value the build reading it never wrote.

Example: non_scope_requirement
required_any_of_permissionsstring[]

Permissions of which the operation needs any one, kept apart from required_permissions for the same reason.

Example: ["Chat.Read.All"]
required_permissionsstring[]

What this operation requires, whether or not a comparison was possible. Always paired with permission_vocabulary, since the same string means "reconnect and grant this", "add this to your API key" or "ask an admin for this role" depending on which vocabulary it is written in.

Example: ["Agent","Customers Read"]
resourcestring

The third-party resource that was forbidden.

Example: contacts
regionstring

The region where the integrated account is placed.

Example: wnam
Possible values:
wnamenamapaceu
statusstring

Status of the integrated account.

  • active - Everything is fine and the account should work
  • connecting - Post install and validation steps are being run
  • post_install_error - There was an error while running post install steps
  • validation_error - There was an error while running validation steps
  • needs_reauth - There was an error while refreshing the credentials in case of OAuth authentication or the credentials are no longer valid in other authentication methods. The integrated account needs to be reauthorized.
Possible values:
activeconnectingpost_install_errorvalidation_errorneeds_reauth
tenant_idstring

The ID of the tenant.

Example: acme-1
updated_atstring · date-time

The date and time when the integrated account was last updated.

Example: 2021-08-10T10:00:00.000Z