Managing a Custom Source

Share a custom source with groups, rename it, read back its records, and delete single records between syncs.

Once a custom source is created and syncing, a few calls cover everything else you'll need to run it: deciding who can see its records, renaming it, looking up its object types, reading back what you've pushed, and removing records between full syncs.

This guide extends Creating a Custom Source. It assumes you have a source and its sourceId.

Endpoints

All endpoints below are relative to the API root https://api.getguru.com/api/v1/ and use basic auth with your Guru user and API token.

EndpointPurpose
GET /sources/{sourceId}/groupsList the groups that can see the source.
POST /sources/{sourceId}/groupsGive a group access to the source.
DELETE /sources/{sourceId}/groups/{groupId}Remove a group's access.
PUT /sources/{sourceId}/configRename the source.
GET /sources/{sourceId}/objecttypesList the source's object types and their ids.
GET /sources/{sourceId}/types/{objectTypeId}/recordsList the records of one object type.
GET /sources/{sourceId}/types/{objectTypeId}/records/{externalId}Read one record.
GET /sources/{sourceId}/types/{objectTypeId}/recordsearchFind records by title or content.
DELETE /sources/{sourceId}/records/{externalId}Delete one record on a single-type RECORD source.

Give groups access to the source

A new source is visible only to the user who created it, who is its owner. To let other people find its records in search and get answers from them, give their Guru groups access to the source.

curl -X POST "https://api.getguru.com/api/v1/sources/$SOURCE_ID/groups" \
  -u $GURU_USER:$GURU_TOKEN \
  -H "Content-Type: application/json" \
  -d '{"groupId": "b97736e3-6139-4e49-b2b8-8d6b1d9d80ec"}'

The group gets the Viewer role on the source. The response describes the new access:

{
  "groupId": "b97736e3-6139-4e49-b2b8-8d6b1d9d80ec",
  "groupName": "Support Team",
  "group": {"id": "b97736e3-6139-4e49-b2b8-8d6b1d9d80ec", "name": "Support Team", ...},
  "role": "MEMBER",
  "objectRole": {"name": "Viewer", ...}
}
FieldDescription
groupIdRequired. The Guru group's id. An id that matches no group on your team fails with a 404.
roleOptional. MEMBER, the only value accepted; anything else fails with a 400.

Granting a group that already has access changes nothing and succeeds. GET /sources/{sourceId}/groups lists every group with access, including the owner's, and DELETE /sources/{sourceId}/groups/{groupId} removes one and returns 204 No Content.

📘

Native permissions sources don't need group access

On a source with native permissions, record permissions decide who sees each record, so you don't need to grant groups access to the source.

Rename a source

Send the new name to the config endpoint. The type must match the source's type, CUSTOM; a different type fails with a 400.

curl -X PUT "https://api.getguru.com/api/v1/sources/$SOURCE_ID/config" \
  -u $GURU_USER:$GURU_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "type": "CUSTOM",
    "name": "Acme NetSuite - All Customers"
  }'

The response is the updated source. Everything else about the source, including trackStatus and its sync history, stays as it was.

This call doesn't change a source's object types, fields, facets, or templates. To change the structure, create a new source with the new definition and sync into it.

Look up object types

If you've lost an object type id, list the source's object types:

curl "https://api.getguru.com/api/v1/sources/$SOURCE_ID/objecttypes" \
  -u $GURU_USER:$GURU_TOKEN

Each entry has the object type's name, its id, and its fields.

Read back records

These calls read what's stored in the source, which is useful for checking that a sync did what you expected. They return every record, whatever its native permissions, so treat them as tools for the source's owner rather than a way to see what a particular user can find.

List the records of one object type, using standard pagination. Each entry has the record's externalId and title:

curl "https://api.getguru.com/api/v1/sources/$SOURCE_ID/types/$OBJECT_TYPE_ID/records" \
  -u $GURU_USER:$GURU_TOKEN

Read one record by its externalId, passed as $RECORD_EXTERNAL_ID. The response has the record's externalId, title, url when it has one, and content, the text search and answers draw on. It can lag behind a push you just made; to confirm an update landed, check that the version in the record's metadata went up.

curl "https://api.getguru.com/api/v1/sources/$SOURCE_ID/types/$OBJECT_TYPE_ID/records/$RECORD_EXTERNAL_ID" \
  -u $GURU_USER:$GURU_TOKEN

Find records by title or content:

curl "https://api.getguru.com/api/v1/sources/$SOURCE_ID/types/$OBJECT_TYPE_ID/recordsearch?searchTerms=refund&searchField=CONTENT" \
  -u $GURU_USER:$GURU_TOKEN
ParameterDescription
searchTermsRequired. The text to look for.
searchFieldOptional. TITLE to match record titles, the default, or CONTENT.
maxResultsOptional. The most records to return.

Delete records between full syncs

A full sync closed with COMPLETE removes every record you didn't push, but an incremental sync removes nothing. When records are deleted in your system and you sync incrementally, remove them from Guru with a full sync on that object type that pushes nothing new. Touch each record you want to keep, leave out the ones to remove, and close with COMPLETE:

  1. Open a full sync on the object type with START (see Open the sync).

  2. Touch every record to keep. A touch sends no body and doesn't re-upload anything:

    curl -X PUT "https://api.getguru.com/api/v1/sources/$SOURCE_ID/objecttypes/$OBJECT_TYPE_ID/objects/$RECORD_EXTERNAL_ID?syncNumber=$SYNC_NUMBER" \
      -u $GURU_USER:$GURU_TOKEN

    A touch returns 204 No Content. Take the ids to keep from your own system, or from the record list above.

  3. Close the sync with COMPLETE. Every record of that object type you didn't touch is removed.

This works on any custom source. Syncs run per object type, so a full sync on one object type never removes records of another. If you touch every record except one, only that one is removed.

If you sync incrementally, run this cleanup on a schedule, for example nightly or weekly, depending on how quickly deleted records need to disappear from Guru. Until the next cleanup, records deleted in your system stay searchable in Guru.

Delete a single record directly

On a source whose only object type is a RECORD type, such as a source of uploaded files, you can also delete one record without a sync:

curl -X DELETE "https://api.getguru.com/api/v1/sources/$SOURCE_ID/records/$RECORD_EXTERNAL_ID" \
  -u $GURU_USER:$GURU_TOKEN

A successful delete returns 204 No Content. Afterward the record's metadata has no externalChecksum, as for a record removed by a sync.

❗️

Direct delete is limited to single-type RECORD sources

This endpoint works only when the source has exactly one object type and that type is RECORD. On a STRUCTURED object type it fails with a 400 (Cannot delete this source record), and on a source with more than one object type it fails with a 400 (Unexpected number of object types), whether or not a sync is open. For those sources, use a full sync as described above.

To remove a whole source and everything in it, see Deleting a source.