SalesOS

Before Save Hooks

Synchronous allow / deny / patch calls to your endpoint or function before a record is saved

List

GET
/v1/before-save-hooks

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

curl -X GET "https://api.salesos.org/v1/before-save-hooks" \
  -H "Authorization: Bearer <token>"

BeforeSaveHookViewArray

[
  {
    "id": "string",
    "organizationId": "string",
    "name": "string",
    "description": "string",
    "objectType": "string",
    "operations": [
      "string"
    ],
    "url": "string",
    "functionId": "string",
    "timeoutMs": 0,
    "failureMode": "string",
    "position": 0,
    "isActive": true,
    "createdById": "string",
    "lastInvokedAt": "2019-08-24T14:15:22Z",
    "createdAt": "2019-08-24T14:15:22Z",
    "updatedAt": "2019-08-24T14:15:22Z",
    "circuit": {
      "state": "CLOSED",
      "failures": 0,
      "retryAt": "2019-08-24T14:15:22Z"
    },
    "managedBy": {
      "installationId": "string",
      "componentId": "string",
      "appId": "string",
      "appName": "string",
      "appSlug": "string"
    }
  }
]

Register a hook; the signing secret is returned once

POST
/v1/before-save-hooks

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Request Body

application/jsonRequired
nameRequiredstring
Maximum length: 120
descriptionstring
Maximum length: 1000
objectTypeRequiredstring

LEAD | CONTACT | ACCOUNT | OPPORTUNITY | TASK | CASE | custom:

operationsRequiredarray<array<string>>
urlstring

https:// endpoint that receives the proposed record (omit when functionId is set)

Maximum length: 2048
functionIdstring

A serverless function that decides instead of a URL (same {allow, patch, message} contract). Empty string switches back to url.

timeoutMsnumber
Default: 3000Minimum: 250Maximum: 5000
failureModestring
Default: "FAIL_OPEN"Value in: "FAIL_OPEN" | "FAIL_CLOSED"
positionnumber

Hooks on the same object run in ascending order

Minimum: 0Maximum: 1000
isActiveboolean
curl -X POST "https://api.salesos.org/v1/before-save-hooks" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Credit check",
    "description": "string",
    "objectType": "OPPORTUNITY",
    "operations": [
      [
        "CREATE",
        "UPDATE"
      ]
    ],
    "url": "string",
    "functionId": "string",
    "timeoutMs": 3000,
    "failureMode": "FAIL_OPEN",
    "position": 1000,
    "isActive": true
  }'

BeforeSaveHookWithSecret

{
  "id": "string",
  "organizationId": "string",
  "name": "string",
  "description": "string",
  "objectType": "string",
  "operations": [
    "string"
  ],
  "url": "string",
  "functionId": "string",
  "timeoutMs": 0,
  "failureMode": "string",
  "position": 0,
  "isActive": true,
  "createdById": "string",
  "lastInvokedAt": "2019-08-24T14:15:22Z",
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z",
  "secret": "string"
}

Get

GET
/v1/before-save-hooks/{id}

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Path Parameters

idRequiredstring
curl -X GET "https://api.salesos.org/v1/before-save-hooks/<string>" \
  -H "Authorization: Bearer <token>"

BeforeSaveHookView

{
  "id": "string",
  "organizationId": "string",
  "name": "string",
  "description": "string",
  "objectType": "string",
  "operations": [
    "string"
  ],
  "url": "string",
  "functionId": "string",
  "timeoutMs": 0,
  "failureMode": "string",
  "position": 0,
  "isActive": true,
  "createdById": "string",
  "lastInvokedAt": "2019-08-24T14:15:22Z",
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z",
  "circuit": {
    "state": "CLOSED",
    "failures": 0,
    "retryAt": "2019-08-24T14:15:22Z"
  },
  "managedBy": {
    "installationId": "string",
    "componentId": "string",
    "appId": "string",
    "appName": "string",
    "appSlug": "string"
  }
}

Update

