Skip to content

Authentication

Authentication is HMAC body signing. Every request must use TLS 1.3 (HTTPS); plaintext HTTP is not accepted.

HMAC body signing

You sign each request body with your shared secret and send the signature alongside your key ID and destination namespace:

X-OpenAP-Key-Id: <key_id>
X-OpenAP-Signature: <signature>
X-OpenAP-Data-Set: <data_set_id>

OpenAP issues you a key ID and a shared secret at onboarding.

Signature construction

The signature is the HMAC-SHA256 of the exact request body bytes, keyed by your shared secret, encoded as lowercase hexadecimal:

X-OpenAP-Signature = hex( HMAC_SHA256(shared_secret, raw_request_body) )

Sign the byte-for-byte body you send — do not reformat, re-serialize, or re-order JSON between signing and sending, or the signature will not match.

KEY_ID="your-key-id"
SHARED_SECRET="..."   # issued by OpenAP

BODY='{"data_set_id":"12345678AA","timestamp":1746558464,"event_type":"page_view"}'
SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SHARED_SECRET" | awk '{print $NF}')

curl -X POST https://ecapi.openap.tv/v1/events \
  -H "X-OpenAP-Key-Id: $KEY_ID" \
  -H "X-OpenAP-Signature: $SIGNATURE" \
  -H "X-OpenAP-Data-Set: 12345678AA" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d "$BODY"

A bad signature or an unknown key ID is rejected with 401 Unauthorized. Shared secrets are rotated on a 90-day cadence; during a rotation, switch to the new secret at the agreed time (there may be a brief window where either verifies).

Authorization

Authentication identifies who you are; authorization checks what you may write to. Your principal (your HMAC key ID) is authorized for one or more data_set_id values, recorded on OpenAP's side.

  • A request whose principal is not authorized for the data_set_id carried in the payload is rejected with 401 Unauthorized. This is enforced at the request level: a batch containing any event for an unauthorized data_set_id is rejected as a whole.
  • The X-OpenAP-Data-Set header and each event's data_set_id field must match, and you must be authorized for that data_set_id.
  • Authorization changes (including revocation) take effect within minutes without any change on your side.

Bearer JWT (future option)

Short-lived Bearer tokens are a possible future authentication option for online/server senders that would rather refresh a token than hold a static secret. They are not enabled today — a request sent with an Authorization: Bearer … header is rejected with 401 Unauthorized. Use HMAC body signing. This section will be expanded if and when token-based auth is offered.

Troubleshooting

  • A 401 with an error body from the eCAPI service means your credentials were evaluated and rejected (missing/malformed signature, unknown key ID, or principal not authorized for the data_set_id).
  • A 403 mentioning Missing Authentication Token or Invalid key=value pair ... in Authorization header is not an authentication failure — it means the request URL path or HTTP method didn't match a valid endpoint and never reached the eCAPI service. Fix the URL/method first; see API reference — Wrong URL or method.