Postingan

Setiap endpoint Posts: contoh cURL, Python, Node; pengumuman, acara, penawaran; penjadwalan, kampanye per lokasi/massal, cek status berkala, penghapusan.

Postingan adalah pembaruan singkat yang dipublikasikan ke Google Business Profile atau halaman Facebook suatu lokasi: pengumuman, acara bertanggal, atau penawaran dengan kupon. Satu kampanye dapat menargetkan banyak lokasi dan kedua situs sekaligus. Publikasi berlangsung secara asinkron, sehingga setiap panggilan pembuatan langsung mengembalikan respons dan Anda memeriksa hasilnya secara berkala. Ketiga endpoint GET dapat digunakan dengan kunci Read (baca); pembuatan dan penghapusan memerlukan kunci Write (tulis).

Sekilas tentang endpoint

MetodePathFungsiReferensi
POST/postsPublikasikan pengumuman berupa pesan biasa dengan tombol dan gambar opsional.Buat postingan pengumuman
POST/postsPublikasikan acara dengan judul serta rentang waktu mulai dan selesai.Buat postingan acara
POST/postsPublikasikan penawaran dengan kode kupon, diskon, dan ketentuan.Buat postingan penawaran
GET/posts/{postId}Satu kampanye dengan status publikasi dan jumlah interaksi per situs.Dapatkan postingan
GET/locations/{locationId}/postsSatu halaman kampanye yang menargetkan satu lokasi.Ambil postingan untuk suatu lokasi
DELETE/posts/{postId}Hapus kampanye secara permanen dan batalkan publikasinya di semua tempat.Hapus postingan
POST/bulk-postsSatu kampanye yang disebarkan ke banyak lokasi.Buat postingan massal
GET/bulk-posts/{postId}Satu kampanye massal dengan perincian analitik per lokasi.Ambil postingan massal berdasarkan ID
GET/locations/{locationId}/bulk-postsKampanye massal yang mencakup satu lokasi, dengan filter dan pengurutan.Ambil postingan massal untuk suatu lokasi

Nilai yang akan Anda gunakan di semua endpoint

Keempat enum di bawah ini digunakan bersama oleh setiap endpoint pembuatan.

FieldNilai yang diterima
postTypeANNOUNCEMENT, EVENT, OFFER, COVID19, PRODUCT
postSites dan setiap siteGOOGLE, FACEBOOK
postCta[].typeBOOK, ORDER, SHOP, LEARN_MORE, SIGN_UP, GET_OFFER
postMediaUrl[].typeIMAGE, VIDEO

Publikasikan pengumuman

POST /posts

Pengumuman menerima pesan serta, secara opsional, satu tombol dan satu gambar per situs. Sediakan satu entri postMessage untuk setiap situs yang tercantum dalam postSites. Respons mengembalikan kampanye baru dengan status diatur ke INPROGRESS, karena publikasi berjalan di latar belakang.

Parameter

NamaLetakWajibCatatan
input.postNamebodyYaNama internal kampanye, tidak pernah ditampilkan kepada pelanggan.
input.locationIdsbodyYaArray ID lokasi dalam base64.
input.postTypebodyYaANNOUNCEMENT di sini.
input.postSitesbodyYaArray berisi GOOGLE dan FACEBOOK.
input.postMessagebodyTidakArray objek dengan site dan message.
input.postCtabodyTidakArray objek dengan site, type, url.
input.postMediaUrlbodyTidakArray objek dengan site, url, type.
input.clientMutationIdbodyTidakDikembalikan tanpa perubahan untuk korelasi.
Announcement
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "Grand Opening Announcement",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],    "postType": "ANNOUNCEMENT",    "postSites": ["GOOGLE"],    "postMessage": [      { "site": "GOOGLE", "message": "We are now open! Visit us this week for our grand opening." }    ],    "postCta": [      { "site": "GOOGLE", "type": "LEARN_MORE", "url": "https://jennyhome.example/opening" }    ],    "postMediaUrl": [      { "site": "GOOGLE", "url": "https://cdn.example.com/opening.jpg", "type": "IMAGE" }    ]  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "errors": [],      "socialPost": {        "id": "U29jaWFsUG9zdDo0NDEyMg==",        "name": "Grand Opening Announcement",        "status": "INPROGRESS",        "type": "ANNOUNCEMENT",        "sites": ["GOOGLE"],        "publishDetails": [          { "site": "GOOGLE", "status": "PUBLISHING", "createdDate": "2026-06-28", "submissionError": null }        ],        "postLinks": [],        "locationIds": [1800289]      }    }  }}

