DAM Wiki

Keepeek API

Keepeek SAS (Papirfly group) · Paris, France · Founded 2008 · subsidiary of Papirfly Group (majority-owned by Verdane)Verified 2026-09-30 · 122 sources
  • SaaS
  • On-premise
  • Enterprise
  • REST API
  • OpenAPI spec
  • Webhooks (Custom)
  • SAML · OIDC SSO
Complete · 7 of 7 pages
122sources
1API specs
09-30verified 2026
Official website ↗Keepeek alternatives →

Scope: the Keepeek REST API ("Kpk API") exposed by every Keepeek DAM instance, plus the Keepicker web component. Papirfly platform APIs (Keepeek's parent group) are out of scope.

At a glance

API styles
REST, hypermedia-driven HAL+JSON (application/hal+json;version=1) S11 S12. Supports GET/PUT/POST/DELETE; no PATCH S10 S2. No GraphQL found.
Base URL(s)
Per instance: https://{tenant}.keepeek.com/api (vendor examples use {KeepeekInstance}) S4 S11. Entry points below /api: /api/dam (authenticated DAM), /api/public (anonymous), /api/share/{tokenId} (share-token access), /api/stat (statistics), /api/geo (geocoding), /api/recognition (face recognition) S2 S41. Download shortcut outside /api: /download-express S26. Custom instance domains: Unknown.
Current version(s) & deprecations
One API representation version: 1 (in the media type). A future API version would not be backward compatible and would be negotiated through Accept S12. Features are tagged with the Keepeek release that introduced them (4.0.0 → 4.124.0 in the docs) S3; the doc instance runs release 4.146.0 S41. No deprecation notice found.
Auth methods
(1) HTTP Basic with a Keepeek user login/password; (2) JWT Bearer signed with a shared secret (HMAC ≥ SHA-256) — marketed as "OAuth 2 / Token JWT", available since back office 4.28.0 and requiring platform configuration by Keepeek S5 S6. Keepeek recommends JWT over Basic S7.
Token lifetime / refresh
JWT lifetime is set by the client (exp claim; the vendor sample uses 60 s). No refresh flow — the integrator re-signs tokens S6. Maximum accepted lifetime: Not public.
Scopes / permission model
No OAuth scopes: every call runs as the Keepeek user identified by the Basic credentials or the JWT login claim, with that user's group rights (folder rights, statuses, ABAC) S5 S6 S48. Resources expose the caller's permission (e.g. READ/WRITE/ADMIN) S2 S32. Optional header X-KPK-CLIENT-ID checks the user's access to a given user interface S5.
Official spec
Swagger 2.0 at /api/doc/swagger.json, rendered at test-doc.keepeek.com/api/doc S1 S2 S8; archived copy on DAM Wiki: API spec downloads. Resource-by-resource guide in the help center "Keepeek - API" section S3. Postman sample attached to a help article S37 (not copied — see specs/README).
Rate limits
Not public — no limits, quotas or 429 behaviour documented S3. Responses pass through a Gravitee API gateway (X-Gravitee-* headers) but no rate-limit headers were returned S41. Documented functional caps instead: see Limits & quirks.
Pagination
Page-based: page (1-based) and size (default 20), HAL links first/previous/next/last, totalCount S2 S16 S17. Maximum size: Not public.
Webhooks / events
Not in the documented API — no webhook, callback or event resource in the spec or the API guide S2 S3; outbound notifications are possible through custom scripts configured on the instance S115. Polling via search on updateDate/importDate ranges S16. An event-messaging integration (Solace) is marketed without technical detail S100.
Official SDKs
None for server-side use. Official front-end component: Keepicker web component (@keepeek/keepicker-react, npm) S43. Keepeek suggests the generic traverson JS library for HAL navigation S11.
Sandbox / trial access
No public sandbox. An API user is created by an administrator of the customer's instance S4. The Swagger UI has no "try it" against the doc instance without credentials (401) S41.

Authentication

Credentials S4

  1. An administrator creates a regular Keepeek user for the integration: Settings → Users → Create a user. There is no separate "API key" object; the API user is a normal user whose group rights bound what the integration can see and do S4 S48.
  2. Check it with GEThttps://{tenant}.keepeek.com/api/dam and Authorization: Basic base64(login:password) — 200 means OK S4. Without credentials /api/dam returns 401 {"code":"security-notAuthorized"} S41.

JWT ("OAuth 2 / Token JWT") S5 S6

AspectDetail
ActivationNeeds platform configuration by the customer's Keepeek project manager; a secret is shared between Keepeek and the customer
SigningHMAC only (RSA not supported), minimum SHA-256; the shared key must be alphanumeric only
Claims (vendor sample)client_id (instance identifier), login (Keepeek login of the user to impersonate), iat, exp
SendingAuthorization: Bearer <jwt> on every call; Keepeek validates it with the same key
Errors401 = incomplete/invalid/expired authorization, including an expired client secret requiring renewal S7

This is a self-issued, shared-secret JWT scheme, not an OAuth authorization server flow: there is no token endpoint, no authorization code and no refresh token in the API documentation S6.

Identity provider (UI login, Keepicker) — each instance publishes GET/api/public/iam-configuration pointing to a Keycloak realm on auth.keepeek.com (OIDC discovery + SAML IdP descriptor), and GET/api/public/sso-configuration (ssoEnabled, googleOAuthEnabled) S41 S42. The Keepicker component authenticates through a Keycloak client (keycloak-client-id, optional keycloak-idp for an SSO button) S43. Whether third-party back-ends may call /api/dam with Keycloak-issued access tokens is Unknown Unverified (not documented; the realm's discovery document lists generic Keycloak grants that say nothing about API acceptance).

Access-control errors specific to UIs S9: 401 error.account.to_be_validated, user-need-registration-{hash} (points to a registration form), user-access-forbidden-for-ui.

Core resources

Paths relative to https://{tenant}.keepeek.com. The spec has 266 paths / 378 operations (227 GET, 65 POST, 60 DELETE, 26 PUT) S2. Keepeek asks clients to follow _links rather than build URIs, as URI layout may change S11. Minimum release per feature from the API guide S3.

ResourceEndpointsNotes
Entry pointsGET/api, GET/api/dam, GET/api/public, GET/api/stat, GET/api/geo, GET/api/recognition/api returns version, release and links; unauthenticated S11 S41
Media (assets)GET/POST/api/dam/medias; GET/PUT/DELETE/api/dam/medias/{mediaId}GET/medias lists only Published, readable media; create from an uploaded file (from link) and/or a form (kpk:form); embedAllMetadata, embeddedFolders flags S2 S20
Metadata valuesGET/api/dam/medias/{id}/metadatas, GET/PUT…/metadatas/{metadataId}One field per PUT; thesaurus values passed as [{id,title}] S20
Metadata schema (forms / fields)GET/api/dam/forms, /forms/{formId}, /forms/{formId}/fields[/{fieldId}], /forms/lookups[/{id}], /forms/{formId}/extensions; GET/api/dam/sheet-fields[/{id}]Read-only in the API (no field creation) S2
Thesaurus (controlled vocabularies)GET/api/dam/thesauruses[/{id}], PUT/thesauruses/{id}; GET/api/dam/thesaurus-tree[/{id}], POST/thesaurus-tree/{id}/children, DELETE/thesaurus-tree/{id}Hierarchical, multilingual (titles, descriptions, synonyms per locale); terms ≤ 100 characters S36
Statuses & labelsGET/api/dam/medias/custom-statuses[/{id}]; GET/api/dam/medias/labels[/{id}]; GET/POST/medias/{id}/labels, DELETE…/labels/{labelId}Status change goes through bulk (kpk:custom-status link) S2 S23
SearchGET/api/dam/search/media, /search/advanced…, /search/folder, /search/basket, /search/board, /search/user, /search/group, /search/trash, /search/autocomplete, /search/facet-fields[/{id}]See Search & querying S2 S16 S18
Folders (classification plan)GET/POST/api/dam/folder-tree, GET/DELETE/folder-tree/{nodeId}, GET/POST…/children, PUT…/order-children; GET/api/dam/folders[/{id}], PUT/DELETE/folders/{id}; GET/POST/DELETE/folders/{id}/medias[/{mediaId}]; …/responsible-usersFolder rights levels incl. ADMIN (4.61.0+); flat folder list may return empty above an unstated size S35
UploadsPOST/api/dam/files, GET/PUT/api/dam/files/{fileId}Temporary file descriptor, then create media S21
VersionsGET/POST/api/dam/medias/{id}/file-versions, GET/PUT/DELETE…/file-versions/{versionId}Replace/restore original file S2
Renditions & linksGET/medias/{id}/permalinks[/{id}], /embed, /player; thumbnail links kpk:medium/large/xlarge/preview/whr in media JSONSee Uploads & binaries S2 S27
Downloads & exportsPOST/api/dam/users/{userId}/selections/{selectionId}/exports, GET/users/{userId}/exports/{id}; POST/GET/DELETE/api/dam/download-requests[/{id}] (4.54.0+); GET/download-express?mid=…Export formats per media type via …/media-types/{type}/export-formats S25 S26 S32
Selections & bulkPOST/api/dam/users/{userId}/selections, POST/DELETE…/medias-collection, GET…/bulks/fields, POST…/bulks; /api/dam/bulk-jobsBulk operation types UPDATE, AUTOTAG S2 S23 S24 S38
Baskets (collections)GET/POST/api/dam/baskets, GET/PUT/DELETE/baskets/{id}, …/medias, …/medias-collection, …/tags, …/share, …/share/public, …/share/tokens, …/terms-of-use, …/usersPermission READ/WRITE/ADMIN; as-admin=true for admins S2 S16
Boards (kanban)GET/POST/api/dam/boards, GET/PUT/DELETE/boards/{id}, …/columns[/{id}]/medias S2
WorkflowsGET/api/dam/workflows[/{id}], GET/POST/DELETE/workflows/{id}/mediasRead + membership only; no step processing/approval endpoint in the spec S2
Validation requests/api/dam/classification-validation-requests (create/read; no delete); /api/dam/download-validation-requests; public variant /api/public/download-validation-requests (disabled by default) S2 S3
SharingMedia/basket share tokens …/share/tokens; share templates /api/dam/share/templates (+ allowed domains); anonymous token access /api/share/{tokenId}/… (shared media, basket, search, selections, exports, download requests)Tokens carry exportDefinition (none/BD/HD), activation/deactivation dates S28 S29 S30
Rights / terms of useGET/medias/{id}/terms-of-use, …/selections/{id}/terms-of-use, …/baskets/{id}/terms-of-useExports require acceptTermsOfUse; non-admins must give a usage S32. Rights configuration (ABAC, folder ACLs) not in the API S2
Users & groupsGET/api/dam/users[/{id}], PUT/DELETE/users/{id}, …/assigned-groups, …/additional-attributes, …/authorized-user-interfaces, …/thumbnail-templates; GET/api/dam/groups[/{id}], POST/groups/{id}/users, …/responsible-usersListing needs manager/admin; new users inactive until assigned group status=VALID; externally authenticated users are delete-only S31 S32
Attachments & relations…/medias/{id}/attachments (+ upload-link, download-link), …/blobs, …/media-links[/{id}]/medias, …/duplicates S2
Face recognitionPOST/api/recognition/detections; GET/api/dam/faces[/{id}], /api/dam/individuals[/{id}]Only with the face-recognition option S2 S3
StatisticsPOST/api/stat/hits, GET/api/stat/hit-types[/{id}[/schema]], GET/api/stat/search/hitDocumented as not requiring API authentication S33
ScriptsGET/api/dam/scripts[/{id}], GET/POST/api/dam/script-runs[/{id}]Run server-side scripts configured on the instance (4.50.0+) S34
Admin / config/api/dam/properties, /api/dam/user-interfaces (PUT), /api/dam/file-resources/{type}/{id} (admin), /api/dam/services/{id}/signatures, DELETE/api/dam/cache/{id}, /api/dam/wikis S2 S36
Semantic embeddingsPOST/api/dam/medias/{id}/embeddingsPresent in the spec without description — purpose Unknown S2 Unverified

Not exposed in the documented API: webhooks/event subscriptions, metadata-schema writes (forms and fields are read-only), rights configuration (folder ACLs, ABAC rules, statuses definitions), workflow template/step actions, SSO/IP-filtering settings S2.

Data model

  • Media: integer id; top-level technical properties (title, status, statusUpdateDate, permission, downloadLevel, width, height, resolution, orientation, mediaType (MIME), fileSize, totalSize, originalFileName, creationDate, updateDate, importDate, trashDate, duration, pageCount, colorSpace, latitude/longitude/address, duplicationStatus, thumbnailGenerationStatus, statViews, statDownloads, checkSums{md5,crc32}, formType, pointOfInterest, fileVersionCount…) S2.
  • Enumerations S2: status ∈ IMPORT, BASKET, DRAFT, PUBLISHED, ARCHIVED, TRASH (plus instance-defined custom statuses); permission ∈ READ, WRITE, PUBLISH, DELETE, ADMIN; downloadLevel ∈ NONE, BD (low def), HD; formType ∈ PICTURE, DOCUMENT, VIDEO, SOUND, RICH_MEDIA, OTHER.
  • Metadata: _embedded.metadata[] items {id, name, value, _links.kpk:field}; id is the field's internal name (e.g. title, legend); empty fields omitted unless embedAllMetadata=true S13 S20. Localized fields are addressed with a locale suffix in search (e.g. title.FR) S19; content language negotiated with Accept-Language / returned in Content-Language; writes target languages via Content-Language S15 S23.
  • Forms ("fiches"): each media has a metadata form (metamodel); field types TEXT, TEXT_AREA, HTML, HTML_AREA, DATE, DATETIME, NUMBER, EMAIL, URL, CHECK_BOX, SIMPLE_LIST, MULTIPLE_LIST, PERSON_LIST, THESAURUS, GEO, FIELD_SET; field flags mandatory, indexed, indexSuggest, forceSelection, editable, visible S2 S13 S23.
  • Taxonomy: hierarchical, multilingual thesauri attached to "microthesaurus" fields; nodes have numeric ids S16 S36. Folder tree (classification plan) with numeric folder ids; a media can be in several folders S11 S13. Labels, basket tags and statuses complete the taxonomy S2.
  • HAL conventions: CURIE prefix kpk (/api/doc/rels/{rel}); single embedded items are returned as an object unless forceArrays=true (4.20.0+) S11 S14.
  • Ephemeral resources: uploaded files, selections, exports, bulk jobs and API-created advanced searches expire and may be purged — do not persist their URIs S21 S19 S24 S32.

Search & querying

S16 unless noted.

AspectBehaviour
Full textq= over indexed fields, Lucene query-parser syntax (+, -, phrases; default OR); lq=true enables raw Lucene queries such as (title.FR:a OR title.FR:b) S2
Field queriesf=field:value (repeatable, AND), wildcards (title:li*), negation (title:-x), ranges [a TO b] on dates (RFC 3339 or epoch), numbers, ids
Filtersfq= restricts the scope without scoring: folderId:10 subtree, folderPath, formId, customStatusId, labelId, thesaurus:{field}:{node} subtree, basketId, workflowId, boardId/columnId, selectionId, associations:(…) types:(…) (≤ 1000 ids), width/height ranges, durationInSecond, facet: entries
FacetsReturned by default as configured in the back office; facet-fields= overrides (4.75.0+), facet-fields=[] suppresses them; facet-values-number ≤ 150 (400 otherwise) S16 S17
Sortingsort=field [desc], incl. statViews, statDownloads, fileSize, totalSize
Projectionfields= partial-response grammar, e.g. fields=id,title,_links{kpk:preview} or _embedded{metadata.byId(title,legend)} S13
Page sizesize default 20; maximum Not public S2
Deep paginationLimit Not public; collection resources (/medias, /folders) may return empty above an unstated total S20 S35 Unverified — partition by date ranges or folders
Advanced searchBuild criteria from GET/api/dam/search/advanced/criterias (modifiers such as EQUALS_ONE, CONTAINS_ONE/ALL/NONE, EMPTY, NOT_EMPTY, date presets, FROM_TO); POST/api/dam/search/advanced returns a TEMPORARY search (expiring), then GET…/{id}/media; saved searches can be shared (4.84.0+) S18 S19
Other helpersnotFoundReference=true lists values that matched nothing (reference-list search); f=duplicationStatus:DUPLICATES_FOUND; autocomplete on folders/terms S16 S2
Delta queriesf=updateDate:[… TO …] / importDate ranges S16

Uploads & binaries

Upload flow S4 S21 S22

  1. POST/api/dam/files with the raw bytes as body and headers Content-Type, Content-Length, and X-KPK-FileName (ISO-8859-1) or X-KPK-Base64FileName (recommended) → 201 + temporary file descriptor (id, expirationDate, _links.self).
  2. Large files: POST/api/dam/files with Content-Length: 0, X-KPK-Upload-Content-Type, X-KPK-Upload-Content-Length; then PUT chunks to the descriptor with Content-Range (202 per chunk, 200 on the last; nextExpectedRanges in the body; 416 on a bad range; GET the descriptor to resume, 4.31.0+).
  3. Create the media: POST/api/dam/folders/{folderId}/medias (4.16.0+) or POST/api/dam/medias with {"_links":{"from":{"href":"…/api/dam/files/{id}"}}}, optionally a kpk:form link → 201 + Location S20.
LimitValue
Single-request uploadMax 50 MB; recommended ≤ 20 MB S21
Chunk size20 MB max recommended S22
File size20 GB officially supported S22
Parallel uploads200 simultaneous S22

Downloads & renditions

  • Thumbnail relations on each media: kpk:medium (112 px), kpk:large (224 px), kpk:xlarge (448 px), preview (607 px), kpk:whr (web hi-res, 1200 px) — default sizes, configurable S27.
  • Permalinks (/medias/{id}/permalinks) are generated at import for configured formats S2 S59.
  • Express download: GET/download-express?mid={id}&mid={id} (Basic or JWT) — one id returns the file, several return a ZIP S26.
  • Formatted exports: selection → POST…/exports with per-media-type kpk:*-export-format links; acceptTermsOfUse required S32 S39. Asynchronous download requests (/api/dam/download-requests, status PROCESSING/SUCCESS/ERROR, target ZIP URL; also contact sheets, 4.68.0+) S25 S2.
  • Dynamic resizing service "Dynameek" (URLs of the form kpk://dynameek-kpk/{size}/… returned by Keepicker) S43 S67; its public URL grammar is Not public.

Events & webhooks

  • No webhook or event-subscription mechanism is documented in the API guide or present in the Swagger spec S2 S3.
  • Webhook-style notifications can be implemented with custom scripts on the instance (project-specific, not a self-service API feature) S115.
  • The only notification resource is PUT/api/public/notifications/{email} to disable e-mail notifications S35.
  • Integration alternatives: poll search/media on updateDate ranges S16; server-side scripts that can be triggered by API (/api/dam/script-runs) S34; statistics hit search (/api/stat/search/hit, max 1,000,000 results, ≤ 10 parallel searches) S33. Keepeek also sells custom "synchronization scripts" as integration services S88.

Limits & quirks

TopicDetail
Rate limitingNot documented; behaviour under load Unknown S3 S41
Bulk updateSelection ≤ 10,000 media (more via support); synchronous; FAQ says ≤ 300 media per bulk call; fields and statuses only (not folders); modes REPLACE (default), APPEND, CLEAR, REMOVE (4.124.0+) S7 S23 Unverified the 300 cap appears only in the FAQ
Bulk jobsTemporary jobs with duration 30–600 s (default 30); 4.33.0+ and need a licence allowing bulk jobs from API S24
Publishing rulesMoving media to a published status fails for the whole selection if mandatory fields are empty (unless filled in the same request) S23
Export limitsFAQ: exports generally ≤ 200 items; direct (synchronous) exports ≤ 10 items, above which the API returns 500 and an e-mail is sent instead. Help center: direct custom-format downloads limited to 50 items by default (DIRECT_EXPORT_NUMBER_LIMIT, changed by support on cloud instances). The current default is 50 S115; the FAQ's 10-item figure appears outdated S7 S60 S115
Status filter on /mediasGET/api/dam/medias only returns Published media — use search for other statuses S2
Search path typoBest-practice article uses /api/dam/media/search; the spec and API guide use /api/dam/search/media S2 S17 Unverified
Single vs arraySingle embedded element returned as object unless forceArrays=true S14
Mixed collaborative filtersCombining basket/workflow/board filters in one query → 400 S16
FilenamesUse X-KPK-Base64FileName to avoid encoding issues S22
JWT keyShared key must be alphanumeric; RSA keys unsupported S6
Performance guidanceKeep responses small: paginate, use fields=, drop facets with facet-fields=[], prefer precise terms, sort server-side S17 S7
Error bodiesJSON {status, code} with string codes (e.g. security-notAuthorized, share-token-not-found) S41 S28
URI stabilityDo not hard-code URI patterns; follow HAL links S11

SDKs, tools & code samples

Library / toolLanguageMaintainerStatus
Server SDK——None published (no Keepeek-owned GitHub organization found — github.com/keePeek is a personal user account with no evident vendor link; no official PyPI/Packagist/NuGet package) S44
Keepicker (@keepeek/keepicker-react)JavaScript web component (<kpk-keepicker>)KeepeekActive: v1.27.0, 153 versions since 2023-08-03; events kpk-insert, kpk-insert-link; Drupal and React examples S43
Postman collection sample—KeepeekAttached to a help article; not mirrored here S37
Java JWT sampleJava (auth0 java-jwt)KeepeekSnippet in the JWT article S6
keepeek (PyPI 1.0.0)PythonUnknown (placeholder metadata)Unverified origin — do not treat as official S44 Unverified
media_keepeekdamPHP (Drupal)CommunityLast push 2025-04-24 S108
keepeek-360-phototheque-connecteurPHP (WordPress)KeepeekClosed on WordPress.org 2023-07-06 S107

Changelog of the API

DateChange
2026-09-30Doc instance reports release 4.146.0 (observation, not an announcement) S41
2026-04-02"FAQ API" article published (auth recommendation, bulk/export limits) S7
2026-01-28Download-express-via-API article published S26
2025-12-17API guide migrated to the Papirfly help center (all articles re-created that day) S3
2025-08-13Release 4.127: API fix on language display of filter names S40
Unknown (4.124.0)Bulk REMOVE mode S23
Unknown (4.84.0)Shared advanced searches in API responses; share options resource S18
Unknown (4.28.0)JWT ("OAuth 2 / Token JWT") authentication S6
Unknown (4.0.0)Hypermedia API v1 baseline (media, folders, uploads) S3

Release dates for 4.x versions are Not public (no public release-notes archive beyond S40).

Stored API specs

1 file · 514 KB · verbatim copies of public vendor filesSpecs README & provenance
FileFormatSizeDownload
keepeek_swagger_rest-api-v1.jsonSwagger / OpenAPI514 KBDownload
Search the wiki