Skip to main content

Automation and MISP API

Use the MISP REST API to search intelligence, maintain events, exchange observations and connect detection or response tools. Start with a small read-only query, check the returned scope and schema, then add writes or scheduled processing deliberately.

Note

This chapter follows MISP 3.0.0, 3.0_wip commit 99ebee729, in light mode. Examples use reserved training values. Screenshots can be enlarged.

Find the API reference

Open API → OpenAPI (/api/openapi) for the bundled reference, or download its specification from /doc/openapi.yaml. Use API → REST client (/api/rest) to load request templates, edit a request and inspect its response. The templates depend on the logged-in user’s role.

The MISP 3.0 REST client, staged with a bounded attribute search and a placeholder authentication header.

The MISP 3.0 REST client, staged with a bounded attribute search and a placeholder authentication header.

The REST client sends an HTTP request with the headers you supply. An interactive login does not replace the request’s authentication key: replace YOUR_API_KEY in its Headers tab. Keep Skip SSL validation off. Check the method, target URL and body before choosing Send; the client can perform writes as well as searches. Its response panel shows status, headers and body.

Use GET /servers/getVersion for the running server version and recommended PyMISP version. The OpenAPI document’s own info.version is not a substitute for that server-version check. For new development-branch features, check the relevant controller and its constraints as well as the reference. Use PyMISP for Python integrations where it provides a helper.

Configure an automation account

Use a dedicated account whose organisation and role match the integration’s purpose. An authentication key inherits that account’s permissions and data visibility; it does not grant site-administrator access by itself. A detection exporter normally needs read access, while an ingestion service needs the relevant add/modify permissions. Native MISP synchronization uses its own sync-account setup.

Open Account → My Profile → Auth keys. Choose Add auth key, enter a useful comment and set an expiry, allowed source IPs and Read only as appropriate. IP restrictions are evaluated against the source address seen by MISP, including the effects of an authorised reverse proxy.

The MISP 3.0 Add auth key dialog before key generation, showing expiry, IP restrictions and the read-only option.

The MISP 3.0 Add auth key dialog before key generation, showing expiry, IP restrictions and the read-only option.

The new key is displayed once. Store it in the integration’s secret store; do not commit it to source control or paste it into shared request logs. Editing an existing key changes its restrictions, not the account’s role. Rotate by deploying a new key, verifying the integration, then revoking the old key. See account management.

When IP usage logging is enabled and your role allows it, a key’s details can show Seen IPs and a Pin action. Pinning restricts the key to that address; confirm it is the stable egress address of the intended service before applying it.

Headers and TLS

Send the raw key, without a Bearer prefix, in the Authorization header:

Authorization: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

Use HTTPS and keep certificate verification enabled. For a private certificate authority, configure the client’s CA bundle (curl --cacert or Requests’ verify path) rather than disabling verification. Keep the key out of URLs. A read-only key may perform supported read-only POST searches; the HTTP verb alone does not determine whether an operation writes data.

Make a first request

Set MISP_URL to your instance’s base URL without a trailing slash. Supply MISP_KEY through your secret-management mechanism. In an interactive Bash session, a hidden prompt is another option:

export MISP_URL='https://misp.example.org'
read -r -s -p 'MISP API key: ' MISP_KEY
export MISP_KEY

The following helper keeps the headers consistent. It leaves TLS verification enabled and reports HTTP errors while retaining their response bodies for diagnosis:

misp_api() {
  local method="$1" path="$2"
  shift 2
  curl --silent --show-error --fail-with-body \
    --request "$method" \
    --header "Authorization: ${MISP_KEY}" \
    --header 'Accept: application/json' \
    --header 'Content-Type: application/json' \
    "${MISP_URL%/}${path}" "$@"
}

misp_api GET /servers/getVersion

Check version, pymisp_recommended_version and any capabilities relevant to your integration, such as collection_sync. Capability flags and the account’s role matter alongside the version. Do not infer support for every MISP 3.0 target type from the PyMISP package’s major version.

Create and maintain event data

The following bodies illustrate writes to a private, unpublished exercise event. Check the response for the created UUID and use that identifier in later requests. The account needs the corresponding permissions and ownership; administrator credentials should not be a script default.

Create an event

POST to /events/add:

{
  "Event": {
    "info": "Integration exercise: private observations",
    "date": "2026-11-06",
    "distribution": 0,
    "threat_level_id": 4,
    "analysis": 0,
    "published": false
  }
}

