Zum Inhalt

Für Entwickler

PODFY Open API Referenz

Rufen Sie Meldungen und Nachweise ab, aktualisieren Sie deren Status und verwalten Sie Ihr Referenzregister aus Ihren eigenen Systemen. Eine JSON-REST-API, Teil von PODFY Advanced.

Was die API ist

Mit der PODFY Open API lesen Ihre eigenen Systeme Datensätze (Liefernachweise und QR-Meldungen), aktualisieren deren Bearbeitungsstatus und verwalten das Referenzregister (Objekte). Es ist eine JSON-REST-API für den Betrieb von Server zu Server. Es gibt kein CORS: Rufen Sie die API aus Ihrem Backend auf, nie aus einem Browser.

Die Open API ist Teil von PODFY Advanced. Ist sie für Ihre Marke nicht aktiv, antwortet jeder Aufruf mit 403 feature_not_active. Die Spezifikation ist OpenAPI 3.1, und die Referenz weiter unten wird aus derselben Datei erzeugt.

API-Schlüssel erstellen

Ein Administrator Ihrer Marke erstellt Schlüssel im Portal (das auf Englisch ist) unter Settings → Integrations → API keys. Geben Sie dem Schlüssel einen Namen und wählen Sie seine Scopes. Der Schlüssel wird nur einmal angezeigt, speichern Sie ihn daher in Ihrer Geheimnisverwaltung. Sie können einen Schlüssel jederzeit widerrufen, und ein widerrufener Schlüssel funktioniert sofort nicht mehr.

  • records:read: Datensätze lesen
  • records:write: Datensätze aktualisieren (erlaubt auch Lesen)
  • references:read: das Referenzregister lesen
  • references:write: Referenzen anlegen und ändern (erlaubt auch Lesen)

Basis-URL und Authentifizierung

Die Basis-URL lautet https://portal.podfy.net/api/v1. Senden Sie Ihren Schlüssel bei jeder Anfrage als Bearer-Token im Authorization-Header mit. Ein Schlüssel funktioniert nie als Query-Parameter.

Ein fehlender, fehlerhafter, unbekannter oder widerrufener Schlüssel erhält immer dieselbe Antwort: 401 invalid_key. Ein Schlüssel ohne den erforderlichen Scope erhält 403 insufficient_scope.

curl -H "Authorization: Bearer $PODFY_API_KEY" \
  "https://portal.podfy.net/api/v1/records?limit=10"

Live- und Testschlüssel

Schlüssel mit dem Präfix pk_live_ sehen nur Produktivdatensätze. Schlüssel mit dem Präfix pk_test_ (nur QA-Datensätze) sehen nur Testdatensätze von qa.podfy.app, deren PODFY-IDs mit QA- beginnen. Die beiden Umgebungen vermischen sich nie.

Das Referenzregister wird mit der Produktion geteilt, daher können Testschlüssel keine Referenzen anlegen oder ändern (403 insufficient_scope). Ein Datensatz oder eine Referenz einer anderen Marke oder ein Datensatz der anderen Umgebung ergibt 404 not_found, nie 403.

Rate Limit

Jeder Schlüssel darf 600 Anfragen pro Minute stellen, gezählt in festen Minutenfenstern. Jede Antwort enthält X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset (Unix-Sekunden, zu denen das Fenster endet).

Über dem Limit erhalten Sie 429 rate_limited mit einem Retry-After-Header (Sekunden). Warten Sie diese Zeit ab und versuchen Sie es erneut.

Fehler

Jeder Fehler ist JSON in derselben Form: {"error":{"code":"…","message":"…"}}. Verarbeiten Sie Fehler anhand des HTTP-Status und des Codes, nicht anhand des Nachrichtentexts. Antworten werden nie zwischengespeichert (Cache-Control: no-store). Die vollständige Liste der Codes finden Sie in der Referenz weiter unten.

Seitenweise Abfrage

Listen-Endpunkte liefern {"data": [...], "next_cursor": "…"}. Geben Sie next_cursor als Parameter cursor zurück, um die nächste Seite zu erhalten, bis er null ist. Cursor sind undurchsichtig: Bauen oder ändern Sie sie nicht. Datensätze werden neueste zuerst aufgelistet. Die Seitengröße legen Sie mit limit fest (1 bis 200, Standard 50).

Referenz

Operationen