PATCH
/v1/before-save-hooks/{id}

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Request Body

application/jsonRequired
namestring
Maximum length: 120
descriptionstring
Maximum length: 1000
objectTypestring

LEAD | CONTACT | ACCOUNT | OPPORTUNITY | TASK | CASE | custom:

operationsarray<string>

Items: at least 1.

urlstring

https:// endpoint that receives the proposed record (omit when functionId is set)

Maximum length: 2048
functionIdstring

A serverless function that decides instead of a URL (same {allow, patch, message} contract). Empty string switches back to url.

timeoutMsnumber
Default: 3000Minimum: 250Maximum: 5000
failureModestring
Default: "FAIL_OPEN"Value in: "FAIL_OPEN" | "FAIL_CLOSED"
positionnumber

Hooks on the same object run in ascending order

Minimum: 0Maximum: 1000
isActiveboolean

Path Parameters

idRequiredstring

Header Parameters

Idempotency-Keystring

Unique key (a UUID is ideal) that makes this write safe to retry for 24 hours: a retry with the same body replays the original response (Idempotent-Replayed: true); the same key with a different body is a 409.

Maximum length: 255
curl -X PATCH "https://api.salesos.org/v1/before-save-hooks/<string>" \
  -H "Idempotency-Key: <string>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Credit check",
    "description": "string",
    "objectType": "OPPORTUNITY",
    "operations": [
      "CREATE",
      "UPDATE"
    ],
    "url": "string",
    "functionId": "string",
    "timeoutMs": 3000,
    "failureMode": "FAIL_OPEN",
    "position": 1000,
    "isActive": true
  }'

BeforeSaveHookView

{
  "id": "string",
  "organizationId": "string",
  "name": "string",
  "description": "string",
  "objectType": "string",
  "operations": [
    "string"
  ],
  "url": "string",
  "functionId": "string",
  "timeoutMs": 0,
  "failureMode": "string",
  "position": 0,
  "isActive": true,
  "createdById": "string",
  "lastInvokedAt": "2019-08-24T14:15:22Z",
  "createdAt": "2019-08-24T14:15:22Z",
  "updatedAt": "2019-08-24T14:15:22Z",
  "circuit": {
    "state": "CLOSED",
    "failures": 0,
    "retryAt": "2019-08-24T14:15:22Z"
  },
  "managedBy": {
    "installationId": "string",
    "componentId": "string",
    "appId": "string",
    "appName": "string",
    "appSlug": "string"
  }
}

Remove

DELETE
/v1/before-save-hooks/{id}

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Path Parameters

idRequiredstring
curl -X DELETE "https://api.salesos.org/v1/before-save-hooks/<string>" \
  -H "Authorization: Bearer <token>"

DeletedResponse

{
  "deleted": true
}

Rotate

POST
/v1/before-save-hooks/{id}/rotate-secret

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Path Parameters

idRequiredstring
curl -X POST "https://api.salesos.org/v1/before-save-hooks/<string>/rotate-secret" \
  -H "Authorization: Bearer <token>"

SecretResponse

{
  "secret": "string"
}

Send a sample record; nothing is saved. Returns the decision, request and response

POST
/v1/before-save-hooks/{id}/test

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Request Body

application/jsonRequired
operationstring
Value in: "CREATE" | "UPDATE" | "DELETE"
recordobject

Sample proposed record

previousobject

Sample stored record (updates and deletes)

Path Parameters

idRequiredstring

Header Parameters

Idempotency-Keystring

Unique key (a UUID is ideal) that makes this write safe to retry for 24 hours: a retry with the same body replays the original response (Idempotent-Replayed: true); the same key with a different body is a 409.

Maximum length: 255
curl -X POST "https://api.salesos.org/v1/before-save-hooks/<string>/test" \
  -H "Idempotency-Key: <string>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "CREATE",
    "record": {},
    "previous": {}
  }'

HookTestResult