threat_level_id is 1 High, 2 Medium, 3 Low, 4 Undefined. Do not use a zero-based mapping. Distribution 0 restricts the event to its owning organisation; an unpublished community event can still be visible locally under the instance’s policy.

Add an attribute or object

POST to /attributes/add/{event_uuid} with an Attribute envelope:

{
  "Attribute": {
    "type": "ip-dst",
    "category": "Network activity",
    "value": "192.0.2.80",
    "to_ids": false,
    "distribution": 5,
    "comment": "Reserved documentation address; keep out of detection exports."
  }
}

Distribution 5 on a child means inherit from its parent. Use GET /attributes/describeTypes to inspect accepted types/categories and POST /objects/add/{event_uuid} for a structured MISP object. Follow the active object template; a collection of similarly named standalone attributes does not create an object automatically.

Update, tag and publish deliberately

Operation Endpoint and body
Fetch an event GET /events/view/{uuid}
Update event metadata POST /events/edit/{uuid} with an Event envelope.
Update an attribute POST /attributes/edit/{uuid} with an Attribute envelope.
Attach an event tag POST /events/addTag with {"event":"EVENT_UUID","tag":"tlp:clear"}.
Remove an event tag POST /events/removeTag with the event and tag identifiers.
Tag an attribute POST /attributes/addTag with {"attribute":"ATTRIBUTE_UUID","tag":"TAG_NAME"}.
Delete an attribute POST /attributes/delete/{uuid}; review soft/hard-delete behaviour before choosing a variant.
Delete an object POST /objects/delete/{uuid}; check the selected deletion mode.
Delete an event POST /events/delete/{uuid}; review the consequences for its children and connected systems.
Publish a reviewed event POST /events/publish/{uuid}; this can initiate synchronization and configured downstream actions.

Fetch the response and confirm the saved state. Do not retry an ambiguous create blindly: after a timeout, query the UUID or reconcile before adding another copy. Publication is a separate workflow decision; none of the training examples requires publishing an event.

MISP 3.0 values and research data

MISP 3.0 distinguishes an attribute occurrence from the value it holds. An attribute has a UUID; a value has a SHA-256 address computed from the stored, normalized UTF-8 text.

Look up an accessible value with:

misp_api GET /values/view --get --data-urlencode 'value=example.org'

The equivalent address lookup is GET /values/view/sha256:{hex}. Local numeric value IDs are not portable identifiers. Read the stored value and address from the response rather than hashing an unnormalized input. For a composite attribute, each component value has its own address.

Use the address fields appropriate to the target type:

Target Address in a write
Event, attribute, object or another UUID target object_uuid for Analyst Data; element_uuid for collection elements.
AttributeValue object_sha256 for Analyst Data; element_sha256 for collection elements.
Relationship’s value target related_object_type: "AttributeValue" with related_object_sha256.

For example, POST a note to /analystData/add/Note/{sha256}/AttributeValue:

{
  "Note": {
    "note": "Training value: retain the source context before making an assessment.",
    "language": "en",
    "distribution": 0
  }
}

Add a value reference with POST /collectionElements/add/{collection_id}:

{
  "CollectionElement": {
    "element_type": "AttributeValue",
    "element_sha256": "SHA256_OF_STORED_VALUE",
    "description": "Reserved training value, not a maliciousness verdict."
  }
}

These records have their own distribution. A reference does not give its reader access to the source event or reveal a value that the reader cannot resolve through a visible attribute. See Analyst Data and Collections for visibility and older-peer limitations. Some 3.0 calls are not wrapped by every PyMISP release; use documented REST requests for those operations rather than inventing a client method.

The old /threads/ and /posts/ discussion API is removed in this branch. Use Analyst Data notes/replies on the relevant target. Event reports use /eventReports/ endpoints for a narrative; neither a note nor a report should be treated as an attribute containing a detection indicator.

Sightings API

POST to /sightings/add/{attribute_uuid} to record an observation of that occurrence:

{
  "type": 0,
  "source": "Documentation exercise",
  "timestamp": 1793956200
}

Use 0 for a sighting, 1 for a false positive and 2 for an expiration. The add request uses timestamp; a returned record has date_sighting. Omitting the observation time records the current time. Supplying a value instead of one attribute occurrence can affect multiple matching attributes; choose the scope deliberately.