Simpan socialPost.id. Nilai ini adalah ID postingan dalam base64 yang diperlukan oleh setiap endpoint lain di sini. Kedua fungsi pembantu SDK menerima satu string message dan mengembangkannya menjadi satu entri per situs, sehingga Anda hanya perlu menyusun array postMessage secara manual dalam cURL.

Publikasikan acara

POST /posts

Acara ditampilkan sebagai kartu bertanggal. Jadwal acara itu sendiri berada dalam postContextInfo. Objek postScheduledDates yang terpisah mengatur kapan postingan itu sendiri muncul dan kedaluwarsa, yang biasanya merupakan periode menjelang acara. Google menolak acara tanpa judul, dan kedua SDK memunculkan kesalahan validasi sebelum mengirim jika title tidak disertakan.

Parameter

NamaLetakWajibCatatan
input.postTypebodyYaEVENT di sini.
input.postContextInfo.titlebodyYa, dalam praktiknyaJudul acara. Google menolak acara tanpa judul.
input.postContextInfo.startDay, endDaybodyTidakTanggal, YYYY-MM-DD.
input.postContextInfo.startTime, endTimebodyTidakString tampilan seperti 10:00am.
input.postScheduledDatesbodyTidakObjek dengan startDatetime, endDatetime, removalSites.

Semua yang tercantum dalam tabel pengumuman juga berlaku.

Event
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "Summer Sale Kickoff Event",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],    "postType": "EVENT",    "postSites": ["GOOGLE"],    "postContextInfo": {      "title": "Summer Sale Kickoff",      "startDay": "2026-07-15",      "startTime": "10:00am",      "endDay": "2026-07-15",      "endTime": "06:00pm"    },    "postMessage": [      { "site": "GOOGLE", "message": "Join us for the Summer Sale kickoff, refreshments and up to 40 percent off in store." }    ]  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "socialPost": {        "id": "U29jaWFsUG9zdDo0NDEyMw==",        "status": "INPROGRESS",        "type": "EVENT",        "scheduledStartDate": "2026-07-15",        "scheduledEndDate": "2026-07-15",        "contextInfo": {          "title": "Summer Sale Kickoff",          "startDay": "2026-07-15",          "startTime": "10:00am",          "endDay": "2026-07-15",          "endTime": "06:00pm"        }      }    }  }}

contextInfo yang dikembalikan adalah rentang waktu acara. scheduledStartDate dan scheduledEndDate menjelaskan jadwal postingan itu sendiri, yang di sini sesuai dengan tanggal acara karena tidak ada postScheduledDates yang dikirim.

Publikasikan penawaran

POST /posts

Penawaran adalah kartu promosi yang memuat kode kupon, diskon, tautan penukaran, dan syarat serta ketentuan. Semua itu dimasukkan ke dalam postContextInfo, sedangkan startDay bersama endDay membatasi masa berlaku penawaran, bukan masa berlaku postingan.

Parameter

NamaLetakWajibCatatan
input.postTypebodyYaOFFER di sini.
input.postContextInfo.titlebodyYa, dalam praktiknyaMemberi label pada penawaran. Kedua SDK mewajibkannya.
input.postContextInfo.couponCodebodyTidakKode yang ditukarkan pelanggan.
input.postContextInfo.discountbodyTidakTeks bebas seperti 25%.
input.postContextInfo.redeemUrlbodyTidakTempat penawaran ditukarkan.
input.postContextInfo.termsConditionsbodyTidakRincian syarat dan ketentuan.
input.postContextInfo.startDay, endDaybodyTidakMasa berlaku, YYYY-MM-DD.
Offer
curl -X POST https://listingsapi.com/api/v4/posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "Festive 25 Percent Off",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],    "postType": "OFFER",    "postSites": ["GOOGLE"],    "postContextInfo": {      "title": "25% off storewide",      "couponCode": "FESTIVE25",      "discount": "25%",      "redeemUrl": "https://jennyhome.example/festive",      "termsConditions": "Valid in-store only through July 6.",      "startDay": "2026-06-22",      "endDay": "2026-07-06"    },    "postMessage": [      { "site": "GOOGLE", "message": "Celebrate with us, 25 percent off everything in store this week." }    ],    "postCta": [      { "site": "GOOGLE", "type": "GET_OFFER", "url": "https://jennyhome.example/festive" }    ]  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "socialPost": {        "id": "U29jaWFsUG9zdDo0NDEyNA==",        "status": "INPROGRESS",        "type": "OFFER",        "contextInfo": {          "title": "25% off storewide",          "couponCode": "FESTIVE25",          "discount": "25%",          "startDay": "2026-06-22",          "endDay": "2026-07-06"        }      }    }  }}

