Naar inhoud

Voor ontwikkelaars

PODFY Open API documentatie

Haal meldingen en bewijs op, werk de status bij en beheer uw referentieregister vanuit uw eigen systemen. Een JSON REST API, onderdeel van PODFY Advanced.

Wat de API is

Met de PODFY Open API lezen uw eigen systemen records (afleverbewijzen en QR-meldingen), werken ze de werkstatus bij en beheren ze het referentieregister (objecten). Het is een JSON REST API voor gebruik van server naar server. Er is geen CORS: roep de API aan vanuit uw backend, nooit vanuit een browser.

De Open API is onderdeel van PODFY Advanced. Is hij niet actief voor uw merk, dan antwoordt elke aanroep met 403 feature_not_active. De specificatie is OpenAPI 3.1 en de referentie hieronder is uit hetzelfde bestand gegenereerd.

Een API-sleutel aanmaken

Een beheerder van uw merk maakt sleutels aan in het portaal (dat in het Engels is) onder Settings → Integrations → API keys. Geef de sleutel een naam en kies de scopes. De sleutel wordt één keer getoond, dus bewaar hem in uw wachtwoord- of secretsbeheer. U kunt een sleutel altijd intrekken, en een ingetrokken sleutel werkt meteen niet meer.

  • records:read: records lezen
  • records:write: records bijwerken (staat ook lezen toe)
  • references:read: het referentieregister lezen
  • references:write: referenties aanmaken en wijzigen (staat ook lezen toe)

Basis-URL en authenticatie

De basis-URL is https://portal.podfy.net/api/v1. Stuur uw sleutel bij elk verzoek mee als Bearer-token in de Authorization-header. Een sleutel werkt nooit als queryparameter.

Een ontbrekende, onjuiste, onbekende of ingetrokken sleutel krijgt altijd hetzelfde antwoord: 401 invalid_key. Een sleutel zonder de vereiste scope krijgt 403 insufficient_scope.

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

Live- en testsleutels

Sleutels die beginnen met pk_live_ zien alleen productierecords. Sleutels die beginnen met pk_test_ (alleen QA-records) zien alleen testrecords van qa.podfy.app, waarvan de PODFY-ID's met QA- beginnen. De twee omgevingen mengen nooit.

Het referentieregister wordt gedeeld met productie, dus testsleutels kunnen geen referenties aanmaken of wijzigen (403 insufficient_scope). Een record of referentie van een ander merk, of een record uit de andere omgeving, geeft 404 not_found, nooit 403.

Rate limit

Elke sleutel mag 600 verzoeken per minuut doen, geteld in vaste vensters van een minuut. Elk antwoord bevat X-RateLimit-Limit, X-RateLimit-Remaining en X-RateLimit-Reset (unix-seconden waarop het venster eindigt).

Boven de limiet krijgt u 429 rate_limited met een Retry-After-header (seconden). Wacht zo lang en probeer het opnieuw.

Foutmeldingen

Elke fout is JSON in dezelfde vorm: {"error":{"code":"…","message":"…"}}. Verwerk fouten op basis van de HTTP-status en de code, niet op de tekst van het bericht. Antwoorden worden nooit gecachet (Cache-Control: no-store). De volledige lijst met codes staat in de referentie hieronder.

Paginering

Lijstendpoints geven {"data": [...], "next_cursor": "…"} terug. Geef next_cursor door als parameter cursor om de volgende pagina te krijgen, tot hij null is. Cursors zijn ondoorzichtig: bouw of wijzig ze niet. Records staan met de nieuwste eerst. De paginagrootte stelt u in met limit (1 tot 200, standaard 50).

Referentie

Operaties

De referentie hieronder is gegenereerd uit het OpenAPI-bestand en staat in elke taal in het Engels. Download de specificatie: openapi.json

Foutcodes

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"