Die Referenz weiter unten wird aus der OpenAPI-Datei erzeugt und ist in jeder Sprache auf Englisch. Spezifikation herunterladen: openapi.json

Fehlercodes

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
409ref_existsThe reference already exists.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

GET /records

List records Required scope: records:read

Records of your brand, newest first. Deleted records are never listed.

Parameters

NameInTypeRequiredDescription
sincequerystringoptionalOnly records created at or after this moment (ISO 8601 date or date-time; a time without zone is UTC).
updated_sincequerystringoptionalOnly records changed (or created) at or after this moment (ISO 8601).
statusquerystringoptionalWork status, one or more comma separated.
referencequerystring max 100 charactersoptionalExact reference (1-100 characters).
categoryquerystring max 40 charactersoptionalCategory code (letters, digits, _ and -; case-insensitive).
limitqueryinteger 1-200 default 50optionalPage size, 1-200 (default 50; larger values are capped at 200).
cursorquerystringoptionalThe next_cursor of the previous page (opaque).

Response 200

A page of records.

FieldTypeRequiredDescription
dataarray of objectrequired
data[].podfy_idstringrequired
data[].modestring one of delivery, reportrequired
data[].referencestringoptionalEmpty string when none.
data[].assetobjectoptionalRegister data at upload time.
data[].asset.namestring or nulloptional
data[].asset.locationstring or nulloptional
data[].asset.groupstring or nulloptional
data[].categorystring or nulloptionalCategory code (report mode) or delivery issue code.
data[].prioritystring one of low, normal, high, criticalrequired
data[].work_statusstring one of new, in_progress, resolved, rejectedrequired
data[].notestringoptional
data[].fieldsobjectoptionalCustom form fields.
data[].group_idstringrequiredRecords of one multi-file upload share it (the podfy_id without the -N suffix).
data[].filesarray of objectrequired
data[].files[].namestringoptional
data[].files[].urlstring urioptional
data[].locationobject or nulloptional
data[].location.latnumberoptional
data[].location.lngnumberoptional
data[].location.sourcestring or nulloptional
data[].duplicate_ofstring or nulloptionalpodfy_id of the first report this one duplicates.
data[].urlstring or null urioptionalPublic detail page of the record.
data[].assigneestring or nulloptionalE-mail of the assigned brand member.
data[].created_atstring date-timerequired
data[].updated_atstring or null date-timeoptional
data[].resolved_atstring or null date-timeoptional
data[].keep_informedbooleanoptionalTrue when the reporter asked to be kept informed (a confirmation or resolved message was or can be sent). Never the address.
next_cursorstring or nullrequired

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  "https://portal.podfy.net/api/v1/records?limit=50"

GET /records/{podfy_id}

Get a record Required scope: records:read

One record with its timeline (created, status, comment, assign, priority, duplicate). Mail recipients and reporter data never appear.

Parameters

NameInTypeRequiredDescription
podfy_idpathstring pattern ^[A-Za-z0-9_-]{1,64}$requiredThe record's PODFY ID, e.g. PFY-7Q4K2-1 (QA-… for test records).

Response 200

The record.

FieldTypeRequiredDescription
podfy_idstringrequired
modestring one of delivery, reportrequired
referencestringoptionalEmpty string when none.
assetobjectoptionalRegister data at upload time.
asset.namestring or nulloptional
asset.locationstring or nulloptional
asset.groupstring or nulloptional
categorystring or nulloptionalCategory code (report mode) or delivery issue code.
prioritystring one of low, normal, high, criticalrequired
work_statusstring one of new, in_progress, resolved, rejectedrequired
notestringoptional
fieldsobjectoptionalCustom form fields.
group_idstringrequiredRecords of one multi-file upload share it (the podfy_id without the -N suffix).
filesarray of objectrequired
files[].namestringoptional
files[].urlstring urioptional
locationobject or nulloptional
location.latnumberoptional
location.lngnumberoptional
location.sourcestring or nulloptional
duplicate_ofstring or nulloptionalpodfy_id of the first report this one duplicates.
urlstring or null urioptionalPublic detail page of the record.
assigneestring or nulloptionalE-mail of the assigned brand member.
created_atstring date-timerequired
updated_atstring or null date-timeoptional
resolved_atstring or null date-timeoptional
keep_informedbooleanoptionalTrue when the reporter asked to be kept informed (a confirmation or resolved message was or can be sent). Never the address.
eventsarray of objectrequired
events[].typestring one of created, status, comment, assign, priority, duplicaterequired
events[].fromstring or nulloptional
events[].tostring or nulloptional
events[].notestring or nulloptionalThe comment text (comment events only).
events[].actorstring or nulloptionalBrand member e-mail, app, or api:<key prefix>.
events[].created_atstring date-timerequired

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  "https://portal.podfy.net/api/v1/records/PFY-7Q4K2-1"