Google menerima ORDER dan Facebook menerima GET_OFFER untuk tombol penawaran. Jika promosi berakhir lebih awal, hapus kampanye alih-alih mengeditnya.

Baca satu postingan dan statusnya

GET /posts/{postId}

Mengembalikan hasil publikasi kampanye yang telah diterima. Responsnya memuat konten kampanye, satu entri publishDetails per situs, penghitung interaksi, dan tautan aktif setelah publikasi berhasil, di dalam data.socialPostView.

Parameter

NamaLetakWajibCatatan
postIdpathYaID postingan dalam format Base64 dari respons pembuatan atau dari daftar.
Get a post
curl https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "socialPostView": {      "socialPostId": "U29jaWFsUG9zdDo0NDEyMg==",      "socialPostInfo": {        "status": "SUCCESS",        "type": "ANNOUNCEMENT",        "views": 128,        "clicks": 14,        "publishDetails": [          { "site": "GOOGLE", "status": "PUBLISHED", "publishedDate": "2026-06-28", "submissionError": null }        ],        "postLinks": [          { "site": "GOOGLE", "link": "https://www.google.com/maps/place/?post=44122" }        ]      },      "publishedLocationsCount": 1,      "socialPostAnalyticsBySite": [        { "site": "GOOGLE", "views": 128, "clicks": 14, "reactions": 3, "shares": 0, "comments": 1 }      ]    }  }}

Ada dua field status yang penting, dan keduanya menjawab pertanyaan yang berbeda.

FieldNilaiArti
socialPostInfo.statusINPROGRESSDiterima, publikasi masih berlangsung.
SUCCESSPublikasi selesai. Baca publishDetails untuk hasil per situs.
SCHEDULEDMenunggu rentang waktu postScheduledDates dimulai.
EXPIREDRentang waktu yang dijadwalkan telah berakhir dan postingan tidak lagi tayang.
publishDetails[].statusPUBLISHINGSitus tersebut belum memberikan respons.
PUBLISHEDTayang di situs tersebut. Lihat URL-nya di postLinks.
ERRORSitus tersebut menolaknya. submissionError menjelaskan alasannya.

Kampanye dapat berstatus SUCCESS sementara satu situs di dalamnya berstatus ERROR, jadi selalu periksa publishDetails alih-alih hanya status tingkat teratas.

Tampilkan daftar postingan di satu lokasi

GET /locations/{locationId}/posts

Riwayat dengan paginasi berbasis offset untuk setiap kampanye yang mencakup satu lokasi, di dalam data.postsByLocation. Gunakan riwayat ini untuk mengaudit apa yang sudah tayang sebelum menjadwalkan sesuatu yang baru.

Parameter

NamaLetakWajibCatatan
locationIdpathYaID dalam format Base64, diteruskan tanpa perubahan.
pagequeryTidakNomor halaman dimulai dari 1, dengan nilai default 1.
perPagequeryTidakNilai default 10, tidak boleh melebihi 50.
Posts on a location
curl "https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/posts?page=1&perPage=10" \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "postsByLocation": {      "records": [        {          "id": "U29jaWFsUG9zdDo0NDEyMg==",          "name": "Summer Hours Update",          "status": "SUCCESS",          "type": "ANNOUNCEMENT",          "createdAt": "2026-06-28",          "views": 128,          "clicks": 14,          "sites": ["GOOGLE"]        }      ],      "pageInfo": { "totalPages": 1, "hasNextPage": false, "totalRecords": 1 }    }  }}

Rute ini tidak menyediakan filter di sisi server. Rute ini hanya menerima page dan perPage, serta mengabaikan parameter lainnya, jadi baca type dan status pada setiap rekaman lalu lakukan pemfilteran dalam kode Anda sendiri. Untuk pengurutan dan pemfilteran di sisi server, gunakan endpoint daftar massal di bawah.