POST /sightings/restSearch provides filtered retrieval. For bulk input, use the endpoint’s documented batch format rather than repeatedly reporting the same observation after an uncertain response. See Sightings for interpretation and visibility.

Exports, attachments and specialised APIs

Use returnFormat in a restSearch body for exports. JSON is a useful starting point; CSV, text, STIX, Suricata/Snort, RPZ and other formats have different controller support and options. Inspect the live reference for the exact format and filters. Export success does not mean that every source feature is representable in the target format. Some formats, including text, default to published, IDS-enabled attributes when those filters are omitted. Set the intended scope explicitly; JSON and detection-oriented formats do not necessarily have identical defaults.

Task Current approach
JSON/XML event export Search /events/restSearch with the selected format and bounded filters.
CSV or plain values Search /attributes/restSearch with returnFormat: "csv" or "text", selecting the required types and fields.
IDS, hash/HIDS or DNS RPZ output Select the supported format, source scope, detection flags and format-specific parameters explicitly.
STIX export/import Use the supported STIX version and installed conversion dependencies; validate the output with the receiving platform.
Download an attachment Use the attribute’s attachment-download endpoint, subject to event visibility. Request binary data only when needed.
Sample lookup/download Use the documented sample APIs and retain the expected archive/password handling. Do not treat the response as ordinary indicator JSON.
Upload a file/sample Use an attribute/object attachment workflow or the documented upload API. Its base64 payload, distribution and IDS defaults need review.
Proposals /shadow_attributes/view, /add, /edit, /accept and /discard, with the required target identifier and ShadowAttribute envelope. The owner reviews proposed changes.
Sharing groups GET /sharing_groups/index returns groups visible to the authenticated account. Their membership is separate from collections of content.
Feed metadata and jobs /feeds/ endpoints described below; caching and ingestion are separate.
Organisations and users Use the reference’s organisation and admin-user endpoints, with the appropriate administrator role and scope. Numeric IDs differ between instances.
Warninglists, statistics and type metadata Use their documented read endpoints; access and response shape depend on the operation and role.

The old positional export recipes (/events/xml/..., /events/csv/..., /events/text/... and similar paths) are legacy interfaces. Prefer a named JSON search body for new clients. Never copy an old URL recipe that embeds an authentication key.

Automate feed operations

Feed administration requires a site administrator. Typical operations are:

Method and endpoint Effect
POST /feeds/enable/{id} Enable ingestion for that feed.
POST /feeds/disable/{id} Disable ingestion; caching is controlled separately.
POST /feeds/cacheFeeds/{id} Cache that feed when its caching flag is enabled.
POST /feeds/cacheFeeds/all Cache all eligible feeds; use misp or freetext for a format scope.
POST /feeds/fetchFromFeed/{id} Import an enabled feed.
POST /feeds/fetchFromAllFeeds Bulk ingestion; review the source set before running it.

With background jobs enabled, acceptance of a request does not prove the job completed. Inspect the job outcome, cache time or resulting event. See Managing feeds.

Query an enrichment service

GET /modules/index exposes enabled enrichment modules available to the account when the service is configured and reachable. POST /modules/queryEnrichment is the hover-query path: it requires an enabled module supporting hover and input matching that module’s schema. It is not a generic import, expansion or AI endpoint. The request needs a module name; MISP adds configured module credentials before forwarding it to the service.

Use the Modules chapter for service configuration, organisation restrictions, event import/enrichment and the separate AI family. Review results before saving them into intelligence or enabling their IDS flags.

Errors and operational checks

HTTP result What to check
200 Parse the expected envelope and inspect endpoint-level success/error fields. A job may still be pending.
403 Missing/invalid/expired key, IP restrictions, account role, read-only restriction or insufficient access.
404 Wrong route, missing entity or an entity not visible to this account. Do not interpret every 404 as a source deletion.
405 Method, required input or workflow constraint rejected. MISP also uses this status for some validation errors. Read the body.
429 Respect a rate limit and any retry guidance from the instance or gateway.
5xx / transport failure Bound retries, retain the last successful checkpoint and investigate server/job logs. Reconcile an ambiguous write before retrying it.

Log status, endpoint, timing and stable identifiers rather than entire authenticated requests or sensitive response bodies. Test with the same account, filters and network path the scheduled integration will use. Include empty results, pagination, permission failures and source removals in acceptance checks, not only the first successful search.