PATCH /records/{podfy_id}

Update a record Required scope: records:write

Change the work status, assignee or priority, or add a comment. Same rules as the portal: one timeline event per change, webhooks record.status_changed / record.updated are sent, the actor is api:<key prefix>. Needs status tracking (report mode or the status tracking add-on), else 403 feature_not_active. Only the fields below are accepted.

Parameters

NameInTypeRequiredDescription
podfy_idpathstring pattern ^[A-Za-z0-9_-]{1,64}$requiredThe record's PODFY ID, e.g. PFY-7Q4K2-1 (QA-… for test records).

Request body (JSON)

FieldTypeRequiredDescription
work_statusstring one of new, in_progress, resolved, rejectedoptional
assigneestring or null emailoptionalAn active member of the brand, or null to unassign.
prioritystring one of low, normal, high, criticaloptional
commentstring or null max 2000 charactersoptionalAdded to the timeline.

Response 200

The record after the update. changed is false when nothing differed.

FieldTypeRequiredDescription
changedbooleanrequired
recordobjectrequiredThe same record object as in webhook payloads, plus timestamps and the assignee.
record.podfy_idstringrequired
record.modestring one of delivery, reportrequired
record.referencestringoptionalEmpty string when none.
record.assetobjectoptionalRegister data at upload time.
record.asset.namestring or nulloptional
record.asset.locationstring or nulloptional
record.asset.groupstring or nulloptional
record.categorystring or nulloptionalCategory code (report mode) or delivery issue code.
record.prioritystring one of low, normal, high, criticalrequired
record.work_statusstring one of new, in_progress, resolved, rejectedrequired
record.notestringoptional
record.fieldsobjectoptionalCustom form fields.
record.group_idstringrequiredRecords of one multi-file upload share it (the podfy_id without the -N suffix).
record.filesarray of objectrequired
record.files[].namestringoptional
record.files[].urlstring urioptional
record.locationobject or nulloptional
record.location.latnumberoptional
record.location.lngnumberoptional
record.location.sourcestring or nulloptional
record.duplicate_ofstring or nulloptionalpodfy_id of the first report this one duplicates.
record.urlstring or null urioptionalPublic detail page of the record.
record.assigneestring or nulloptionalE-mail of the assigned brand member.
record.created_atstring date-timerequired
record.updated_atstring or null date-timeoptional
record.resolved_atstring or null date-timeoptional
record.keep_informedbooleanoptionalTrue when the reporter asked to be kept informed (a confirmation or resolved message was or can be sent). Never the address.

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl -X PATCH \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"work_status": "in_progress", "assignee": "[email protected]"}' \
  "https://portal.podfy.net/api/v1/records/PFY-7Q4K2-1"

GET /references

List references Required scope: references:read

Your reference register, ordered by ref.

Parameters

NameInTypeRequiredDescription
statusquerystring one of active, retiredoptional
groupquerystring max 40 charactersoptionalExact group code.
qquerystring max 100 charactersoptionalText contained in ref, name or location (1-100 characters).
limitqueryinteger 1-200 default 50optionalPage size, 1-200 (default 50; larger values are capped at 200).
cursorquerystringoptionalThe next_cursor of the previous page (opaque).

Response 200

A page of references.

FieldTypeRequiredDescription
dataarray of objectrequired
data[].refstringrequired
data[].kindstring or null one of asset, shipmentoptional
data[].namestring or nulloptional
data[].locationstring or nulloptional
data[].group_codestring or nulloptional
data[].sticker_textstring or nulloptional
data[].statusstring one of active, retiredrequired
data[].active_fromstring or nulloptional
data[].retired_atstring or null date-timeoptional
data[].created_atstring or null date-timeoptional
data[].updated_atstring or null date-timeoptional
data[].qr_urlstring urirequiredhttps://podfy.app/{brand}/{ref}
next_cursorstring or nullrequired

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  "https://portal.podfy.net/api/v1/references?limit=50"

POST /references

Create a reference Required scope: references:write