Hapus postingan

DELETE /posts/{postId}

Penghapusan bersifat permanen dan membatalkan publikasi postingan di setiap situs tempat postingan tersebut telah dipublikasikan. Tidak ada opsi untuk mengurungkan penghapusan maupun endpoint pengeditan, sehingga untuk memperbaiki postingan yang sedang tayang, Anda harus menghapusnya dan memublikasikan penggantinya.

Parameter

NamaLetakWajibCatatan
postIdpathYaID postingan dalam format Base64.
clientMutationIdbodyTidakOpsional, dikembalikan tanpa perubahan untuk keperluan korelasi.
Delete
curl -X DELETE https://listingsapi.com/api/v4/posts/U29jaWFsUG9zdDo0NDEyMg== \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{ "clientMutationId": "delete-44122-req-1" }'
JSON
{  "data": {    "deleteSocialPost": {      "success": true,      "socialPostId": "U29jaWFsUG9zdDo0NDEyMg=="    }  }}

Menghapus postingan yang tidak dikenal atau sudah dihapus akan mengembalikan respons kesalahan dengan data bernilai null, bukan success: false.

Publikasikan satu kampanye di banyak lokasi

POST /bulk-posts

Kontraknya sama dengan POST /posts dan dirancang untuk pengelolaan banyak lokasi: cantumkan setiap lokasi di locationIds dan satu kampanye akan mencakup semuanya. Respons menggunakan kunci createSocialPost, sama seperti POST /posts.

Parameter

NamaLetakWajibCatatan
input.postNamebodyYaNama internal kampanye.
input.locationIdsbodyYaSetiap ID lokasi dalam format base64 yang menjadi tujuan publikasi.
input.postTypebodyYaEVENT, OFFER, dan PRODUCT juga memerlukan postContextInfo atau products.
input.postSitesbodyYaGOOGLE, FACEBOOK, atau keduanya.
input.postScheduledDatesbodyTidakstartDatetime dan endDatetime dalam format ISO 8601. Membuat postingan dengan status SCHEDULED.
input.componentIdentifierbodyTidakReferensi Anda sendiri, berguna sebagai filter nantinya.
Bulk publish
curl -X POST https://listingsapi.com/api/v4/bulk-posts \-H "Authorization: API $LISTINGSAPI_KEY" \-H "Content-Type: application/json" \-d '{  "input": {    "postName": "July Reopening Announcement",    "locationIds": ["TG9jYXRpb246MTgwMDI4OQ==", "TG9jYXRpb246MTgwMDI5MA=="],    "postType": "ANNOUNCEMENT",    "postSites": ["GOOGLE", "FACEBOOK"],    "postMessage": [      { "site": "GOOGLE", "message": "We are back. Visit us this week for our summer menu." },      { "site": "FACEBOOK", "message": "We are back. Swing by for the new summer menu." }    ],    "postScheduledDates": {      "startDatetime": "2026-07-10T09:00:00Z",      "endDatetime": "2026-07-24T23:59:00Z"    }  }}'
JSON
{  "data": {    "createSocialPost": {      "success": true,      "errors": null,      "socialPost": {        "id": "U29jaWFsUG9zdDo5OTIwMQ==",        "name": "July Reopening Announcement",        "status": "SCHEDULED",        "type": "ANNOUNCEMENT",        "scheduledStartDate": "2026-07-10",        "scheduledEndDate": "2026-07-24",        "sites": ["GOOGLE", "FACEBOOK"],        "locationIds": [1800289, 1800290]      }    }  }}

Fungsi pembantu pada kedua SDK menetapkan Google dan Facebook sebagai nilai default sites, mengembangkan pemetaan pesan per situs untuk Anda, dan mengodekan ID lokasi numerik, sehingga publikasi massal biasanya menjadi pemanggilan paling singkat di kedua SDK.

Baca satu kampanye massal

GET /bulk-posts/{postId}

Versi massal dari GET /posts/{postId}. Endpoint ini mengembalikan struktur yang sama, dengan publishedLocationsCount lebih dari satu dan perincian analitik per toko di socialPostAnalyticsByLocationId.

Parameter