{
  "invocationId": "string",
  "status": "string",
  "decision": "ALLOW",
  "message": "string",
  "patch": {},
  "statusCode": 0,
  "latencyMs": 0,
  "errorCode": "string",
  "errorMessage": "string",
  "requestHeaders": {
    "property1": "string",
    "property2": "string"
  },
  "requestBody": {},
  "responseBody": "string"
}

Invocations page

GET
/v1/before-save-hooks/{id}/invocations

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Path Parameters

idRequiredstring

Query Parameters

pagestring
Default: 1
limitstring
Default: 20
statusstring
Value in: "SUCCEEDED" | "FAILED" | "TIMEOUT" | "BLOCKED" | "REJECTED" | "CIRCUIT_OPEN"
curl -X GET "https://api.salesos.org/v1/before-save-hooks/<string>/invocations?page=1&limit=20&status=SUCCEEDED" \
  -H "Authorization: Bearer <token>"

ExtensionInvocationPage

{
  "data": [
    {
      "id": "string",
      "organizationId": "string",
      "kind": "string",
      "customActionId": "string",
      "beforeSaveHookId": "string",
      "source": "string",
      "status": "string",
      "objectType": "string",
      "recordId": "string",
      "userId": "string",
      "requestUrl": "string",
      "requestHeaders": null,
      "requestBody": null,
      "statusCode": 0,
      "responseBody": "string",
      "errorCode": "string",
      "errorMessage": "string",
      "latencyMs": 0,
      "attempts": 0,
      "outcome": null,
      "replayOfId": "string",
      "createdAt": "2019-08-24T14:15:22Z"
    }
  ],
  "total": 0,
  "page": 0,
  "limit": 0,
  "totalPages": 0,
  "retentionDays": 0
}

Invocation

GET
/v1/before-save-hooks/{id}/invocations/{invocationId}

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Path Parameters

idRequiredstring
invocationIdRequiredstring
curl -X GET "https://api.salesos.org/v1/before-save-hooks/<string>/invocations/<string>" \
  -H "Authorization: Bearer <token>"

ExtensionInvocation

{
  "id": "string",
  "organizationId": "string",
  "kind": "string",
  "customActionId": "string",
  "beforeSaveHookId": "string",
  "source": "string",
  "status": "string",
  "objectType": "string",
  "recordId": "string",
  "userId": "string",
  "requestUrl": "string",
  "requestHeaders": null,
  "requestBody": null,
  "statusCode": 0,
  "responseBody": "string",
  "errorCode": "string",
  "errorMessage": "string",
  "latencyMs": 0,
  "attempts": 0,
  "outcome": null,
  "replayOfId": "string",
  "createdAt": "2019-08-24T14:15:22Z"
}

Re-send the logged payload as a test (the original save is not re-run)

POST
/v1/before-save-hooks/{id}/invocations/{invocationId}/replay

Authorization

AuthorizationRequiredBearer <token>

Session token from the SalesOS web app.

In: header

X-API-Key<token>

API key from Settings → API Keys. Authorization: ApiKey <key> is also accepted. Each operation lists the scope it needs under x-api-key-scopes.

In: header

Path Parameters

idRequiredstring
invocationIdRequiredstring

Header Parameters

Idempotency-Keystring

Unique key (a UUID is ideal) that makes this write safe to retry for 24 hours: a retry with the same body replays the original response (Idempotent-Replayed: true); the same key with a different body is a 409.

Maximum length: 255
curl -X POST "https://api.salesos.org/v1/before-save-hooks/<string>/invocations/<string>/replay" \
  -H "Idempotency-Key: <string>" \
  -H "Authorization: Bearer <token>"

HookTestResult

{
  "invocationId": "string",
  "status": "string",
  "decision": "ALLOW",
  "message": "string",
  "patch": {},
  "statusCode": 0,
  "latencyMs": 0,
  "errorCode": "string",
  "errorMessage": "string",
  "requestHeaders": {
    "property1": "string",
    "property2": "string"
  },
  "requestBody": {},
  "responseBody": "string"
}