Adds one reference. 409 ref_exists when the ref is already in the register.

QA keys (pk_test_) cannot change references: the register is shared with production records (403 insufficient_scope).

Request body (JSON)

FieldTypeRequiredDescription
refstring pattern ^[A-Za-z0-9._-]{1,64}$required
namestring or null max 120 charactersoptional
locationstring or null max 120 charactersoptional
group_codestring or null max 40 charactersoptional
sticker_textstring or null max 120 charactersoptional

Response 201

The new reference.

FieldTypeRequiredDescription
refstringrequired
kindstring or null one of asset, shipmentoptional
namestring or nulloptional
locationstring or nulloptional
group_codestring or nulloptional
sticker_textstring or nulloptional
statusstring one of active, retiredrequired
active_fromstring or nulloptional
retired_atstring or null date-timeoptional
created_atstring or null date-timeoptional
updated_atstring or null date-timeoptional
qr_urlstring urirequiredhttps://podfy.app/{brand}/{ref}

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
409ref_existsThe reference already exists.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl -X POST \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ref": "example", "name": "example"}' \
  "https://portal.podfy.net/api/v1/references"

GET /references/{ref}

Get a reference Required scope: references:read

One reference.

Parameters

NameInTypeRequiredDescription
refpathstring pattern ^[A-Za-z0-9._-]{1,64}$requiredThe reference (1-64 characters: letters, digits, dot, underscore, hyphen).

Response 200

The reference.

FieldTypeRequiredDescription
refstringrequired
kindstring or null one of asset, shipmentoptional
namestring or nulloptional
locationstring or nulloptional
group_codestring or nulloptional
sticker_textstring or nulloptional
statusstring one of active, retiredrequired
active_fromstring or nulloptional
retired_atstring or null date-timeoptional
created_atstring or null date-timeoptional
updated_atstring or null date-timeoptional
qr_urlstring urirequiredhttps://podfy.app/{brand}/{ref}

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  "https://portal.podfy.net/api/v1/references/YOUR_REF"

PATCH /references/{ref}

Update a reference Required scope: references:write

Edit, move, retire (status: retired) or reactivate a reference. Only the fields below are accepted; an empty string clears a text field.

QA keys (pk_test_) cannot change references: the register is shared with production records (403 insufficient_scope).

Parameters

NameInTypeRequiredDescription
refpathstring pattern ^[A-Za-z0-9._-]{1,64}$requiredThe reference (1-64 characters: letters, digits, dot, underscore, hyphen).

Request body (JSON)

FieldTypeRequiredDescription
namestring or null max 120 charactersoptional
locationstring or null max 120 charactersoptional
group_codestring or null max 40 charactersoptional
sticker_textstring or null max 120 charactersoptional
statusstring one of active, retiredoptional

Response 200

The reference after the update.

FieldTypeRequiredDescription
changedbooleanrequired
referenceobjectrequired
reference.refstringrequired
reference.kindstring or null one of asset, shipmentoptional
reference.namestring or nulloptional
reference.locationstring or nulloptional
reference.group_codestring or nulloptional
reference.sticker_textstring or nulloptional
reference.statusstring one of active, retiredrequired
reference.active_fromstring or nulloptional
reference.retired_atstring or null date-timeoptional
reference.created_atstring or null date-timeoptional
reference.updated_atstring or null date-timeoptional
reference.qr_urlstring urirequiredhttps://podfy.app/{brand}/{ref}

Errors

StatusCodesMeaning
400invalid_parameter invalid_cursor invalid_body invalid_status invalid_priority invalid_assignee invalid_comment comment_too_long nothing_to_update invalid_ref name_too_long location_too_long group_code_too_long sticker_text_too_long no_valid_fieldsInvalid query parameter or body.
401invalid_keyThe API key is missing, malformed, unknown or revoked (always the same body).
403feature_not_active insufficient_scopeThe Open API (or, for references, the reference register; for record updates, status tracking) is not active for the brand, or the key lacks the scope.
404not_foundNo such endpoint, or no such record / reference for this key's brand and environment.
405method_not_allowedThe endpoint exists but not with this method; Allow lists the methods.
429rate_limitedMore than 600 requests in this minute for this key.
500server_errorUnexpected error; try again later.

Example

curl -X PATCH \
  -H "Authorization: Bearer $PODFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "example", "location": "example"}' \
  "https://portal.podfy.net/api/v1/references/YOUR_REF"