NamaDiWajibCatatan
postIdpathYaID postingan massal dalam Base64, bukan bilangan bulat mentah.
Get a bulk post
curl https://listingsapi.com/api/v4/bulk-posts/U29jaWFsUG9zdDo1MTA4OA== \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "socialPostView": {      "socialPostId": "U29jaWFsUG9zdDo1MTA4OA==",      "socialPostInfo": {        "name": "Festive Offer - All Stores",        "status": "SUCCESS",        "type": "OFFER",        "views": 4210,        "clicks": 318,        "sites": ["GOOGLE", "FACEBOOK"]      },      "socialPostAnalyticsByLocationId": [        {          "locationId": 1800289,          "siteStats": [            { "site": "GOOGLE", "status": "PUBLISHED", "views": 1040, "clicks": 80 },            { "site": "FACEBOOK", "status": "PUBLISHED", "views": 360, "clicks": 26 }          ]        }      ]    }  }}

socialPostAnalyticsBySite menjumlahkan hasil kampanye di seluruh toko, sedangkan socialPostAnalyticsByLocationId memerinci angka yang sama per toko. Periksa nilai status per toko untuk menemukan lokasi yang mengalami kegagalan pada salah satu situs.

Tampilkan daftar kampanye massal pada suatu lokasi

GET /locations/{locationId}/bulk-posts

Menggunakan paginasi berbasis offset di bawah data.rollupSocialPosts. Berbeda dengan daftar per lokasi, rute ini menerima filter dan pengurutan, sehingga menjadi endpoint yang tepat untuk dasbor kampanye.

Parameter

NamaDiWajibCatatan
locationIdpathYaID Base64, diteruskan tanpa perubahan.
page, perPagequeryTidakPaginasi berbasis offset.
filtersqueryTidakDienkode sebagai JSON, berdasarkan type, status, creationDateRange atau siteUrls.
sortFieldsqueryTidakDienkode sebagai JSON, misalnya field created_at dengan urutan Descending.
locationIdsqueryTidakArray ID lokasi tambahan yang akan disertakan, dienkode sebagai JSON.
componentIdentifierqueryTidakMembatasi hasil pada kampanye yang dibuat oleh integrasi Anda.

Field yang dapat digunakan untuk pengurutan adalah name, type, status, created_at, schedule_start_date, schedule_end_date, client_name, clicks, views dan shares.

Bulk posts on a location
curl -G https://listingsapi.com/api/v4/locations/TG9jYXRpb246MTgwMDI4OQ==/bulk-posts \-H "Authorization: API $LISTINGSAPI_KEY" \--data-urlencode 'page=1' \--data-urlencode 'perPage=10' \--data-urlencode 'sortFields={"field":"created_at","order":"Descending"}'
JSON
{  "data": {    "rollupSocialPosts": {      "records": [        {          "id": "U29jaWFsUG9zdDo1MTA4OA==",          "name": "Festive Offer - All Stores",          "status": "SUCCESS",          "type": "OFFER",          "createdAt": "2026-06-20",          "views": 4210,          "clicks": 318        }      ],      "pageInfo": { "totalPages": 1, "hasNextPage": false, "totalRecords": 1 }    }  }}

Kedua SDK mengenkode objek filters dan sortFields sebagai JSON untuk Anda, jadi teruskan keduanya sebagai dictionary atau objek bawaan.

Kesalahan yang akan Anda temui

Kode atau statusArtiPerbaikan
400 tidak memiliki variabel $inputBody tidak dibungkus dalam input.Tempatkan setiap field di bawah satu key input.
SY90016 sebagai HTTP 400Kunci Read digunakan untuk operasi pembuatan atau penghapusan.Gunakan kunci Write.
401Kunci tidak ada atau tidak valid.Kirim Authorization: API <YOUR_API_KEY>.
429 dengan Retry-AfterTerlalu banyak panggilan, sering kali akibat pemeriksaan status postingan secara berkala.Tunggu selama jumlah detik yang dinyatakan. Lihat Batas laju.
200 dengan success: falseValidasi gagal.Baca errors di data.createSocialPost.
per_page must not exceed 50perPage melebihi batas pada daftar lokasi.Minta 50 atau kurang.
tag is not a supported parameter for this querytag dikirim ke rute postingan per lokasi.Kirim hanya page dan perPage.

Daftar lengkap tersedia di Kode kesalahan.

Langkah berikutnya